Ticket #638: dragFeature.patch
| File dragFeature.patch, 20.3 kB (added by tschaub, 1 year ago) |
|---|
-
tests/Control/test_DragFeature.html
old new 1 <html> 2 <head> 3 <script src="../../lib/OpenLayers.js"></script> 4 <script type="text/javascript"> 5 function test_Control_DragFeature_constructor(t) { 6 t.plan(3); 7 8 var options = { 9 geometryTypes: "foo" 10 }; 11 var layer = "bar"; 12 var control = new OpenLayers.Control.DragFeature(layer, options); 13 t.ok(control instanceof OpenLayers.Control.DragFeature, 14 "new OpenLayers.Control.DragFeature returns an instance"); 15 t.eq(control.layer, "bar", 16 "constructor sets layer correctly"); 17 t.eq(control.featureHandler.geometryTypes, "foo", 18 "constructor sets options correctly on feature handler"); 19 } 20 21 function test_Control_DragFeature_destroy(t) { 22 t.plan(2); 23 var map = new OpenLayers.Map("map"); 24 var layer = new OpenLayers.Layer.Vector(); 25 map.addLayer(layer); 26 var control = new OpenLayers.Control.DragFeature(layer); 27 control.dragHandler.destroy = function() { 28 t.ok(true, 29 "control.destroy calls destroy on drag handler"); 30 } 31 control.featureHandler.destroy = function() { 32 t.ok(true, 33 "control.destroy calls destroy on feature handler"); 34 } 35 control.destroy(); 36 37 } 38 39 function test_Control_DragFeature_activate(t) { 40 t.plan(2); 41 var map = new OpenLayers.Map("map"); 42 var layer = new OpenLayers.Layer.Vector(); 43 map.addLayer(layer); 44 var control = new OpenLayers.Control.DragFeature(layer); 45 map.addControl(control); 46 t.ok(!control.featureHandler.active, 47 "feature handler is not active prior to activating control"); 48 control.activate(); 49 t.ok(control.featureHandler.active, 50 "feature handler is active after activating control"); 51 } 52 53 function test_Control_DragFeature_deactivate(t) { 54 t.plan(2); 55 var map = new OpenLayers.Map("map"); 56 var layer = new OpenLayers.Layer.Vector(); 57 map.addLayer(layer); 58 var control = new OpenLayers.Control.DragFeature(layer); 59 map.addControl(control); 60 61 control.dragHandler.deactivate = function() { 62 t.ok(true, 63 "control.deactivate calls deactivate on drag handler"); 64 } 65 control.featureHandler.deactivate = function() { 66 t.ok(true, 67 "control.deactivate calls deactivate on feature handler"); 68 } 69 control.deactivate(); 70 } 71 72 function test_Control_DragFeature_over(t) { 73 t.plan(3); 74 var map = new OpenLayers.Map("map"); 75 var layer = new OpenLayers.Layer.Vector(); 76 map.addLayer(layer); 77 var control = new OpenLayers.Control.DragFeature(layer); 78 map.addControl(control); 79 80 control.activate(); 81 t.ok(!control.dragHandler.active, 82 "drag handler is not active before over a feature"); 83 84 // simulate a mouseover on a feature 85 layer.getFeatureFromEvent = function(evt) { 86 return "foo"; 87 } 88 map.events.triggerEvent("mousemove"); 89 90 t.eq(control.feature, "foo", 91 "control gets the proper feature from the feature handler"); 92 t.ok(control.dragHandler.active, 93 "drag handler activated when over a feature"); 94 } 95 96 function test_Control_DragFeature_down(t) { 97 t.plan(3); 98 var map = new OpenLayers.Map("map"); 99 var layer = new OpenLayers.Layer.Vector(); 100 map.addLayer(layer); 101 var control = new OpenLayers.Control.DragFeature(layer); 102 map.addControl(control); 103 104 control.activate(); 105 106 // simulate a mouseover on a feature 107 layer.getFeatureFromEvent = function(evt) { 108 return "foo"; 109 } 110 map.events.triggerEvent("mousemove"); 111 112 t.ok(!control.dragHandler.dragging, 113 "control is not dragging before the mousedown"); 114 115 // simulate a mousedown on a feature 116 map.events.triggerEvent("mousedown", {xy: "bar", which: 1}); 117 118 t.ok(control.dragHandler.dragging, 119 "drag is dragging after the mousedown"); 120 t.eq(control.lastPixel, "bar", 121 "mousedown sets the lastPixel correctly"); 122 } 123 124 function test_Control_DragFeature_move(t) { 125 t.plan(3); 126 var map = new OpenLayers.Map("map"); 127 var layer = new OpenLayers.Layer.Vector(); 128 map.addLayer(layer); 129 var control = new OpenLayers.Control.DragFeature(layer); 130 map.addControl(control); 131 map.getResolution = function() { 132 return 2; 133 } 134 135 control.activate(); 136 137 // mock up a feature - for the sole purpose of testing mousemove 138 var uid = Math.random(); 139 layer.getFeatureFromEvent = function() { 140 var geom = new OpenLayers.Geometry.Point(Math.random(), 141 Math.random()); 142 geom.move = function(x, y) { 143 t.eq(x, 2, "move called with dx * res"); 144 t.eq(y, -4, "move called with -dy * res"); 145 }; 146 var feature = new OpenLayers.Feature.Vector(geom); 147 feature.uid = uid; 148 return feature; 149 }; 150 layer.drawFeature = function(feature) { 151 t.eq(feature.uid, uid, 152 "layer.drawFeature called with correct feature"); 153 }; 154 155 // simulate a mouseover on a feature 156 map.events.triggerEvent("mousemove"); 157 158 // simulate a mousedown on a feature 159 var down = new OpenLayers.Pixel(0, 0); 160 map.events.triggerEvent("mousedown", {xy: down, which: 1}); 161 162 // simulate a mousemove on a feature 163 var move = new OpenLayers.Pixel(1, 2); 164 map.events.triggerEvent("mousemove", {xy: move, which: 1}); 165 166 } 167 168 </script> 169 </head> 170 <body> 171 <div id="map" style="width: 400px; height: 250px;"/> 172 </body> 173 </html> -
tests/list-tests.html
old new 58 58 <li>test_Tile.html</li> 59 59 <li>Tile/test_Image.html</li> 60 60 <li>test_Control.html</li> 61 <li>Control/test_DragFeature.html</li> 61 62 <li>Control/test_DragPan.html</li> 62 63 <li>Control/test_OverviewMap.html</li> 63 64 <li>Control/test_NavToolbar.html</li> -
lib/OpenLayers/Control/DragFeature.js
old new 1 /* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license. 2 * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 3 * for the full text of the license. */ 4 5 6 /** 7 * @requires OpenLayers/Control.js 8 * @requires OpenLayers/Handler/Drag.js 9 * @requires OpenLayers/Handler/Feature.js 10 * 11 * Class: OpenLayers.Control.DragFeature 12 * Move a feature with a drag. Create a new control with the 13 * <OpenLayers.Control.DragFeature> constructor. 14 * 15 * Inherits From: 16 * - <OpenLayers.Control> 17 */ 18 OpenLayers.Control.DragFeature = OpenLayers.Class(OpenLayers.Control, { 19 20 /** 21 * APIProperty: geometryTypes 22 * {Array(String)} To restrict dragging to a limited set of geometry types, 23 * send a list of strings corresponding to the geometry class names. 24 */ 25 geometryTypes: null, 26 27 /** 28 * APIProperty: onDrag 29 * {Function} Define this function if you want to know about each move of a 30 * feature. The function should expect to receive two arguments: the 31 * feature that is being dragged and the pixel location of the mouse. 32 * 33 * Parameters: 34 * feature - {OpenLayers.Feature.Vector} The feature that was dragged. 35 * pixel - {OpenLayers.Pixel} The pixel location of the mouse. 36 */ 37 onDrag: function(feature, pixel) {}, 38 39 /** 40 * APIProperty: onComplete 41 * {Function} Define this function if you want to know when a feature is 42 * done dragging. The function should expect to receive two arguments: 43 * the feature that is being dragged and the pixel location of the 44 * mouse. 45 * 46 * Parameters: 47 * feature - {OpenLayers.Feature.Vector} The feature that was dragged. 48 * pixel - {OpenLayers.Pixel} The pixel location of the mouse. 49 */ 50 onComplete: function(feature, pixel) {}, 51 52 /** 53 * Property: layer 54 * {OpenLayers.Layer.Vector} 55 */ 56 layer: null, 57 58 /** 59 * Property: feature 60 * {OpenLayers.Feature.Vector} 61 */ 62 feature: null, 63 64 /** 65 * Property: dragHandler 66 * {OpenLayers.Handler.Drag} 67 */ 68 dragHandler: null, 69 70 /** 71 * Property: dragCallbacks 72 * {Object} The functions that are sent to the drag handler for callback. 73 */ 74 dragCallbacks: {}, 75 76 /** 77 * Property: featureHandler 78 * {OpenLayers.Handler.Feature} 79 */ 80 featureHandler: null, 81 82 /** 83 * Property: featureCallbacks 84 * {Object} The functions that are sent to the feature handler for callback. 85 */ 86 featureCallbacks: {}, 87 88 /** 89 * Property: lastPixel 90 * {OpenLayers.Pixel} 91 */ 92 lastPixel: null, 93 94 /** 95 * Constructor: OpenLayers.Control.DragFeature 96 * Create a new control to drag features. 97 * 98 * Parameters: 99 * layer - {OpenLayers.Layer.Vector} The layer containing features to be 100 * dragged. 101 * options - {Object} Optional object whose properties will be set on the 102 * control. 103 */ 104 initialize: function(layer, options) { 105 OpenLayers.Control.prototype.initialize.apply(this, [options]); 106 this.layer = layer; 107 this.dragCallbacks = OpenLayers.Util.extend({down: this.downFeature, 108 move: this.moveFeature, 109 up: this.upFeature, 110 out: this.cancel, 111 done: this.doneDragging 112 }, this.dragCallbacks); 113 this.dragHandler = new OpenLayers.Handler.Drag(this, this.dragCallbacks); 114 this.featureCallbacks = OpenLayers.Util.extend({over: this.overFeature, 115 out: this.outFeature 116 }, this.featureCallbacks); 117 var handlerOptions = {geometryTypes: this.geometryTypes}; 118 this.featureHandler = new OpenLayers.Handler.Feature(this, this.layer, 119 this.featureCallbacks, 120 handlerOptions); 121 }, 122 123 /** 124 * APIMethod: destroy 125 * Take care of things that are not handled in superclass 126 */ 127 destroy: function() { 128 this.layer = null; 129 this.dragHandler.destroy(); 130 this.featureHandler.destroy(); 131 OpenLayers.Control.prototype.destroy.apply(this, []); 132 }, 133 134 /** 135 * APIMethod: activate 136 * Activate the control and the feature handler. 137 * 138 * Returns: 139 * {Boolean} Successfully activated the control and feature handler. 140 */ 141 activate: function() { 142 return (this.featureHandler.activate() && 143 OpenLayers.Control.prototype.activate.apply(this, arguments)); 144 }, 145 146 /** 147 * APIMethod: deactivate 148 * Deactivate the control and all handlers. 149 * 150 * Returns: 151 * {Boolean} Successfully deactivated the control. 152 */ 153 deactivate: function() { 154 // the return from the handlers is unimportant in this case 155 this.dragHandler.deactivate(); 156 this.featureHandler.deactivate(); 157 return OpenLayers.Control.prototype.deactivate.apply(this, arguments); 158 }, 159 160 /** 161 * Method: overFeature 162 * Called when the feature handler detects a mouse-over on a feature. 163 * This activates the drag handler. 164 * 165 * Parameters: 166 * feature - {OpenLayers.Feature.Vector} The selected feature. 167 */ 168 overFeature: function(feature) { 169 if(!this.dragHandler.dragging) { 170 this.feature = feature; 171 this.dragHandler.activate(); 172 this.over = true; 173 // TBD replace with CSS classes 174 this.map.div.style.cursor = "move"; 175 } else { 176 if(this.feature.id == feature.id) { 177 this.over = true; 178 } else { 179 this.over = false; 180 } 181 } 182 }, 183 184 /** 185 * Method: downFeature 186 * Called when the drag handler detects a mouse-down. 187 * 188 * Parameters: 189 * pixel - {OpenLayers.Pixel} Location of the mouse event. 190 */ 191 downFeature: function(pixel) { 192 this.dragHandler.dragging = true; 193 this.lastPixel = pixel; 194 }, 195 196 /** 197 * Method: moveFeature 198 * Called when the drag handler detects a mouse-move. Also calls the 199 * optional onDrag method. 200 * 201 * Parameters: 202 * pixel - {OpenLayers.Pixel} Location of the mouse event. 203 */ 204 moveFeature: function(pixel) { 205 var res = this.map.getResolution(); 206 this.feature.geometry.move(res * (pixel.x - this.lastPixel.x), 207 res * (this.lastPixel.y - pixel.y)); 208 this.layer.drawFeature(this.feature); 209 this.lastPixel = pixel; 210 this.onDrag(this.feature, pixel); 211 }, 212 213 /** 214 * Method: upFeature 215 * Called when the drag handler detects a mouse-up. Also calls the 216 * optional onComplete method. 217 * 218 * Parameters: 219 * pixel - {OpenLayers.Pixel} Location of the mouse event. 220 */ 221 upFeature: function(pixel) { 222 if(!this.over) { 223 this.dragHandler.deactivate(); 224 this.feature = null; 225 // TBD replace with CSS classes 226 this.map.div.style.cursor = "default"; 227 } 228 }, 229 230 /** 231 * Method: doneDragging 232 * Called when the drag handler is done dragging. 233 * 234 * Parameters: 235 * pixel - {OpenLayers.Pixel} The last event pixel location. If this event 236 * came from a mouseout, this may not be in the map viewport. 237 */ 238 doneDragging: function(pixel) { 239 this.onComplete(this.feature, pixel); 240 }, 241 242 /** 243 * Method: outFeature 244 * Called when the feature handler detects a mouse-out on a feature. 245 * 246 * Parameters: 247 * feature - {OpenLayers.Feature.Vector} The feature that the mouse left. 248 */ 249 outFeature: function(feature) { 250 if(!this.dragHandler.dragging) { 251 this.over = false; 252 this.dragHandler.deactivate(); 253 // TBD replace with CSS classes 254 this.map.div.style.cursor = "default"; 255 } else { 256 if(this.feature.id == feature.id) { 257 this.over = false; 258 } 259 } 260 }, 261 262 /** 263 * Method: cancel 264 * Called when the drag handler detects a mouse-out (from the map viewport). 265 */ 266 cancel: function() { 267 this.dragHandler.deactivate(); 268 this.over = false; 269 }, 270 271 /** 272 * Method: setMap 273 * Set the map property for the control and all handlers. 274 * 275 * Parameters: 276 * map - {OpenLayers.Map} The control's map. 277 */ 278 setMap: function(map) { 279 this.dragHandler.setMap(map); 280 this.featureHandler.setMap(map); 281 OpenLayers.Control.prototype.setMap.apply(this, arguments); 282 }, 283 284 CLASS_NAME: "OpenLayers.Control.DragFeature" 285 }); -
lib/OpenLayers.js
old new 138 138 "OpenLayers/Control/Scale.js", 139 139 "OpenLayers/Control/LayerSwitcher.js", 140 140 "OpenLayers/Control/DrawFeature.js", 141 "OpenLayers/Control/DragFeature.js", 141 142 "OpenLayers/Control/Panel.js", 142 143 "OpenLayers/Control/SelectFeature.js", 143 144 "OpenLayers/Geometry.js", -
examples/drag-feature.html
old new 1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <title>Drag Feature</title> 4 <style type="text/css"> 5 #map { 6 width: 512px; 7 height: 350px; 8 border: 1px solid gray; 9 } 10 #controls { 11 width: 512px; 12 } 13 #controlToggle { 14 padding-left: 1em; 15 } 16 #controlToggle li { 17 list-style: none; 18 } 19 </style> 20 <script src="../lib/OpenLayers.js"></script> 21 <script type="text/javascript"> 22 <!-- 23 var map, vectors, controls; 24 function init(){ 25 map = new OpenLayers.Map('map'); 26 var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS", 27 "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'}); 28 29 vectors = new OpenLayers.Layer.Vector("Vector Layer"); 30 31 map.addLayers([wms, vectors]); 32 map.addControl(new OpenLayers.Control.LayerSwitcher()); 33 map.addControl(new OpenLayers.Control.MousePosition()); 34 35 controls = { 36 point: new OpenLayers.Control.DrawFeature(vectors, 37 OpenLayers.Handler.Point), 38 line: new OpenLayers.Control.DrawFeature(vectors, 39 OpenLayers.Handler.Path), 40 polygon: new OpenLayers.Control.DrawFeature(vectors, 41 OpenLayers.Handler.Polygon), 42 drag: new OpenLayers.Control.DragFeature(vectors) 43 }; 44 45 for(var key in controls) { 46 map.addControl(controls[key]); 47 } 48 49 map.setCenter(new OpenLayers.LonLat(0, 0), 3); 50 document.getElementById('noneToggle').checked = true; 51 } 52 53 function toggleControl(element) { 54 for(key in controls) { 55 var control = controls[key]; 56 if(element.value == key && element.checked) { 57 control.activate(); 58 } else { 59 control.deactivate(); 60 } 61 } 62 } 63 64 // --> 65 </script> 66 </head> 67 <body onload="init()"> 68 <h1>OpenLayers Drag Feature Example</h1> 69 <div id="map"></div> 70 <div id="controls"> 71 <ul id="controlToggle"> 72 <li> 73 <input type="radio" name="type" value="none" id="noneToggle" 74 onclick="toggleControl(this);" checked="checked" /> 75 <label for="noneToggle">navigate</label> 76 </li> 77 <li> 78 <input type="radio" name="type" value="point" id="pointToggle" onclick="toggleControl(this);" /> 79 <label for="pointToggle">draw point</label> 80 </li> 81 <li> 82 <input type="radio" name="type" value="line" id="lineToggle" onclick="toggleControl(this);" /> 83 <label for="lineToggle">draw line</label> 84 </li> 85 <li> 86 <input type="radio" name="type" value="polygon" id="polygonToggle" onclick="toggleControl(this);" /> 87 <label for="polygonToggle">draw polygon</label> 88 </li> 89 <li> 90 <input type="radio" name="type" value="drag" id="dragToggle" 91 onclick="toggleControl(this);" /> 92 <label for="dragToggle">drag feature</label> 93 </li> 94 </ul> 95 </div> 96 </body> 97 </html>
