[OpenLayers-Commits] r11854 - in sandbox/cmoullet/openlayers: .
build examples lib/OpenLayers lib/OpenLayers/Control
lib/OpenLayers/Format/Filter lib/OpenLayers/Handler
lib/OpenLayers/Layer lib/OpenLayers/Renderer tests/Control
tests/Renderer
commits-20090109 at openlayers.org
commits-20090109 at openlayers.org
Fri Apr 1 15:54:39 EDT 2011
Author: cmoullet
Date: 2011-04-01 12:54:37 -0700 (Fri, 01 Apr 2011)
New Revision: 11854
Added:
sandbox/cmoullet/openlayers/examples/canvas-hit-detection.html
sandbox/cmoullet/openlayers/examples/canvas-hit-detection.js
sandbox/cmoullet/openlayers/examples/canvas-inspector.html
sandbox/cmoullet/openlayers/examples/canvas-inspector.js
Modified:
sandbox/cmoullet/openlayers/
sandbox/cmoullet/openlayers/build/mobile.cfg
sandbox/cmoullet/openlayers/examples/mobile-base.js
sandbox/cmoullet/openlayers/examples/mobile-jq.js
sandbox/cmoullet/openlayers/examples/mobile-layers.html
sandbox/cmoullet/openlayers/examples/mobile-layers.js
sandbox/cmoullet/openlayers/examples/mobile-sencha.html
sandbox/cmoullet/openlayers/lib/OpenLayers/Control/DragFeature.js
sandbox/cmoullet/openlayers/lib/OpenLayers/Format/Filter/v1.js
sandbox/cmoullet/openlayers/lib/OpenLayers/Handler/Path.js
sandbox/cmoullet/openlayers/lib/OpenLayers/Handler/Point.js
sandbox/cmoullet/openlayers/lib/OpenLayers/Layer/Vector.js
sandbox/cmoullet/openlayers/lib/OpenLayers/Map.js
sandbox/cmoullet/openlayers/lib/OpenLayers/Renderer.js
sandbox/cmoullet/openlayers/lib/OpenLayers/Renderer/Canvas.js
sandbox/cmoullet/openlayers/tests/Control/DragFeature.html
sandbox/cmoullet/openlayers/tests/Renderer/Canvas.html
Log:
Merge with trunk
Property changes on: sandbox/cmoullet/openlayers
___________________________________________________________________
Modified: svn:mergeinfo
- /sandbox/roberthl/openlayers:9745-9748
/trunk/openlayers:11161-11775,11777-11842
+ /sandbox/roberthl/openlayers:9745-9748
/trunk/openlayers:11161-11775,11777-11853
Modified: sandbox/cmoullet/openlayers/build/mobile.cfg
===================================================================
--- sandbox/cmoullet/openlayers/build/mobile.cfg 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/build/mobile.cfg 2011-04-01 19:54:37 UTC (rev 11854)
@@ -9,6 +9,7 @@
OpenLayers/Layer/SphericalMercator.js
OpenLayers/Layer/XYZ.js
OpenLayers/Layer/Bing.js
+OpenLayers/Layer/WMS.js
OpenLayers/Control/TouchNavigation.js
OpenLayers/Control/Geolocate.js
OpenLayers/Control/ZoomPanel.js
@@ -24,6 +25,11 @@
OpenLayers/Renderer/SVG.js
OpenLayers/Renderer/Canvas.js
OpenLayers/Format/GeoJSON.js
+OpenLayers/Format/KML.js
+OpenLayers/Protocol/HTTP.js
+OpenLayers/Protocol/WFS.js
+OpenLayers/Protocol/WFS/v1_0_0.js
+OpenLayers/Strategy/Fixed.js
[exclude]
Copied: sandbox/cmoullet/openlayers/examples/canvas-hit-detection.html (from rev 11853, trunk/openlayers/examples/canvas-hit-detection.html)
===================================================================
--- sandbox/cmoullet/openlayers/examples/canvas-hit-detection.html (rev 0)
+++ sandbox/cmoullet/openlayers/examples/canvas-hit-detection.html 2011-04-01 19:54:37 UTC (rev 11854)
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>OpenLayers Canvas Hit Detection Example</title>
+ <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+ <link rel="stylesheet" href="../theme/default/google.css" type="text/css">
+ <link rel="stylesheet" href="style.css" type="text/css">
+ <script src="../lib/OpenLayers.js"></script>
+ </head>
+ <body>
+ <h1 id="title">Feature Hit Detection with Canvas</h1>
+ <p id="shortdesc">
+ Demonstrates detection of feature hits with the canvas renderer.
+ </p>
+ <div id="map" class="smallmap"></div>
+ <div id="docs">
+ <p>
+ View the <a href="canvas-hit-detection.js" target="_blank">canvas-hit-detection.js</a>
+ source to see how this is done.
+ </p>
+ </div>
+ <script src="canvas-hit-detection.js"></script>
+ </body>
+</html>
Copied: sandbox/cmoullet/openlayers/examples/canvas-hit-detection.js (from rev 11853, trunk/openlayers/examples/canvas-hit-detection.js)
===================================================================
--- sandbox/cmoullet/openlayers/examples/canvas-hit-detection.js (rev 0)
+++ sandbox/cmoullet/openlayers/examples/canvas-hit-detection.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -0,0 +1,88 @@
+
+// create some sample features
+var Feature = OpenLayers.Feature.Vector;
+var Geometry = OpenLayers.Geometry;
+var features = [
+ new Feature(new Geometry.Point(-90, 45)),
+ new Feature(
+ new Geometry.Point(0, 45),
+ {cls: "one"}
+ ),
+ new Feature(
+ new Geometry.Point(90, 45),
+ {cls: "two"}
+ ),
+ new Feature(
+ Geometry.fromWKT("LINESTRING(-110 -60, -80 -40, -50 -60, -20 -40)")
+ ),
+ new Feature(
+ Geometry.fromWKT("POLYGON((20 -20, 110 -20, 110 -80, 20 -80, 20 -20), (40 -40, 90 -40, 90 -60, 40 -60, 40 -40))")
+ )
+];
+
+// create rule based styles
+var Rule = OpenLayers.Rule;
+var Filter = OpenLayers.Filter;
+var style = new OpenLayers.Style({
+ pointRadius: 10,
+ strokeWidth: 2,
+ strokeOpacity: 0.7,
+ strokeColor: "navy",
+ fillColor: "#ffcc66",
+ fillOpacity: 1
+}, {
+ rules: [
+ new Rule({
+ filter: new Filter.Comparison({
+ type: "==",
+ property: "cls",
+ value: "one"
+ }),
+ symbolizer: {
+ externalGraphic: "../img/marker-blue.png"
+ }
+ }),
+ new Rule({
+ filter: new Filter.Comparison({
+ type: "==",
+ property: "cls",
+ value: "two"
+ }),
+ symbolizer: {
+ externalGraphic: "../img/marker-green.png"
+ }
+ }),
+ new Rule({
+ elseFilter: true,
+ symbolizer: {
+ graphicName: "circle"
+ }
+ })
+ ]
+});
+
+var layer = new OpenLayers.Layer.Vector(null, {
+ styleMap: new OpenLayers.StyleMap({
+ "default": style,
+ select: {
+ fillColor: "red",
+ pointRadius: 13,
+ strokeColor: "yellow",
+ strokeWidth: 3
+ }
+ }),
+ isBaseLayer: true,
+ renderers: ["Canvas"]
+});
+layer.addFeatures(features);
+
+var map = new OpenLayers.Map({
+ div: "map",
+ layers: [layer],
+ center: new OpenLayers.LonLat(0, 0),
+ zoom: 0
+});
+
+var select = new OpenLayers.Control.SelectFeature(layer, {hover: true});
+map.addControl(select);
+select.activate();
Copied: sandbox/cmoullet/openlayers/examples/canvas-inspector.html (from rev 11853, trunk/openlayers/examples/canvas-inspector.html)
===================================================================
--- sandbox/cmoullet/openlayers/examples/canvas-inspector.html (rev 0)
+++ sandbox/cmoullet/openlayers/examples/canvas-inspector.html 2011-04-01 19:54:37 UTC (rev 11854)
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>OpenLayers Canvas Inspector</title>
+ <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+ <link rel="stylesheet" href="../theme/default/google.css" type="text/css">
+ <link rel="stylesheet" href="style.css" type="text/css">
+ <script src="../lib/OpenLayers.js"></script>
+ <script src="Jugl.js"></script>
+ <style>
+ #template {
+ display: none;
+ }
+ #inspector table {
+ border-right: 1px solid #666;
+ border-bottom: 1px solid #666;
+ }
+ #inspector table td {
+ font-size: 9px;
+ text-align: center;
+ width: 60px;
+ height: 60px;
+ border-top: 1px solid #666;
+ border-left: 1px solid #666;
+ }
+ </style>
+ </head>
+ <body>
+ <h1 id="title">Canvas Inspector</h1>
+ <p id="shortdesc">
+ Displays pixel values for canvas context.
+ </p>
+ <div id="map" class="smallmap"></div>
+ <div id="docs">
+ <p>
+ View the <a href="canvas-inspector.js" target="_blank">canvas-inspector.js</a>
+ source to see how this is done.
+ </p>
+ </div>
+ <div id="inspector">
+ </div>
+ <table id="template">
+ <tr jugl:repeat="row new Array(rows)">
+ <td jugl:repeat="col new Array(cols)"
+ jugl:attributes="id 'c' + repeat.col.index + 'r' + repeat.row.index">
+
+ </td>
+ </tr>
+ </table>
+ <script src="canvas-inspector.js"></script>
+ </body>
+</html>
Copied: sandbox/cmoullet/openlayers/examples/canvas-inspector.js (from rev 11853, trunk/openlayers/examples/canvas-inspector.js)
===================================================================
--- sandbox/cmoullet/openlayers/examples/canvas-inspector.js (rev 0)
+++ sandbox/cmoullet/openlayers/examples/canvas-inspector.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -0,0 +1,91 @@
+
+var features = [
+
+ new OpenLayers.Feature.Vector(
+ OpenLayers.Geometry.fromWKT(
+ "LINESTRING(-90 90, 90 -90)"
+ ),
+ {color: "#0f0000"}
+ ),
+
+ new OpenLayers.Feature.Vector(
+ OpenLayers.Geometry.fromWKT(
+ "LINESTRING(100 50, -100 -50)"
+ ),
+ {color: "#00ff00"}
+ )
+
+];
+
+var layer = new OpenLayers.Layer.Vector(null, {
+ styleMap: new OpenLayers.StyleMap({
+ strokeWidth: 3,
+ strokeColor: "${color}"
+ }),
+ isBaseLayer: true,
+ renderers: ["Canvas"],
+ rendererOptions: {hitDetection: true}
+});
+layer.addFeatures(features);
+
+var map = new OpenLayers.Map({
+ div: "map",
+ layers: [layer],
+ center: new OpenLayers.LonLat(0, 0),
+ zoom: 0
+});
+
+var xOff = 2, yOff = 2;
+
+var rows = 1 + (2 * yOff);
+var cols = 1 + (2 * xOff);
+
+var template = new jugl.Template("template");
+template.process({
+ clone: true,
+ parent: "inspector",
+ context: {
+ rows: rows,
+ cols: cols
+ }
+});
+
+function isDark(r, g, b, a) {
+ a = a / 255;
+ var da = 1 - a;
+ // convert color values to decimal (assume white background)
+ r = (a * r / 255) + da;
+ g = (a * g / 255) + da;
+ b = (a * b / 255) + da;
+ // use w3C brightness measure
+ var brightness = (r * 0.299) + (g * 0.587) + (b * 0.144);
+ return brightness < 0.5;
+}
+
+var context = layer.renderer.canvas; //layer.renderer.hitContext;
+var size = map.getSize();
+map.events.on({
+ mousemove: function(event) {
+ var x = event.xy.x - 1; // TODO: fix this elsewhere
+ var y = event.xy.y;
+ if ((x >= xOff) && (x < size.w - xOff) && (y >= yOff) && (y < size.h - yOff)) {
+ var data = context.getImageData(x - xOff, y - yOff, rows, cols).data;
+ var offset, red, green, blue, alpha, cell;
+ for (var i=0; i<cols; ++i) {
+ for (var j=0; j<rows; ++j) {
+ offset = (i * 4) + (j * 4 * cols);
+ red = data[offset];
+ green = data[offset + 1];
+ blue = data[offset + 2];
+ alpha = data[offset + 3];
+ cell = document.getElementById("c" + i + "r" + j);
+ cell.innerHTML = "R: " + red + "<br>G: " + green + "<br>B: " + blue + "<br>A: " + alpha;
+ cell.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + (alpha / 255) + ")";
+ cell.style.color = isDark(red, green, blue, alpha) ? "#ffffff" : "#000000";
+ }
+ }
+ }
+ }
+});
+
+
Modified: sandbox/cmoullet/openlayers/examples/mobile-base.js
===================================================================
--- sandbox/cmoullet/openlayers/examples/mobile-base.js 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/examples/mobile-base.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -7,11 +7,11 @@
var gg = new OpenLayers.Projection("EPSG:4326");
var sm = new OpenLayers.Projection("EPSG:900913");
-var init = function () {
+var init = function (onSelectFeatureFunction) {
var vector = new OpenLayers.Layer.Vector("Vector Layer", {});
- sprintersLayer = new OpenLayers.Layer.Vector("Sprinters", {
+ var sprintersLayer = new OpenLayers.Layer.Vector("Sprinters", {
styleMap: new OpenLayers.StyleMap({
externalGraphic: "img/mobile-loc.png",
graphicOpacity: 1.0,
@@ -113,15 +113,15 @@
}
),
new OpenLayers.Feature.Vector(
- OpenLayers.Geometry.Polygon.createRegularPolygon(
- new OpenLayers.Geometry.Point(e.point.x, e.point.y),
- e.position.coords.accuracy / 2,
- 50,
- 0
- ),
- {},
- style
- )
+ OpenLayers.Geometry.Polygon.createRegularPolygon(
+ new OpenLayers.Geometry.Point(e.point.x, e.point.y),
+ e.position.coords.accuracy / 2,
+ 50,
+ 0
+ ),
+ {},
+ style
+ )
]);
map.zoomToExtent(vector.getDataExtent());
});
Modified: sandbox/cmoullet/openlayers/examples/mobile-jq.js
===================================================================
--- sandbox/cmoullet/openlayers/examples/mobile-jq.js 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/examples/mobile-jq.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -27,7 +27,10 @@
map.updateSize();
} else {
// initialize map
- init();
+ init(function(feature) {
+ selectedFeature = feature;
+ $.mobile.changePage($("#popup"), "pop");
+ });
}
}
$(window).bind("orientationchange resize pageshow", fixContentHeight);
@@ -49,7 +52,6 @@
control.activate();
}
});
-
$('div#popup').live('pageshow',function(event, ui){
var li = "";
@@ -150,4 +152,4 @@
$(item).toggleClass('checked');
}
});
-}
\ No newline at end of file
+}
Modified: sandbox/cmoullet/openlayers/examples/mobile-layers.html
===================================================================
--- sandbox/cmoullet/openlayers/examples/mobile-layers.html 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/examples/mobile-layers.html 2011-04-01 19:54:37 UTC (rev 11854)
@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0;">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="stylesheet" href="style.mobile.css" type="text/css">
- <script src="../lib/OpenLayers.js"></script>
+ <script src="../lib/OpenLayers.js?mobile"></script>
<script src="mobile-layers.js"></script>
<style>
html, body {
@@ -87,7 +87,7 @@
mobile, WMS, WFS, KML
</div>
<p id="shortdesc">
- A mobile example displaying various layer types: WMS, WFS, KML
+ A mobile example displaying various layer types: WMS, WFS, KML.
</p>
<div id="map"></div>
Modified: sandbox/cmoullet/openlayers/examples/mobile-layers.js
===================================================================
--- sandbox/cmoullet/openlayers/examples/mobile-layers.js 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/examples/mobile-layers.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -14,11 +14,14 @@
setTimeout(fixSize, 700);
setTimeout(fixSize, 1500);
+// allow testing of specific renderers via "?renderer=Canvas", etc
+var renderer = OpenLayers.Util.getParameters(window.location.href).renderer;
+renderer = (renderer) ? [renderer] : OpenLayers.Layer.Vector.prototype.renderers;
+
OpenLayers.ProxyHost = "proxy.cgi?url=";
-var init = function () {
+function init() {
- // create map
map = new OpenLayers.Map({
div: "map",
theme: null,
@@ -31,18 +34,16 @@
}
}),
new OpenLayers.Control.ZoomPanel()
- ],
- layers: [
- new OpenLayers.Layer.WMS("OpenLayers WMS",
- "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'}, {isBaseLayer: true, transitionEffect: 'resize'})
]
});
- // allow testing of specific renderers via "?renderer=Canvas", etc
- var renderer = OpenLayers.Util.getParameters(window.location.href).renderer;
- renderer = (renderer) ? [renderer] : OpenLayers.Layer.Vector.prototype.renderers;
+ var wms = new OpenLayers.Layer.WMS("OpenLayers WMS",
+ "http://vmap0.tiles.osgeo.org/wms/vmap0",
+ {layers: 'basic'},
+ {isBaseLayer: true, transitionEffect: 'resize'}
+ )
- var sundials = new OpenLayers.Layer.Vector("KML", {
+ var kml = new OpenLayers.Layer.Vector("KML", {
projection: map.displayProjection,
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP({
@@ -65,6 +66,7 @@
renderers: renderer
});
- map.addLayers([wfs, sundials]);
- map.zoomToMaxExtent();
+ map.addLayers([wms, wfs, kml]);
+
+ map.setCenter(new OpenLayers.LonLat(-104, 42), 3);
};
Modified: sandbox/cmoullet/openlayers/examples/mobile-sencha.html
===================================================================
--- sandbox/cmoullet/openlayers/examples/mobile-sencha.html 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/examples/mobile-sencha.html 2011-04-01 19:54:37 UTC (rev 11854)
@@ -1,162 +1,77 @@
<!DOCTYPE html>
<html>
-<head>
- <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
- <meta name="apple-mobile-web-app-capable" content="yes"/>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <title>OpenLayers with Sencha Touch</title>
- <script src="../lib/OpenLayers.js?mobile"></script>
- <link rel="stylesheet" href="style.mobile.css" type="text/css">
- <link rel="stylesheet" href="http://dev.sencha.com/deploy/touch/resources/css/sencha-touch.css">
- <script src="http://dev.sencha.com/deploy/touch/sencha-touch.js"></script>
- <script src="mobile-sencha.js"></script>
- <script src="mobile-base.js"></script>
- <style>
- .searchList {
- min-height: 150px;
- }
+ <head>
+ <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
+ <meta name="apple-mobile-web-app-capable" content="yes"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>OpenLayers with Sencha Touch</title>
+ <script src="../lib/OpenLayers.js?mobile"></script>
+ <link rel="stylesheet" href="style.mobile.css" type="text/css">
+ <link rel="stylesheet" href="http://dev.sencha.com/deploy/touch/resources/css/sencha-touch.css">
+ <script src="http://dev.sencha.com/deploy/touch/sencha-touch.js"></script>
+ <script src="mobile-sencha.js"></script>
+ <script src="mobile-base.js"></script>
+ <style>
+ .searchList {
+ min-height: 150px;
+ }
- .close-btn {
- position: absolute;
- right: 10px;
- top: 10px;
- }
+ .close-btn {
+ position: absolute;
+ right: 10px;
+ top: 10px;
+ }
- img.minus {
- -webkit-mask-image: url(img/minus1.png);
- }
+ img.minus {
+ -webkit-mask-image: url(img/minus1.png);
+ }
- img.layers {
- -webkit-mask-image: url(img/list.png);
- }
+ img.layers {
+ -webkit-mask-image: url(img/list.png);
+ }
- .gx-layer-item {
- margin-left: 10px;
- }
+ .gx-layer-item {
+ margin-left: 10px;
+ }
- #map {
- width: 100%;
- height: 100%;
- }
+ #map {
+ width: 100%;
+ height: 100%;
+ }
- .olControlAttribution {
- font-size: 10px;
- bottom: 5px;
- right: 5px;
- }
+ .olControlAttribution {
+ font-size: 10px;
+ bottom: 5px;
+ right: 5px;
+ }
- #title, #tags, #shortdesc {
- display: none;
- }
- </style>
- <script>
-
- var featurePopup;
- var sprintersLayer;
-
- var onSelectFeatureFunction = function(feature) {
- var htmlContent = "";
- for (var property in feature.data) {
- if (feature.data[property] != 'undefined') {
- htmlContent = htmlContent + feature.data[property] + "<br>";
- }
+ #title, #tags, #shortdesc {
+ display: none;
}
- if (featurePopup) {
- featurePopup.destroy();
- }
- featurePopup = new Ext.Panel({
- floating: true,
- modal: true,
- centered: true,
- hideOnMaskTap: true,
- width: 240,
- html: htmlContent,
- scroll: 'vertical'
- });
- featurePopup.show();
- };
+ </style>
+ <script>
var app = new Ext.Application({
name: "ol",
launch: function() {
this.viewport = new Ext.Panel({
fullscreen: true,
- dockedItems: [
- {
- dock: "bottom",
- xtype: "toolbar",
- ui: "light",
- layout: {
- pack: "center"
- },
- items: [
- {
- iconCls: "search",
- iconMask: true,
- handler: function() {
- // this is the app
- if (!app.searchFormPopupPanel) {
- app.searchFormPopupPanel = new App.SearchFormPopupPanel({
- map: map
- });
- }
- app.searchFormPopupPanel.show('pop');
- }
- },
- {
- iconCls: "locate",
- iconMask: true,
- handler: function() {
- var geolocate = map.getControlsBy("id", "locate-control")[0];
- if (geolocate.active) {
- geolocate.getCurrentLocation();
- } else {
- geolocate.activate();
- }
- }
- },
- {
- xtype: "spacer"
- },
- {
- iconMask: true,
- iconCls: "add",
- handler: function() {
- map.zoomIn();
- }
- },
- {
- iconMask: true,
- iconCls: "minus",
- handler: function() {
- map.zoomOut();
- }
- },
- {
- xtype: "spacer"
- },
- {
- iconMask: true,
- iconCls: "layers",
- handler: function() {
- if (!app.popup) {
- app.popup = new Ext.Panel({
- floating: true,
- modal: true,
- centered: true,
- hideOnMaskTap: true,
- width: 240,
- items: [
- {
- xtype: 'app_layerlist',
- map: map
- }
- ],
- scroll: 'vertical'
- });
- }
- app.popup.show('pop');
- }
+ dockedItems: [{
+ dock: "bottom",
+ xtype: "toolbar",
+ ui: "light",
+ layout: {
+ pack: "center"
+ },
+ items: [{
+ iconCls: "search",
+ iconMask: true,
+ handler: function() {
+ // this is the app
+ if (!app.searchFormPopupPanel) {
+ app.searchFormPopupPanel = new App.SearchFormPopupPanel({
+ map: map
+ });
}
]
}
@@ -168,11 +83,37 @@
monitorResize: true,
id: "map",
listeners: {
- render: init,
+ render: function() {
+ var self = this;
+ init(function(feature) {
+ var htmlContent = "";
+ for (var property in feature.data) {
+ if (feature.data[property] != 'undefined') {
+ htmlContent = htmlContent + feature.data[property] + "<br>";
+ }
+ }
+ if (self.featurePopup) {
+ self.featurePopup.destroy();
+ }
+ self.featurePopup = new Ext.Panel({
+ floating: true,
+ modal: true,
+ centered: true,
+ hideOnMaskTap: true,
+ width: 240,
+ html: htmlContent,
+ scroll: 'vertical'
+ });
+ self.featurePopup.show();
+ })
+ },
resize: function() {
if (window.map) {
map.updateSize();
}
+ },
+ scope: {
+ featurePopup: null
}
}
}
@@ -180,16 +121,16 @@
});
}
});
- </script>
-</head>
-<body>
-<h1 id="title">OpenLayers with Sencha Touch</h1>
+ </script>
+ </head>
+ <body>
+ <h1 id="title">OpenLayers with Sencha Touch</h1>
-<div id="tags">
- mobile, sencha touch
-</div>
-<p id="shortdesc">
- Using Sencha Touch to display an OpenLayers map.
-</p>
-</body>
+ <div id="tags">
+ mobile, sencha touch
+ </div>
+ <p id="shortdesc">
+ Using Sencha Touch to display an OpenLayers map.
+ </p>
+ </body>
</html>
Modified: sandbox/cmoullet/openlayers/lib/OpenLayers/Control/DragFeature.js
===================================================================
--- sandbox/cmoullet/openlayers/lib/OpenLayers/Control/DragFeature.js 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/lib/OpenLayers/Control/DragFeature.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -151,6 +151,10 @@
),
feature: new OpenLayers.Handler.Feature(
this, this.layer, OpenLayers.Util.extend({
+ // 'click' and 'clickout' callback are for the mobile
+ // support: no 'over' or 'out' in touch based browsers.
+ click: this.clickFeature,
+ clickout: this.clickoutFeature,
over: this.overFeature,
out: this.outFeature
}, this.featureCallbacks),
@@ -158,8 +162,35 @@
)
};
},
-
+
/**
+ * Method: clickFeature
+ * Called when the feature handler detects a click-in on a feature.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ clickFeature: function(feature) {
+ if (this.overFeature(feature)) {
+ this.handlers.drag.dragstart(this.handlers.feature.evt);
+ // to let the events propagate to the feature handler (click callback)
+ this.handlers.drag.stopDown = false;
+ }
+ },
+
+ /**
+ * Method: clickoutFeature
+ * Called when the feature handler detects a click-out on a feature.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ clickoutFeature: function(feature) {
+ this.outFeature(feature);
+ this.handlers.drag.stopDown = true;
+ },
+
+ /**
* APIMethod: destroy
* Take care of things that are not handled in superclass
*/
@@ -207,11 +238,16 @@
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>} The selected feature.
+ *
+ * Returns:
+ * {Boolean} Successfully activated the drag handler.
*/
overFeature: function(feature) {
+ var activated = false;
if(!this.handlers.drag.dragging) {
this.feature = feature;
this.handlers.drag.activate();
+ activated = true;
this.over = true;
OpenLayers.Element.addClass(this.map.viewPortDiv, this.displayClass + "Over");
this.onEnter(feature);
@@ -222,6 +258,7 @@
this.over = false;
}
}
+ return activated;
},
/**
Modified: sandbox/cmoullet/openlayers/lib/OpenLayers/Format/Filter/v1.js
===================================================================
--- sandbox/cmoullet/openlayers/lib/OpenLayers/Format/Filter/v1.js 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/lib/OpenLayers/Format/Filter/v1.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -5,6 +5,7 @@
/**
* @requires OpenLayers/Format/Filter.js
* @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Filter/Function.js
*/
/**
Modified: sandbox/cmoullet/openlayers/lib/OpenLayers/Handler/Path.js
===================================================================
--- sandbox/cmoullet/openlayers/lib/OpenLayers/Handler/Path.js 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/lib/OpenLayers/Handler/Path.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -262,8 +262,8 @@
},
/**
- * Method: mousedown
- * Handle mouse down. Add a new point to the geometry and
+ * Method: down
+ * Handle mousedown and touchstart. Add a new point to the geometry and
* render it. Return determines whether to propagate the event on the map.
*
* Parameters:
@@ -287,8 +287,8 @@
},
/**
- * Method: mousemove
- * Handle mouse move. Adjust the geometry and redraw.
+ * Method: move
+ * Handle mousemove and touchmove. Adjust the geometry and redraw.
* Return determines whether to propagate the event on the map.
*
* Parameters:
@@ -312,8 +312,8 @@
},
/**
- * Method: mouseup
- * Handle mouse up. Send the latest point in the geometry to
+ * Method: up
+ * Handle mouseup and touchend. Send the latest point in the geometry to
* the control. Return determines whether to propagate the event on the map.
*
* Parameters:
Modified: sandbox/cmoullet/openlayers/lib/OpenLayers/Handler/Point.js
===================================================================
--- sandbox/cmoullet/openlayers/lib/OpenLayers/Handler/Point.js 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/lib/OpenLayers/Handler/Point.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -475,8 +475,8 @@
},
/**
- * Method: mousedown
- * Handle mouse down. Adjust the geometry and redraw.
+ * Method: down
+ * Handle mousedown and touchstart. Adjust the geometry and redraw.
* Return determines whether to propagate the event on the map.
*
* Parameters:
@@ -496,8 +496,8 @@
},
/**
- * Method: mousemove
- * Handle mouse move. Adjust the geometry and redraw.
+ * Method: move
+ * Handle mousemove and touchmove. Adjust the geometry and redraw.
* Return determines whether to propagate the event on the map.
*
* Parameters:
@@ -515,8 +515,8 @@
},
/**
- * Method: mouseup
- * Handle mouse up. Send the latest point in the geometry to the control.
+ * Method: up
+ * Handle mouseup and touchend. Send the latest point in the geometry to the control.
* Return determines whether to propagate the event on the map.
*
* Parameters:
Modified: sandbox/cmoullet/openlayers/lib/OpenLayers/Layer/Vector.js
===================================================================
--- sandbox/cmoullet/openlayers/lib/OpenLayers/Layer/Vector.js 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/lib/OpenLayers/Layer/Vector.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -810,7 +810,9 @@
}
}
- if (!this.renderer.drawFeature(feature, style)) {
+ var drawn = this.renderer.drawFeature(feature, style);
+ //TODO remove the check for null when we get rid of Renderer.SVG
+ if (drawn === false || drawn === null) {
this.unrenderedFeatures[feature.id] = feature;
} else {
delete this.unrenderedFeatures[feature.id];
@@ -843,9 +845,17 @@
if (!this.renderer) {
OpenLayers.Console.error(OpenLayers.i18n("getFeatureError"));
return null;
- }
+ }
+ var feature = null;
var featureId = this.renderer.getFeatureIdFromEvent(evt);
- return this.getFeatureById(featureId);
+ if (featureId) {
+ if (typeof featureId === "string") {
+ feature = this.getFeatureById(featureId);
+ } else {
+ feature = featureId;
+ }
+ }
+ return feature;
},
/**
Modified: sandbox/cmoullet/openlayers/lib/OpenLayers/Map.js
===================================================================
--- sandbox/cmoullet/openlayers/lib/OpenLayers/Map.js 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/lib/OpenLayers/Map.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -1849,7 +1849,7 @@
bounds = this.baseLayer.getExtent();
- for (var i=0, len=this.layers.length; i<len; i++) {
+ for (var i=this.layers.length-1; i>=0; --i) {
var layer = this.layers[i];
if (layer !== this.baseLayer && !layer.isBaseLayer) {
var inRange = layer.calculateInRange();
Modified: sandbox/cmoullet/openlayers/lib/OpenLayers/Renderer/Canvas.js
===================================================================
--- sandbox/cmoullet/openlayers/lib/OpenLayers/Renderer/Canvas.js 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/lib/OpenLayers/Renderer/Canvas.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -15,6 +15,22 @@
* - <OpenLayers.Renderer>
*/
OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, {
+
+ /**
+ * APIProperty: hitDetection
+ * {Boolean} Allow for hit detection of features. Default is true.
+ */
+ hitDetection: true,
+
+ /**
+ * Property: hitOverflow
+ * {Number} The method for converting feature identifiers to color values
+ * supports 16777215 sequential values. Two features cannot be
+ * predictably detected if their identifiers differ by more than this
+ * value. The hitOverflow allows for bigger numbers (but the
+ * difference in values is still limited).
+ */
+ hitOverflow: 0,
/**
* Property: canvas
@@ -32,14 +48,21 @@
* Constructor: OpenLayers.Renderer.Canvas
*
* Parameters:
- * containerID - {<String>}
+ * containerID - {<String>}
+ * options - {Object} Optional properties to be set on the renderer.
*/
- initialize: function(containerID) {
+ initialize: function(containerID, options) {
OpenLayers.Renderer.prototype.initialize.apply(this, arguments);
this.root = document.createElement("canvas");
this.container.appendChild(this.root);
this.canvas = this.root.getContext("2d");
this.features = {};
+ if (this.hitDetection) {
+ this.hitCanvas = document.createElement("canvas");
+ this.hitContext = this.hitCanvas.getContext("2d");
+ this.hitGraphicCanvas = document.createElement("canvas");
+ this.hitGraphicContext = this.hitGraphicCanvas.getContext("2d");
+ }
},
/**
@@ -78,11 +101,24 @@
*/
setSize: function(size) {
this.size = size.clone();
- this.root.style.width = size.w + "px";
- this.root.style.height = size.h + "px";
- this.root.width = size.w;
- this.root.height = size.h;
+ var root = this.root;
+ root.style.width = size.w + "px";
+ root.style.height = size.h + "px";
+ root.width = size.w;
+ root.height = size.h;
this.resolution = null;
+ if (this.hitDetection) {
+ var hitCanvas = this.hitCanvas;
+ hitCanvas.style.width = size.w + "px";
+ hitCanvas.style.height = size.h + "px";
+ hitCanvas.width = size.w;
+ hitCanvas.height = size.h;
+ var hitGraphicCanvas = this.hitGraphicCanvas;
+ hitGraphicCanvas.style.width = size.w + "px";
+ hitGraphicCanvas.style.height = size.h + "px";
+ hitGraphicCanvas.width = size.w;
+ hitGraphicCanvas.height = size.h;
+ }
},
/**
@@ -93,16 +129,25 @@
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
* style - {<Object>}
+ *
+ * Returns:
+ * {Boolean} The feature has been drawn completely. If the feature has no
+ * geometry, undefined will be returned. If the feature is not rendered
+ * for other reasons, false will be returned.
*/
drawFeature: function(feature, style) {
- style = style || feature.style;
- style = this.applyDefaultSymbolizer(style);
-
- this.features[feature.id] = [feature, style];
- this.redraw();
+ var rendered;
+ if (feature.geometry) {
+ style = style || feature.style;
+ style = this.applyDefaultSymbolizer(style);
+
+ this.features[feature.id] = [feature, style];
+ this.redraw();
+ rendered = true;
+ }
+ return rendered;
},
-
/**
* Method: drawGeometry
* Used when looping (in redraw) over the features; draws
@@ -112,29 +157,29 @@
* geometry - {<OpenLayers.Geometry>}
* style - {Object}
*/
- drawGeometry: function(geometry, style) {
+ drawGeometry: function(geometry, style, featureId) {
var className = geometry.CLASS_NAME;
if ((className == "OpenLayers.Geometry.Collection") ||
(className == "OpenLayers.Geometry.MultiPoint") ||
(className == "OpenLayers.Geometry.MultiLineString") ||
(className == "OpenLayers.Geometry.MultiPolygon")) {
for (var i = 0; i < geometry.components.length; i++) {
- this.drawGeometry(geometry.components[i], style);
+ this.drawGeometry(geometry.components[i], style, featureId);
}
return;
}
switch (geometry.CLASS_NAME) {
case "OpenLayers.Geometry.Point":
- this.drawPoint(geometry, style);
+ this.drawPoint(geometry, style, featureId);
break;
case "OpenLayers.Geometry.LineString":
- this.drawLineString(geometry, style);
+ this.drawLineString(geometry, style, featureId);
break;
case "OpenLayers.Geometry.LinearRing":
- this.drawLinearRing(geometry, style);
+ this.drawLinearRing(geometry, style, featureId);
break;
case "OpenLayers.Geometry.Polygon":
- this.drawPolygon(geometry, style);
+ this.drawPolygon(geometry, style, featureId);
break;
default:
break;
@@ -148,37 +193,70 @@
* Parameters:
* geometry - {<OpenLayers.Geometry>}
* style - {Object}
+ * featureId - {String}
*/
- drawExternalGraphic: function(pt, style) {
- var img = new Image();
-
- if(style.graphicTitle) {
- img.title=style.graphicTitle;
- }
+ drawExternalGraphic: function(pt, style, featureId) {
+ var img = new Image();
- var width = style.graphicWidth || style.graphicHeight;
- var height = style.graphicHeight || style.graphicWidth;
- width = width ? width : style.pointRadius*2;
- height = height ? height : style.pointRadius*2;
- var xOffset = (style.graphicXOffset != undefined) ?
+ if (style.graphicTitle) {
+ img.title = style.graphicTitle;
+ }
+
+ var width = style.graphicWidth || style.graphicHeight;
+ var height = style.graphicHeight || style.graphicWidth;
+ width = width ? width : style.pointRadius * 2;
+ height = height ? height : style.pointRadius * 2;
+ var xOffset = (style.graphicXOffset != undefined) ?
style.graphicXOffset : -(0.5 * width);
- var yOffset = (style.graphicYOffset != undefined) ?
+ var yOffset = (style.graphicYOffset != undefined) ?
style.graphicYOffset : -(0.5 * height);
-
- var context = { img: img,
- x: (pt[0]+xOffset),
- y: (pt[1]+yOffset),
- width: width,
- height: height,
- opacity: style.graphicOpacity || style.fillOpacity,
- canvas: this.canvas };
- img.onload = OpenLayers.Function.bind( function() {
- this.canvas.globalAlpha = this.opacity;
- this.canvas.drawImage(this.img, this.x,
- this.y, this.width, this.height);
- }, context);
- img.src = style.externalGraphic;
+ var x = pt[0] + xOffset;
+ var y = pt[1] + yOffset;
+
+ var numRows = this.root.width;
+ var numCols = this.root.height;
+
+ var opacity = style.graphicOpacity || style.fillOpacity;
+
+ var rgb = this.featureIdToRGB(featureId);
+ var red = rgb[0];
+ var green = rgb[1];
+ var blue = rgb[2];
+
+ var onLoad = function() {
+ // TODO: check that we haven't moved
+ var canvas = this.canvas;
+ canvas.globalAlpha = opacity;
+ canvas.drawImage(
+ img, x, y, width, height
+ );
+ if (this.hitDetection) {
+ var hitGraphicContext = this.hitGraphicContext;
+ var hitContext = this.hitContext;
+ hitGraphicContext.clearRect(0, 0, numRows, numCols);
+ hitGraphicContext.drawImage(
+ img, 0, 0, width, height
+ );
+ var imagePixels = hitGraphicContext.getImageData(0, 0, width, height).data;
+ var indexData = hitContext.createImageData(width, height);
+ var indexPixels = indexData.data;
+ var pixelIndex;
+ for (var i=0, len=imagePixels.length; i<len; i+=4) {
+ // look for visible pixels
+ if (imagePixels[i+3] > 0) {
+ indexData[i] = red;
+ indexPixels[i+1] = green;
+ indexPixels[i+2] = blue;
+ indexPixels[i+3] = 255;
+ }
+ }
+ hitContext.putImageData(indexData, x, y);
+ }
+ };
+
+ img.onload = OpenLayers.Function.bind(onLoad, this);
+ img.src = style.externalGraphic;
},
/**
@@ -190,10 +268,10 @@
* style - {Object} Symbolizer hash
*/
setCanvasStyle: function(type, style) {
- if (type == "fill") {
+ if (type === "fill") {
this.canvas.globalAlpha = style['fillOpacity'];
this.canvas.fillStyle = style['fillColor'];
- } else if (type == "stroke") {
+ } else if (type === "stroke") {
this.canvas.globalAlpha = style['strokeOpacity'];
this.canvas.strokeStyle = style['strokeColor'];
this.canvas.lineWidth = style['strokeWidth'];
@@ -202,40 +280,124 @@
this.canvas.lineWidth = 1;
}
},
+
+ /**
+ * Method: featureIdToHex
+ * Convert a feature ID string into an RGB hex string.
+ *
+ * Parameters:
+ * featureId - {String} Feature id
+ *
+ * Returns:
+ * {String} RGB hex string.
+ */
+ featureIdToHex: function(featureId) {
+ var id = Number(featureId.split("_").pop()) + 1; // zero for no feature
+ if (id >= 16777216) {
+ this.hitOverflow = id - 16777215;
+ id = id % 16777216 + 1;
+ }
+ var hex = "000000" + id.toString(16);
+ var len = hex.length;
+ hex = "#" + hex.substring(len-6, len);
+ return hex;
+ },
+
+ /**
+ * Method: featureIdToRGB
+ * Convert a feature ID string into an RGB array.
+ *
+ * Parameters:
+ * featureId - {String} Feature id
+ *
+ * Returns:
+ * {Array} RGB values.
+ */
+ featureIdToRGB: function(featureId) {
+ var hex = this.featureIdToHex(featureId);
+ return [
+ parseInt(hex.substring(1, 3), 16),
+ parseInt(hex.substring(3, 5), 16),
+ parseInt(hex.substring(5, 7), 16)
+ ];
+ },
/**
+ * Method: setHitContextStyle
+ * Prepare the hit canvas for drawing by setting various global settings.
+ *
+ * Parameters:
+ * type - {String} one of 'stroke', 'fill', or 'reset'
+ * featureId - {String} The feature id.
+ * symbolizer - {<OpenLayers.Symbolizer>} The symbolizer.
+ */
+ setHitContextStyle: function(type, featureId, symbolizer) {
+ var hex = this.featureIdToHex(featureId);
+ if (type == "fill") {
+ this.hitContext.globalAlpha = 1.0;
+ this.hitContext.fillStyle = hex;
+ } else if (type == "stroke") {
+ this.hitContext.globalAlpha = 1.0;
+ this.hitContext.strokeStyle = hex;
+ // bump up stroke width to deal with antialiasing
+ this.hitContext.lineWidth = symbolizer.strokeWidth + 2;
+ } else {
+ this.hitContext.globalAlpha = 0;
+ this.hitContext.lineWidth = 1;
+ }
+ },
+
+ /**
* Method: drawPoint
* This method is only called by the renderer itself.
*
* Parameters:
* geometry - {<OpenLayers.Geometry>}
* style - {Object}
+ * featureId - {String}
*/
- drawPoint: function(geometry, style) {
+ drawPoint: function(geometry, style, featureId) {
if(style.graphic !== false) {
var pt = this.getLocalXY(geometry);
-
- if (style.externalGraphic) {
- this.drawExternalGraphic(pt, style);
- } else {
- if(style.fill !== false) {
- this.setCanvasStyle("fill", style);
- this.canvas.beginPath();
- this.canvas.arc(pt[0], pt[1], style.pointRadius, 0, Math.PI*2, true);
- this.canvas.fill();
+ var p0 = pt[0];
+ var p1 = pt[1];
+ if (!isNaN(p0) && !isNaN(p1)) {
+ if (style.externalGraphic) {
+ this.drawExternalGraphic(pt, style, featureId);
+ } else {
+ var twoPi = Math.PI*2;
+ var radius = style.pointRadius;
+ if(style.fill !== false) {
+ this.setCanvasStyle("fill", style);
+ this.canvas.beginPath();
+ this.canvas.arc(p0, p1, radius, 0, twoPi, true);
+ this.canvas.fill();
+ if (this.hitDetection) {
+ this.setHitContextStyle("fill", featureId, style);
+ this.hitContext.beginPath();
+ this.hitContext.arc(p0, p1, radius, 0, twoPi, true);
+ this.hitContext.fill();
+ }
+ }
+
+ if(style.stroke !== false) {
+ this.setCanvasStyle("stroke", style);
+ this.canvas.beginPath();
+ this.canvas.arc(p0, p1, radius, 0, twoPi, true);
+ this.canvas.stroke();
+ if (this.hitDetection) {
+ this.setHitContextStyle("stroke", featureId, style);
+ this.hitContext.beginPath();
+ this.hitContext.arc(p0, p1, radius, 0, twoPi, true);
+ this.hitContext.stroke();
+ }
+ this.setCanvasStyle("reset");
+ }
}
-
- if(style.stroke !== false) {
- this.setCanvasStyle("stroke", style);
- this.canvas.beginPath();
- this.canvas.arc(pt[0], pt[1], style.pointRadius, 0, Math.PI*2, true);
- this.canvas.stroke();
- this.setCanvasStyle("reset");
- }
}
}
},
-
+
/**
* Method: drawLineString
* This method is only called by the renderer itself.
@@ -243,20 +405,11 @@
* Parameters:
* geometry - {<OpenLayers.Geometry>}
* style - {Object}
+ * featureId - {String}
*/
- drawLineString: function(geometry, style) {
- if(style.stroke !== false) {
- this.setCanvasStyle("stroke", style);
- this.canvas.beginPath();
- var start = this.getLocalXY(geometry.components[0]);
- this.canvas.moveTo(start[0], start[1]);
- for(var i = 1; i < geometry.components.length; i++) {
- var pt = this.getLocalXY(geometry.components[i]);
- this.canvas.lineTo(pt[0], pt[1]);
- }
- this.canvas.stroke();
- }
- this.setCanvasStyle("reset");
+ drawLineString: function(geometry, style, featureId) {
+ style = OpenLayers.Util.applyDefaults({fill: false}, style);
+ this.drawLinearRing(geometry, style, featureId);
},
/**
@@ -266,52 +419,94 @@
* Parameters:
* geometry - {<OpenLayers.Geometry>}
* style - {Object}
+ * featureId - {String}
*/
- drawLinearRing: function(geometry, style) {
- if(style.fill !== false) {
+ drawLinearRing: function(geometry, style, featureId) {
+ if (style.fill !== false) {
this.setCanvasStyle("fill", style);
- this.canvas.beginPath();
- var start = this.getLocalXY(geometry.components[0]);
- this.canvas.moveTo(start[0], start[1]);
- for(var i = 1; i < geometry.components.length - 1 ; i++) {
- var pt = this.getLocalXY(geometry.components[i]);
- this.canvas.lineTo(pt[0], pt[1]);
+ this.renderPath(this.canvas, geometry, style, featureId, "fill");
+ if (this.hitDetection) {
+ this.setHitContextStyle("fill", featureId, style);
+ this.renderPath(this.hitContext, geometry, style, featureId, "fill");
}
- this.canvas.fill();
}
-
- if(style.stroke !== false) {
+ if (style.stroke !== false) {
this.setCanvasStyle("stroke", style);
- this.canvas.beginPath();
- var start = this.getLocalXY(geometry.components[0]);
- this.canvas.moveTo(start[0], start[1]);
- for(var i = 1; i < geometry.components.length; i++) {
- var pt = this.getLocalXY(geometry.components[i]);
- this.canvas.lineTo(pt[0], pt[1]);
+ this.renderPath(this.canvas, geometry, style, featureId, "stroke");
+ if (this.hitDetection) {
+ this.setHitContextStyle("stroke", featureId, style);
+ this.renderPath(this.hitContext, geometry, style, featureId, "stroke");
}
- this.canvas.stroke();
}
this.setCanvasStyle("reset");
- },
+ },
/**
+ * Method: renderPath
+ * Render a path with stroke and optional fill.
+ */
+ renderPath: function(context, geometry, style, featureId, type) {
+ var components = geometry.components;
+ var len = components.length;
+ context.beginPath();
+ var start = this.getLocalXY(components[0]);
+ var x = start[0];
+ var y = start[1];
+ if (!isNaN(x) && !isNaN(y)) {
+ context.moveTo(start[0], start[1]);
+ for (var i=1; i<len; ++i) {
+ var pt = this.getLocalXY(components[i]);
+ context.lineTo(pt[0], pt[1]);
+ }
+ if (type === "fill") {
+ context.fill();
+ } else {
+ context.stroke();
+ }
+ }
+ },
+
+ /**
* Method: drawPolygon
* This method is only called by the renderer itself.
*
* Parameters:
* geometry - {<OpenLayers.Geometry>}
* style - {Object}
+ * featureId - {String}
*/
- drawPolygon: function(geometry, style) {
- this.drawLinearRing(geometry.components[0], style);
- for (var i = 1; i < geometry.components.length; i++) {
- this.drawLinearRing(geometry.components[i], {
- fillOpacity: 0,
- strokeWidth: 0,
- strokeOpacity: 0,
- strokeColor: '#000000',
- fillColor: '#000000'}
- ); // inner rings are 'empty'
+ drawPolygon: function(geometry, style, featureId) {
+ var components = geometry.components;
+ var len = components.length;
+ this.drawLinearRing(components[0], style, featureId);
+ // erase inner rings
+ for (var i=1; i<len; ++i) {
+ /**
+ * Note that this is overly agressive. Here we punch holes through
+ * all previously rendered features on the same canvas. A better
+ * solution for polygons with interior rings would be to draw the
+ * polygon on a sketch canvas first. We could erase all holes
+ * there and then copy the drawing to the layer canvas.
+ * TODO: http://trac.osgeo.org/openlayers/ticket/3130
+ */
+ this.canvas.globalCompositeOperation = "destination-out";
+ if (this.hitDetection) {
+ this.hitContext.globalCompositeOperation = "destination-out";
+ }
+ this.drawLinearRing(
+ components[i],
+ OpenLayers.Util.applyDefaults({stroke: false, fillOpacity: 1.0}, style),
+ featureId
+ );
+ this.canvas.globalCompositeOperation = "source-over";
+ if (this.hitDetection) {
+ this.hitContext.globalCompositeOperation = "source-over";
+ }
+ this.drawLinearRing(
+ components[i],
+ OpenLayers.Util.applyDefaults({fill: false}, style),
+ featureId
+ );
}
},
@@ -408,8 +603,13 @@
* Clear all vectors from the renderer.
*/
clear: function() {
- this.canvas.clearRect(0, 0, this.root.width, this.root.height);
+ var height = this.root.height;
+ var width = this.root.width;
+ this.canvas.clearRect(0, 0, width, height);
this.features = {};
+ if (this.hitDetection) {
+ this.hitContext.clearRect(0, 0, width, height);
+ }
},
/**
@@ -420,23 +620,28 @@
* evt - {<OpenLayers.Event>}
*
* Returns:
- * {String} A feature id or null.
+ * {<OpenLayers.Feature.Vector} A feature or null. This method returns a
+ * feature instead of a feature id to avoid an unnecessary lookup on the
+ * layer.
*/
getFeatureIdFromEvent: function(evt) {
- var loc = this.map.getLonLatFromPixel(evt.xy);
- var resolution = this.getResolution();
- var bounds = new OpenLayers.Bounds(loc.lon - resolution * 5,
- loc.lat - resolution * 5,
- loc.lon + resolution * 5,
- loc.lat + resolution * 5);
- var geom = bounds.toGeometry();
- for (var feat in this.features) {
- if (!this.features.hasOwnProperty(feat)) { continue; }
- if (this.features[feat][0].geometry.intersects(geom)) {
- return feat;
+ var feature = null;
+ if (this.hitDetection) {
+ // this dragging check should go in the feature handler
+ if (!this.map.dragging) {
+ var xy = evt.xy;
+ var x = xy.x | 0;
+ var y = xy.y | 0;
+ var data = this.hitContext.getImageData(x, y, 1, 1).data;
+ if (data[3] === 255) { // antialiased
+ var id = data[2] + (256 * (data[1] + (256 * data[0])));
+ if (id) {
+ feature = this.features["OpenLayers.Feature.Vector_" + (id - 1 + this.hitOverflow)][0];
+ }
+ }
}
- }
- return null;
+ }
+ return feature;
},
/**
@@ -467,7 +672,12 @@
*/
redraw: function() {
if (!this.locked) {
- this.canvas.clearRect(0, 0, this.root.width, this.root.height);
+ var height = this.root.height;
+ var width = this.root.width;
+ this.canvas.clearRect(0, 0, width, height);
+ if (this.hitDetection) {
+ this.hitContext.clearRect(0, 0, width, height);
+ }
var labelMap = [];
var feature, style;
for (var id in this.features) {
@@ -475,7 +685,7 @@
feature = this.features[id][0];
style = this.features[id][1];
if (!feature.geometry) { continue; }
- this.drawGeometry(feature.geometry, style);
+ this.drawGeometry(feature.geometry, style, feature.id);
if(style.label) {
labelMap.push([feature, style]);
}
Modified: sandbox/cmoullet/openlayers/lib/OpenLayers/Renderer.js
===================================================================
--- sandbox/cmoullet/openlayers/lib/OpenLayers/Renderer.js 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/lib/OpenLayers/Renderer.js 2011-04-01 19:54:37 UTC (rev 11854)
@@ -83,6 +83,7 @@
*/
initialize: function(containerID, options) {
this.container = OpenLayers.Util.getElement(containerID);
+ OpenLayers.Util.extend(this, options);
},
/**
Modified: sandbox/cmoullet/openlayers/tests/Control/DragFeature.html
===================================================================
--- sandbox/cmoullet/openlayers/tests/Control/DragFeature.html 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/tests/Control/DragFeature.html 2011-04-01 19:54:37 UTC (rev 11854)
@@ -103,6 +103,41 @@
"onEnter called with expected feature");
}
+ function test_Control_DragFeature_over_touch(t) {
+ t.plan(7);
+ var log = [];
+ var map = new OpenLayers.Map("map");
+ var layer = new OpenLayers.Layer.Vector();
+ map.addLayer(layer);
+ var control = new OpenLayers.Control.DragFeature(layer, {
+ onEnter: function(f) { log.push({feature: f}); }
+ });
+ map.addControl(control);
+
+ control.activate();
+ t.ok(!control.handlers.drag.active,
+ "drag handler is not active before touch on a feature");
+
+ // simulate a touch on a feature
+ var feature = new OpenLayers.Feature.Vector();
+ feature.layer = layer;
+ layer.getFeatureFromEvent = function(evt) {
+ return feature;
+ }
+ map.events.triggerEvent("touchstart", {type: "touchstart", touches: ['foo']});
+
+ t.eq(control.feature.id, feature.id,
+ "control gets the proper feature from the feature handler");
+ t.ok(control.handlers.drag.active,
+ "drag handler activated when touch on a feature");
+ t.ok(control.handlers.drag.started, "drag handler has started");
+ t.ok(!control.handlers.drag.stopDown, "drag handler is not stopping down");
+ t.eq(log.length, 1,
+ "onEnter called exactly once");
+ t.eq(log[0].feature.id, feature.id,
+ "onEnter called with expected feature");
+ }
+
function test_Control_DragFeature_down(t) {
t.plan(3);
var map = new OpenLayers.Map("map");
@@ -284,6 +319,44 @@
"onLeave called with expected feature");
}
+ function test_Control_DragFeature_out_touch(t) {
+ t.plan(5);
+ var log = [];
+ var map = new OpenLayers.Map("map");
+ var layer = new OpenLayers.Layer.Vector();
+ map.addLayer(layer);
+ var control = new OpenLayers.Control.DragFeature(layer, {
+ onLeave: function(f) { log.push({feature: f}); }
+ });
+ map.addControl(control);
+
+ control.activate();
+
+ // simulate a touch on a feature
+ var feature = new OpenLayers.Feature.Vector();
+ feature.layer = layer;
+ layer.getFeatureFromEvent = function() {
+ return feature;
+ };
+ map.events.triggerEvent("touchstart", {type: "touchstart", touches: ['foo']});
+ t.eq(control.feature.id, feature.id,
+ "feature is set on mouse over");
+
+ // simulate a touch outside the feature
+ layer.getFeatureFromEvent = function() {
+ return null;
+ };
+ map.events.triggerEvent("touchstart", {type: "touchstart", touches: ['foo']});
+ t.ok(control.feature == null,
+ "feature is set to null on mouse out");
+ t.ok(control.handlers.drag.stopDown,
+ "drag handler is stopping down again");
+ t.eq(log.length, 1,
+ "onLeave called exactly once");
+ t.eq(log[0].feature.id, feature.id,
+ "onLeave called with expected feature");
+ }
+
</script>
</head>
<body>
Modified: sandbox/cmoullet/openlayers/tests/Renderer/Canvas.html
===================================================================
--- sandbox/cmoullet/openlayers/tests/Renderer/Canvas.html 2011-04-01 09:26:39 UTC (rev 11853)
+++ sandbox/cmoullet/openlayers/tests/Renderer/Canvas.html 2011-04-01 19:54:37 UTC (rev 11854)
@@ -56,6 +56,75 @@
t.eq(r.resolution, resolution, "resolution is correctly set");
}
+ function test_featureIdToRGB(t) {
+ if (!supported) {
+ t.plan(0);
+ return;
+ }
+ t.plan(2);
+ var el = document.body;
+ el.id = "foo";
+ var renderer = new OpenLayers.Renderer.Canvas(el.id);
+
+ var cases = [{
+ id: "foo_0", rgb: [0, 0, 1]
+ }, {
+ id: "foo_10", rgb: [0, 0, 11]
+ }, {
+ id: "foo_100", rgb: [0, 0, 101]
+ }, {
+ id: "foo_1000000", rgb: [15, 66, 65]
+ }, {
+ id: "foo_16777214", rgb: [255, 255, 255]
+ }, {
+ id: "foo_16777215", rgb: [0, 0, 1]
+ }];
+ t.plan(cases.length);
+
+ var c;
+ for (var i=0; i<cases.length; ++i) {
+ c = cases[i];
+ t.eq(renderer.featureIdToRGB(c.id), c.rgb, c.id);
+ }
+
+ renderer.destroy();
+ }
+
+ function test_featureIdToHex(t) {
+ if (!supported) {
+ t.plan(0);
+ return;
+ }
+ t.plan(2);
+ var el = document.body;
+ el.id = "foo";
+ var renderer = new OpenLayers.Renderer.Canvas(el.id);
+
+ var cases = [{
+ id: "foo_0", hex: "#000001"
+ }, {
+ id: "foo_10", hex: "#00000b"
+ }, {
+ id: "foo_100", hex: "#000065"
+ }, {
+ id: "foo_1000000", hex: "#0f4241"
+ }, {
+ id: "foo_16777214", hex: "#ffffff"
+ }, {
+ id: "foo_16777215", hex: "#000001"
+ }];
+ t.plan(cases.length);
+
+ var c;
+ for (var i=0; i<cases.length; ++i) {
+ c = cases[i];
+ t.eq(renderer.featureIdToHex(c.id), c.hex, c.id);
+ }
+
+ renderer.destroy();
+ }
+
+
function test_Renderer_Canvas_destroy(t) {
if (!supported) { t.plan(0); return; }
t.plan(5);
@@ -77,7 +146,86 @@
t.eq(r.resolution, null, "resolution nullified");
t.eq(r.map, null, "map nullified");
}
+
+ function test_hitDetection(t) {
+ if (!supported) {
+ t.plan(0);
+ return;
+ }
+
+ var layer = new OpenLayers.Layer.Vector(null, {
+ isBaseLayer: true,
+ resolutions: [1],
+ styleMap: new OpenLayers.StyleMap({
+ pointRadius: 5,
+ strokeWidth: 3,
+ fillColor: "red",
+ fillOpacity: 0.5,
+ strokeColor: "blue",
+ strokeOpacity: 0.75
+ }),
+ renderers: ["Canvas"]
+ });
+
+ var map = new OpenLayers.Map({
+ div: "map",
+ controls: [],
+ layers: [layer],
+ center: new OpenLayers.LonLat(0, 0),
+ zoom: 0
+ });
+
+ layer.addFeatures([
+ new OpenLayers.Feature.Vector(
+ new OpenLayers.Geometry.Point(-100, 0)
+ ),
+ new OpenLayers.Feature.Vector(
+ OpenLayers.Geometry.fromWKT("LINESTRING(-50 0, 50 0)")
+ ),
+ new OpenLayers.Feature.Vector(
+ OpenLayers.Geometry.fromWKT("POLYGON((100 -25, 150 -25, 150 25, 100 25, 100 -25), (120 -5, 130 -5, 130 5, 120 5, 120 -5))")
+ )
+ ]);
+
+ var cases = [{
+ msg: "center of point", x: -100, y: 0, id: layer.features[0].id
+ }, {
+ msg: "edge of point", x: -103, y: 3, id: layer.features[0].id
+ }, {
+ msg: "outside point", x: -110, y: 3, id: null
+ }, {
+ msg: "center of line", x: 0, y: 0, id: layer.features[1].id
+ }, {
+ msg: "edge of line", x: 0, y: 1, id: layer.features[1].id
+ }, {
+ msg: "outside line", x: 0, y: 5, id: null
+ }, {
+ msg: "inside polygon", x: 110, y: 0, id: layer.features[2].id
+ }, {
+ msg: "edge of polygon", x: 99, y: 0, id: layer.features[2].id
+ }, {
+ msg: "inside polygon hole", x: 125, y: 0, id: null
+ }, {
+ msg: "outside polygon", x: 155, y: 0, id: null
+ }];
+ function px(x, y) {
+ return map.getPixelFromLonLat(
+ new OpenLayers.LonLat(x, y)
+ );
+ }
+
+ var num = cases.length;
+ t.plan(num);
+ var c, feature;
+ for (var i=0; i<num; ++i) {
+ c = cases[i];
+ feature = layer.renderer.getFeatureIdFromEvent({xy: px(c.x, c.y)});
+ t.eq(feature && feature.id, c.id, c.msg);
+ }
+
+ }
+
</script>
</head>
<body>
More information about the Commits
mailing list