Canvas events fixes (fix #3915)
- fix fireEvent called for each layer containing event point - fix layer not removed from this._layer at remove - fix L.DomEvent.stop(e) not honoured for canvas because events are both listenned on canvas container and map container
This commit is contained in:
parent
c82aaa4158
commit
0b0989f9f1
@ -77,6 +77,7 @@
|
||||
<script type="text/javascript" src="suites/layer/vector/PolygonSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/layer/vector/PolylineSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/layer/vector/PolylineGeometrySpec.js"></script>
|
||||
<script type="text/javascript" src="suites/layer/vector/CanvasSpec.js"></script>
|
||||
|
||||
<!-- /map -->
|
||||
<script type="text/javascript" src="suites/map/MapSpec.js"></script>
|
||||
|
78
spec/suites/layer/vector/CanvasSpec.js
Normal file
78
spec/suites/layer/vector/CanvasSpec.js
Normal file
@ -0,0 +1,78 @@
|
||||
describe('Canvas', function () {
|
||||
|
||||
var c, map, p2ll, latLngs;
|
||||
|
||||
before(function () {
|
||||
c = document.createElement('div');
|
||||
c.style.width = '400px';
|
||||
c.style.height = '400px';
|
||||
c.style.position = 'absolute';
|
||||
c.style.top = '0';
|
||||
c.style.left = '0';
|
||||
document.body.appendChild(c);
|
||||
map = new L.Map(c, {preferCanvas: true, zoomControl: false});
|
||||
map.setView([0, 0], 6);
|
||||
p2ll = function (x, y) {
|
||||
return map.layerPointToLatLng([x, y]);
|
||||
};
|
||||
latLngs = [p2ll(0, 0), p2ll(0, 100), p2ll(100, 100), p2ll(100, 0)];
|
||||
});
|
||||
|
||||
after(function () {
|
||||
document.body.removeChild(c);
|
||||
});
|
||||
|
||||
describe("#events", function () {
|
||||
var layer;
|
||||
|
||||
beforeEach(function () {
|
||||
layer = L.polygon(latLngs).addTo(map);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
layer.remove();
|
||||
});
|
||||
|
||||
it("should fire event when layer contains mouse", function () {
|
||||
var spy = sinon.spy();
|
||||
layer.on('click', spy);
|
||||
happen.at('click', 50, 50); // Click on the layer.
|
||||
expect(spy.callCount).to.eql(1);
|
||||
happen.at('click', 150, 150); // Click outside layer.
|
||||
expect(spy.callCount).to.eql(1);
|
||||
layer.off("click", spy);
|
||||
});
|
||||
|
||||
it("DOM events propagate from canvas polygon to map", function () {
|
||||
var spy = sinon.spy();
|
||||
map.on("click", spy);
|
||||
happen.at('click', 50, 50);
|
||||
expect(spy.callCount).to.eql(1);
|
||||
map.off("click", spy);
|
||||
});
|
||||
|
||||
it("DOM events fired on canvas polygon can be cancelled before being caught by the map", function () {
|
||||
var mapSpy = sinon.spy();
|
||||
var layerSpy = sinon.spy();
|
||||
map.on("click", mapSpy);
|
||||
layer.on("click", L.DomEvent.stopPropagation).on("click", layerSpy);
|
||||
happen.at('click', 50, 50);
|
||||
expect(layerSpy.callCount).to.eql(1);
|
||||
expect(mapSpy.callCount).to.eql(0);
|
||||
map.off("click", mapSpy);
|
||||
layer.off("click", L.DomEvent.stopPropagation).off("click", layerSpy);
|
||||
});
|
||||
|
||||
it("DOM events fired on canvas polygon are propagated only once to the map even when two layers contains the event", function () {
|
||||
var spy = sinon.spy();
|
||||
var layer2 = L.polygon(latLngs).addTo(map);
|
||||
map.on("click", spy);
|
||||
happen.at('click', 50, 50);
|
||||
expect(spy.callCount).to.eql(1);
|
||||
layer2.remove();
|
||||
map.off("click", spy);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
@ -644,14 +644,6 @@ describe("Map", function () {
|
||||
expect(spy.calledOnce).to.be.ok();
|
||||
});
|
||||
|
||||
it("DOM events propagate from canvas polygon to map", function () {
|
||||
var spy = sinon.spy();
|
||||
map.on("mousemove", spy);
|
||||
var layer = new L.Polygon([[1, 2], [3, 4], [5, 6]], {rendered: L.canvas()}).addTo(map);
|
||||
happen.mousemove(layer._path);
|
||||
expect(spy.calledOnce).to.be.ok();
|
||||
});
|
||||
|
||||
it("DOM events propagate from marker to map", function () {
|
||||
var spy = sinon.spy();
|
||||
map.on("mousemove", spy);
|
||||
@ -682,17 +674,6 @@ describe("Map", function () {
|
||||
expect(mapSpy.called).not.to.be.ok();
|
||||
});
|
||||
|
||||
it("DOM events fired on canvas polygon can be cancelled before being caught by the map", function () {
|
||||
var mapSpy = sinon.spy();
|
||||
var layerSpy = sinon.spy();
|
||||
map.on("mousemove", mapSpy);
|
||||
var layer = new L.Polygon([[1, 2], [3, 4], [5, 6]], {rendered: L.canvas()}).addTo(map);
|
||||
layer.on("mousemove", L.DomEvent.stopPropagation).on("mousemove", layerSpy);
|
||||
happen.mousemove(layer._path);
|
||||
expect(layerSpy.calledOnce).to.be.ok();
|
||||
expect(mapSpy.called).not.to.be.ok();
|
||||
});
|
||||
|
||||
it("mouseout is forwarded if fired on the original target", function () {
|
||||
var mapSpy = sinon.spy(),
|
||||
layerSpy = sinon.spy(),
|
||||
|
@ -61,6 +61,7 @@ L.Canvas = L.Renderer.extend({
|
||||
|
||||
_removePath: function (layer) {
|
||||
layer._removed = true;
|
||||
delete this._layers[L.stamp(layer)];
|
||||
this._requestRedraw(layer);
|
||||
},
|
||||
|
||||
@ -201,14 +202,17 @@ L.Canvas = L.Renderer.extend({
|
||||
// so we emulate that by calculating what's under the mouse on mousemove/click manually
|
||||
|
||||
_onClick: function (e) {
|
||||
var point = this._map.mouseEventToLayerPoint(e);
|
||||
var point = this._map.mouseEventToLayerPoint(e), layers = [];
|
||||
|
||||
for (var id in this._layers) {
|
||||
if (this._layers[id]._containsPoint(point)) {
|
||||
L.DomEvent._fakeStop(e);
|
||||
this._fireEvent(this._layers[id], e);
|
||||
layers.push(this._layers[id]);
|
||||
}
|
||||
}
|
||||
if (layers.length) {
|
||||
this._fireEvent(layers, e);
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseMove: function (e) {
|
||||
@ -225,7 +229,7 @@ L.Canvas = L.Renderer.extend({
|
||||
if (layer && (e.type === 'mouseout' || !layer._containsPoint(point))) {
|
||||
// if we're leaving the layer, fire mouseout
|
||||
L.DomUtil.removeClass(this._container, 'leaflet-interactive');
|
||||
this._fireEvent(layer, e, 'mouseout');
|
||||
this._fireEvent([layer], e, 'mouseout');
|
||||
this._hoveredLayer = null;
|
||||
}
|
||||
},
|
||||
@ -237,19 +241,19 @@ L.Canvas = L.Renderer.extend({
|
||||
layer = this._drawnLayers[id];
|
||||
if (layer.options.interactive && layer._containsPoint(point)) {
|
||||
L.DomUtil.addClass(this._container, 'leaflet-interactive'); // change cursor
|
||||
this._fireEvent(layer, e, 'mouseover');
|
||||
this._fireEvent([layer], e, 'mouseover');
|
||||
this._hoveredLayer = layer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._hoveredLayer) {
|
||||
this._fireEvent(this._hoveredLayer, e);
|
||||
this._fireEvent([this._hoveredLayer], e);
|
||||
}
|
||||
},
|
||||
|
||||
_fireEvent: function (layer, e, type) {
|
||||
this._map._fireDOMEvent(e, type || e.type, [layer]);
|
||||
_fireEvent: function (layers, e, type) {
|
||||
this._map._fireDOMEvent(e, type || e.type, layers);
|
||||
},
|
||||
|
||||
// TODO _bringToFront & _bringToBack, pretty tricky
|
||||
|
@ -688,6 +688,8 @@ L.Map = L.Evented.extend({
|
||||
|
||||
_fireDOMEvent: function (e, type, targets) {
|
||||
|
||||
if (e._stopped) { return; }
|
||||
|
||||
targets = (targets || []).concat(this._findEventTargets(e, type));
|
||||
|
||||
if (!targets.length) { return; }
|
||||
|
Loading…
Reference in New Issue
Block a user