new "immediate" option to enable live measuring while moving the mouse. p=patzi,me r=me (closes #2935)

git-svn-id: http://svn.openlayers.org/trunk/openlayers@10917 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
ahocevar
2010-11-24 10:44:01 +00:00
parent 30eabe26ad
commit e970151067
3 changed files with 194 additions and 6 deletions

View File

@@ -132,6 +132,13 @@
control.geodesic = element.checked;
}
}
function toggleImmediate(element) {
for(key in measureControls) {
var control = measureControls[key];
control.setImmediate(element.checked);
}
}
</script>
</head>
<body onload="init()">
@@ -164,13 +171,19 @@
<input type="checkbox" name="geodesic" id="geodesicToggle" onclick="toggleGeodesic(this);" />
<label for="geodesicToggle">use geodesic measures</label>
</li>
<li>
<input type="checkbox" name="immediate" id="immediateToggle" onclick="toggleImmediate(this);" />
<label for="immediateToggle">use immediate measures</label>
</li>
</ul>
<p>Note that the geometries drawn are planar geometries and the
metrics returned by the measure control are planar measures by
default. If your map is in a geographic projection or you have the
appropriate projection definitions to transform your geometries into
geographic coordinates, you can set the "geodesic" property of the control
to true to calculate geodesic measures instead of planar measures.</p>
to true to calculate geodesic measures instead of planar measures.
Also you have the possibility to set the "immediate" property to true
to get a new calculated value once the mouse has been mooved.</p>
</div>
</body>
</html>

View File

@@ -33,7 +33,8 @@ OpenLayers.Control.Measure = OpenLayers.Class(OpenLayers.Control, {
* will receive an event with measure, units, order, and geometry
* properties.
* measurepartial - Triggered when a new point is added to the
* measurement sketch. Listeners receive an event with measure,
* measurement sketch or if the <immediate> property is true and the
* measurement sketch is modified. Listeners receive an event with measure,
* units, order, and geometry.
*/
EVENT_TYPES: ['measure', 'measurepartial'],
@@ -103,6 +104,14 @@ OpenLayers.Control.Measure = OpenLayers.Class(OpenLayers.Control, {
*/
persist: false,
/**
* APIProperty: immediate
* {Boolean} Activates the immediate measurement so that the "measurepartial"
* event is also fired once the measurement sketch is modified.
* Default is false.
*/
immediate : false,
/**
* Constructor: OpenLayers.Control.Measure
*
@@ -117,10 +126,12 @@ OpenLayers.Control.Measure = OpenLayers.Class(OpenLayers.Control, {
OpenLayers.Control.prototype.EVENT_TYPES
);
OpenLayers.Control.prototype.initialize.apply(this, [options]);
this.callbacks = OpenLayers.Util.extend(
{done: this.measureComplete, point: this.measurePartial},
this.callbacks
);
var callbacks = {done: this.measureComplete,
point: this.measurePartial};
if (this.immediate){
callbacks.modify = this.measureImmediate;
}
this.callbacks = OpenLayers.Util.extend(callbacks, this.callbacks);
// let the handler options override, so old code that passes 'persist'
// directly to the handler does not need an update
@@ -147,6 +158,20 @@ OpenLayers.Control.Measure = OpenLayers.Class(OpenLayers.Control, {
this.cancelDelay();
this.handler.cancel();
},
/**
* APIMethod: setImmediate
* Set <persist> is true, the temporary
* sketch will be erased.
*/
setImmediate: function(immediate) {
this.immediate = immediate;
if (this.immediate){
this.callbacks.modify = this.measureImmediate;
} else {
delete this.callbacks.modify;
}
},
/**
* Method: updateHandler
@@ -205,6 +230,20 @@ OpenLayers.Control.Measure = OpenLayers.Class(OpenLayers.Control, {
}
},
/**
* Method: measureImmediate
* Called each time the measurement sketch is modified.
*
* Parameters: point - {<OpenLayers.Geometry.Point>} The point at the
* mouseposition. feature - {<OpenLayers.Feature.Vector>} The sketch feature.
*/
measureImmediate : function(point, feature) {
if (this.delayedTrigger === null &&
!this.handler.freehandMode(this.handler.evt)) {
this.measure(feature.geometry, "measurepartial");
}
},
/**
* Method: cancelDelay
* Cancels the delay measurement that measurePartial began.

View File

@@ -222,6 +222,142 @@
);
}
function test_immediate(t) {
t.plan(29);
var map = new OpenLayers.Map({
div: "map",
units: "m",
resolutions: [1],
layers: [
new OpenLayers.Layer(null, {
isBaseLayer: true
})
],
center: new OpenLayers.LonLat(0, 0)
});
var log = [];
var control = new OpenLayers.Control.Measure(
OpenLayers.Handler.Path, {
persist: true,
immediate: true,
eventListeners: {
measurepartial: function(evt) {
log.push(evt);
},
measure: function(evt){
log.push(evt);
}
}
}
);
map.addControl(control);
control.activate();
// convenience function to trigger mouse events
function trigger(type, x, y) {
map.events.triggerEvent(type, {
xy: new OpenLayers.Pixel(x, y)
})
};
// delay in seconds
var delay = control.partialDelay / 1000;
// a) establish first point
trigger("mousedown", 0, 0);
trigger("mouseup", 0, 0);
// move 10 pixels
trigger("mousemove", 0, 10);
t.eq(log.length, 0, "a) no event fired yet");
t.delay_call(
delay, function() {
// confirm measurepartial is fired
t.eq(log.length, 1, "a) event logged");
t.eq(log[0].type, "measurepartial", "a) correct type");
// mousemove within the partialDelay fires no event, so the
// measure below is the one of the initial point
t.eq(log[0].measure, 0, "a) correct measure");
// b) move 10 pixels
trigger("mousemove", 0, 20);
// c) move 10 pixels again
trigger("mousemove", 0, 30);
// confirm measurepartial is fired 2 times
t.eq(log.length, 3, "b) event logged");
t.eq(log[1].type, "measurepartial", "b) correct type");
t.eq(log[1].measure, 20, "b) correct measure");
t.eq(log[2].type, "measurepartial", "c) correct type");
t.eq(log[2].measure, 30, "c) correct measure");
// d) switch immediate measurement off
control.setImmediate(false);
t.eq(control.immediate, false, "d) immediate is false");
// e) move 10 pixels and click
trigger("mousemove", 0, 40);
trigger("mousedown", 0, 40);
trigger("mouseup", 0, 40);
// confirm measurepartial is not fired before delay
t.eq(log.length, 3, "e) no event fired yet")
},
// wait for delay then confirm event was logged
delay, function() {
t.eq(log.length, 4, "e) event logged")
t.eq(log[3].type, "measurepartial", "e) correct type");
t.eq(log[3].measure, 40, "e) correct measure");
// f) switch immediate measurement on
control.setImmediate(true);
t.eq(control.immediate, true, "f) immediate is true");
// g) move 10 pixels
trigger("mousemove", 0, 50);
},
delay, function() {
t.eq(log.length, 5, "g) event logged");
t.eq(log[4].type, "measurepartial", "g) correct type");
t.eq(log[4].measure, 50, "g) correct measure");
// h) move 10 pixels
trigger("mousemove", 0, 60);
t.eq(log.length, 6, "h) event logged");
t.eq(log[5].type, "measurepartial", "h) correct type");
t.eq(log[5].measure, 60, "h) correct measure");
// i) double click to finish
trigger("mousedown", 0, 60);
trigger("mouseup", 0, 60);
t.eq(log.length, 6, "i) no event fired yet");
},
delay, function() {
t.eq(log.length, 7, "i) event logged");
t.eq(log[6].type, "measurepartial", "i) correct type");
t.eq(log[6].measure, 60, "i) correct measure");
trigger("dblclick", 0, 60);
t.eq(log.length, 8, "i) event logged");
t.eq(log[7].type, "measure", "i) correct type");
t.eq(log[7].measure, 60, "i) correct measure");
// clear log
log = [];
// j) clean up
map.destroy();
// wait for delay and confirm event not logged
},
delay, function() {
t.eq(log.length, 0, "j) no event fired after destroy");
}
);
}
</script>
</head>