Skip to content

Commit 37e1d9d

Browse files
committed
fix: use singleclick instead of click to avoid bugs
1 parent 24b2357 commit 37e1d9d

File tree

4 files changed

+89
-57
lines changed

4 files changed

+89
-57
lines changed

cypress/integration/control/modify.spec.js

+28-25
Original file line numberDiff line numberDiff line change
@@ -48,33 +48,35 @@ describe('ModifyControl', () => {
4848
.click(102, 152)
4949
.then(() => {
5050
// singleclick event needs a timeout period.
51-
// cy.wait(400).then(() => {
52-
selectedFeaturesArray = win.modify.selectModify
53-
.getFeatures()
54-
.getArray();
55-
// Verify one polygon node was deleted on click (3 nodes, 4 coordinates)
56-
expect(
57-
selectedFeaturesArray[0].getGeometry().getCoordinates()[0].length,
58-
).to.equal(4);
51+
cy.wait(400).then(() => {
52+
selectedFeaturesArray = win.modify.selectModify
53+
.getFeatures()
54+
.getArray();
55+
// Verify one polygon node was deleted on click (3 nodes, 4 coordinates)
56+
expect(
57+
selectedFeaturesArray[0].getGeometry().getCoordinates()[0].length,
58+
).to.equal(4);
59+
});
5960
});
6061

6162
// Click another node (click on map canvas at node pixel)
6263
cy.get('.ol-viewport')
6364
.click(100, 100, FORCE)
6465
.then(() => {
6566
// singleclick event needs a timeout period.
66-
// cy.wait(400).then(() => {
67-
// Verify no further node was deleted on click (because polygon minimum number nodes is 3)
68-
expect(
69-
selectedFeaturesArray[0].getGeometry().getCoordinates()[0].length,
70-
).to.equal(4);
71-
// Check that no features from the overlay are mistakenly selected
72-
const toTest = omitFeatureSelectSpy.withArgs(
73-
omitFeatureSelectSpy.args[0][0],
74-
null,
75-
);
76-
// eslint-disable-next-line no-unused-expressions
77-
expect(toTest).to.not.be.called;
67+
cy.wait(400).then(() => {
68+
// Verify no further node was deleted on click (because polygon minimum number nodes is 3)
69+
expect(
70+
selectedFeaturesArray[0].getGeometry().getCoordinates()[0].length,
71+
).to.equal(4);
72+
// Check that no features from the overlay are mistakenly selected
73+
const toTest = omitFeatureSelectSpy.withArgs(
74+
omitFeatureSelectSpy.args[0][0],
75+
null,
76+
);
77+
// eslint-disable-next-line no-unused-expressions
78+
expect(toTest).to.not.be.called;
79+
});
7880
});
7981

8082
// Select line (double click line in map canvas container to start modifying)
@@ -97,11 +99,12 @@ describe('ModifyControl', () => {
9799
.click(270, 344, FORCE)
98100
.then(() => {
99101
// singleclick event needs a timeout period.
100-
// cy.wait(400).then(() => {
101-
// Verify one line node was deleted on click (2 nodes, 2 coordinates)
102-
expect(
103-
selectedFeaturesArray[0].getGeometry().getCoordinates().length,
104-
).to.equal(2);
102+
cy.wait(400).then(() => {
103+
// Verify one line node was deleted on click (2 nodes, 2 coordinates)
104+
expect(
105+
selectedFeaturesArray[0].getGeometry().getCoordinates().length,
106+
).to.equal(2);
107+
});
105108
});
106109

107110
// Click another node (click on map canvas at node pixel)

index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io/en/v6.4.3/build/ol.js"></script>
1515
<script src="https://unpkg.com/[email protected]/dist/mapbox-gl.js"></script>
1616
<script src="https://unpkg.com/[email protected]/dist/jsts.min.js"></script>
17-
<script src="build/index.js"></script>
17+
<script src="index.js"></script>
1818
<div id="app">
1919
<div id="header">
2020
<nav>

src/control/modify.js

+58-29
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Modify } from 'ol/interaction';
2-
import { click } from 'ol/events/condition';
1+
import { Modify, Interaction } from 'ol/interaction';
2+
import { singleClick } from 'ol/events/condition';
33
import Control from './control';
44
import image from '../../img/modify_geometry2.svg';
55
import SelectMove from '../interaction/selectmove';
@@ -23,7 +23,7 @@ class ModifyControl extends Control {
2323
* @param {Object} [options.moveInteractionOptions] Options for the move interaction.
2424
* @param {Object} [options.modifyInteractionOptions] Options for the modify interaction.
2525
* @param {Object} [options.deleteInteractionOptions] Options for the delete interaction.
26-
*
26+
* @param {Object} [options.deselectInteractionOptions] Options for the deselect interaction. Default: features are deselected on click on map.
2727
*/
2828
constructor(options) {
2929
super({
@@ -70,15 +70,13 @@ class ModifyControl extends Control {
7070
this.cursorFilter = options.cursorFilter || (() => true);
7171
this.cursorHandler = this.cursorHandler.bind(this);
7272

73-
/* onClickOutsideFeatures management */
74-
this.onClickOutsideFeatures = this.onClickOutsideFeatures.bind(this);
75-
7673
/* Interactions */
7774
this.createSelectMoveInteraction(options.selectMoveOptions);
7875
this.createSelectModifyInteraction(options.selectModifyOptions);
7976
this.createModifyInteraction(options.modifyInteractionOptions);
8077
this.createMoveInteraction(options.moveInteractionOptions);
8178
this.createDeleteInteraction(options.deleteInteractionOptions);
79+
this.createDeselectInteraction(options.deselectInteractionOptions);
8280
}
8381

8482
/**
@@ -156,6 +154,7 @@ class ModifyControl extends Control {
156154
/**
157155
* Create the interaction used to move feature.
158156
* @param {*} options
157+
* @private
159158
*/
160159
createMoveInteraction(options = {}) {
161160
/**
@@ -182,6 +181,7 @@ class ModifyControl extends Control {
182181
/**
183182
* Create the interaction used to modify vertexes of features.
184183
* @param {*} options
184+
* @private
185185
*/
186186
createModifyInteraction(options = {}) {
187187
/**
@@ -190,7 +190,7 @@ class ModifyControl extends Control {
190190
*/
191191
this.modifyInteraction = new Modify({
192192
features: this.selectModify.getFeatures(),
193-
deleteCondition: click,
193+
deleteCondition: singleClick,
194194
...options,
195195
});
196196

@@ -209,6 +209,7 @@ class ModifyControl extends Control {
209209
/**
210210
* Create the interaction used to delete selected features.
211211
* @param {*} options
212+
* @private
212213
*/
213214
createDeleteInteraction(options = {}) {
214215
/**
@@ -223,6 +224,42 @@ class ModifyControl extends Control {
223224
this.deleteInteraction.setActive(false);
224225
}
225226

227+
/**
228+
* Create the interaction used to deselected features when we click on the map.
229+
* @param {*} options
230+
* @private
231+
*/
232+
createDeselectInteraction(options = {}) {
233+
// it's important that this condition was the same as the selectModify's
234+
// deleteCondition to avoid the selection of the feature under the node to delete.
235+
const condition = options.condition || singleClick;
236+
237+
/**
238+
* @type {ol.interaction.Interaction}
239+
* @private
240+
*/
241+
this.deselectInteraction = new Interaction({
242+
handleEvent: (mapBrowserEvent) => {
243+
if (!condition(mapBrowserEvent)) {
244+
return true;
245+
}
246+
const onFeature = this.getFeatureAtPixel(mapBrowserEvent.pixel);
247+
const onVertex = this.isHoverVertexFeatureAtPixel(
248+
mapBrowserEvent.pixel,
249+
);
250+
251+
if (!onVertex && !onFeature) {
252+
// Default: Clear selection on click outside features.
253+
this.selectMove.getFeatures().clear();
254+
this.selectModify.getFeatures().clear();
255+
return false;
256+
}
257+
return true;
258+
},
259+
});
260+
this.deselectInteraction.setActive(false);
261+
}
262+
226263
/**
227264
* Get a selectable feature at a pixel.
228265
* @param {*} pixel
@@ -324,36 +361,19 @@ class ModifyControl extends Control {
324361
}
325362
}
326363

327-
/**
328-
* Clear selection on map's singleclick event.
329-
* @param {*} evt
330-
* @private
331-
*/
332-
onClickOutsideFeatures(evt) {
333-
if (!this.getActive()) {
334-
return;
335-
}
336-
const onFeature = this.getFeatureAtPixel(evt.pixel);
337-
const onVertex = this.isHoverVertexFeatureAtPixel(evt.pixel);
338-
339-
if (!onVertex && !onFeature) {
340-
// Default: Clear selection on click outside features.
341-
this.selectMove.getFeatures().clear();
342-
this.selectModify.getFeatures().clear();
343-
}
344-
}
345-
346364
setMap(map) {
347365
if (this.map) {
348366
this.map.removeInteraction(this.modifyInteraction);
349367
this.map.removeInteraction(this.moveInteraction);
350368
this.map.removeInteraction(this.selectMove);
351369
this.map.removeInteraction(this.selectModify);
352370
this.map.removeInteraction(this.deleteInteraction);
371+
this.map.removeInteraction(this.deselectInteraction);
353372
this.removeListeners();
354373
}
355374
super.setMap(map);
356375
this.addListeners();
376+
this.map.addInteraction(this.deselectInteraction);
357377
this.map.addInteraction(this.deleteInteraction);
358378
this.map.addInteraction(this.selectModify);
359379
// For the default behvior it's very important to add selectMove after selectModify.
@@ -363,16 +383,23 @@ class ModifyControl extends Control {
363383
this.map.addInteraction(this.modifyInteraction);
364384
}
365385

386+
/**
387+
* Add others listeners on the map than interactions.
388+
* @param {*} evt
389+
* @private
390+
*/
366391
addListeners() {
367392
this.removeListeners();
368-
// To avoid bug, it's important that this event is the same as for modify's deleteCondition.
369-
this.map.on('click', this.onClickOutsideFeatures);
370393
this.map.on('pointermove', this.cursorHandler);
371394
}
372395

396+
/**
397+
* Remove others listeners on the map than interactions.
398+
* @param {*} evt
399+
* @private
400+
*/
373401
removeListeners() {
374402
clearTimeout(this.cursorTimeout);
375-
this.map.un('click', this.onClickOutsideFeatures);
376403
this.map.un('pointermove', this.cursorHandler);
377404
}
378405

@@ -381,6 +408,7 @@ class ModifyControl extends Control {
381408
*/
382409
activate() {
383410
super.activate();
411+
this.deselectInteraction.setActive(true);
384412
this.deleteInteraction.setActive(true);
385413
this.selectModify.setActive(true);
386414
// For the default behavior it's very important to add selectMove after selectModify.
@@ -395,6 +423,7 @@ class ModifyControl extends Control {
395423
clearTimeout(this.cursorTimeout);
396424
this.selectMove.getFeatures().clear();
397425
this.selectModify.getFeatures().clear();
426+
this.deselectInteraction.setActive(false);
398427
this.deleteInteraction.setActive(false);
399428
this.selectModify.setActive(false);
400429
this.selectMove.setActive(false);

src/interaction/selectmove.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Select from 'ol/interaction/Select';
22
import { Circle, Style, Fill, Stroke } from 'ol/style';
3-
import { click } from 'ol/events/condition';
3+
import { singleClick } from 'ol/events/condition';
44

55
// Default style on moving geometries
66
const selectMoveStyle = new Style({
@@ -34,7 +34,7 @@ class SelectMove extends Select {
3434
*/
3535
constructor(options) {
3636
super({
37-
condition: click,
37+
condition: singleClick,
3838
style: selectMoveStyle,
3939
...options,
4040
});

0 commit comments

Comments
 (0)