Add back Select interaction without Overlay

This commit is contained in:
Tobias Kohr
2019-09-25 16:25:00 +02:00
parent 38124d770b
commit 2ccaed0ace
2 changed files with 52 additions and 86 deletions

View File

@@ -9,10 +9,9 @@ import {singleClick, never, shiftKeyOnly, pointerMove} from '../events/condition
import {TRUE} from '../functions.js'; import {TRUE} from '../functions.js';
import GeometryType from '../geom/GeometryType.js'; import GeometryType from '../geom/GeometryType.js';
import Interaction from './Interaction.js'; import Interaction from './Interaction.js';
import VectorLayer from '../layer/Vector.js';
import {clear} from '../obj.js'; import {clear} from '../obj.js';
import VectorSource from '../source/Vector.js';
import {createEditingStyle} from '../style/Style.js'; import {createEditingStyle} from '../style/Style.js';
import Collection from '../Collection.js';
/** /**
@@ -205,23 +204,25 @@ class Select extends Interaction {
*/ */
this.hitTolerance_ = options.hitTolerance ? options.hitTolerance : 0; this.hitTolerance_ = options.hitTolerance ? options.hitTolerance : 0;
const featureOverlay = new VectorLayer({ /**
source: new VectorSource({ * @private
useSpatialIndex: false, * @type {import("../style/Style.js").default|Array.<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction|null}
features: options.features, */
wrapX: options.wrapX this.style_ = options.style ? options.style : getDefaultStyleFunction();
}),
style: options.style ? options.style : /**
getDefaultStyleFunction(), * An association between selected feature (key)
updateWhileAnimating: true, * and original style (value)
updateWhileInteracting: true * @private
}); * @type {Object.<number, import("../style/Style.js").default|Array.<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction>}
*/
this.featureStyleAssociation_ = {};
/** /**
* @private * @private
* @type {VectorLayer} * @type {import("../Collection.js").default}
*/ */
this.featureOverlay_ = featureOverlay; this.features_ = options.features || new Collection();
/** @type {function(import("../layer/Layer.js").default): boolean} */ /** @type {function(import("../layer/Layer.js").default): boolean} */
let layerFilter; let layerFilter;
@@ -272,7 +273,7 @@ class Select extends Interaction {
* @api * @api
*/ */
getFeatures() { getFeatures() {
return this.featureOverlay_.getSource().getFeaturesCollection(); return this.features_;
} }
/** /**
@@ -290,24 +291,15 @@ class Select extends Interaction {
* programmatic method like pushing features to * programmatic method like pushing features to
* {@link module:ol/interaction/Select~Select#getFeatures collection}. * {@link module:ol/interaction/Select~Select#getFeatures collection}.
* @param {import("../Feature.js").FeatureLike} feature Feature * @param {import("../Feature.js").FeatureLike} feature Feature
* @return {VectorLayer} Layer. * @return {import('../layer/Vector.js').default} Layer.
* @api * @api
*/ */
getLayer(feature) { getLayer(feature) {
return ( return (
/** @type {VectorLayer} */ (this.featureLayerAssociation_[getUid(feature)]) /** @type {import('../layer/Vector.js').default} */ (this.featureLayerAssociation_[getUid(feature)])
); );
} }
/**
* Get the overlay layer that this interaction renders selected features to.
* @return {VectorLayer} Overlay layer.
* @api
*/
getOverlay() {
return this.featureOverlay_;
}
/** /**
* Hit-detection tolerance. Pixels inside the radius around the given position * Hit-detection tolerance. Pixels inside the radius around the given position
* will be checked for features. * will be checked for features.
@@ -327,14 +319,12 @@ class Select extends Interaction {
*/ */
setMap(map) { setMap(map) {
const currentMap = this.getMap(); const currentMap = this.getMap();
const selectedFeatures = this.getFeatures(); if (currentMap && this.style_) {
if (currentMap) { this.features_.forEach(this.removeSelectedStyle_.bind(this));
selectedFeatures.forEach(currentMap.unskipFeature.bind(currentMap));
} }
super.setMap(map); super.setMap(map);
this.featureOverlay_.setMap(map); if (map && this.style_) {
if (map) { this.features_.forEach(this.giveSelectedStyle_.bind(this));
selectedFeatures.forEach(map.skipFeature.bind(map));
} }
} }
@@ -343,9 +333,9 @@ class Select extends Interaction {
* @private * @private
*/ */
addFeature_(evt) { addFeature_(evt) {
const map = this.getMap(); const feature = evt.element;
if (map) { if (this.style_) {
map.skipFeature(/** @type {import("../Feature.js").default} */ (evt.element)); this.giveSelectedStyle_(feature);
} }
} }
@@ -354,12 +344,32 @@ class Select extends Interaction {
* @private * @private
*/ */
removeFeature_(evt) { removeFeature_(evt) {
const map = this.getMap(); const feature = evt.element;
if (map) { if (this.style_) {
map.unskipFeature(/** @type {import("../Feature.js").default} */ (evt.element)); this.removeSelectedStyle_(feature);
} }
} }
/**
* @param {import("../Feature.js").default} feature Feature
* @private
*/
giveSelectedStyle_(feature) {
const key = getUid(feature);
this.featureStyleAssociation_[key] = feature.getStyle();
feature.setStyle(this.style_);
}
/**
* @param {import("../Feature.js").default} feature Feature
* @private
*/
removeSelectedStyle_(feature) {
const key = getUid(feature);
feature.setStyle(this.featureStyleAssociation_[key]);
delete this.featureStyleAssociation_[key];
}
/** /**
* @param {import("../Feature.js").FeatureLike} feature Feature. * @param {import("../Feature.js").FeatureLike} feature Feature.
* @private * @private
@@ -471,7 +481,7 @@ function getDefaultStyleFunction() {
extend(styles[GeometryType.POLYGON], styles[GeometryType.LINE_STRING]); extend(styles[GeometryType.POLYGON], styles[GeometryType.LINE_STRING]);
extend(styles[GeometryType.GEOMETRY_COLLECTION], styles[GeometryType.LINE_STRING]); extend(styles[GeometryType.GEOMETRY_COLLECTION], styles[GeometryType.LINE_STRING]);
return function(feature, resolution) { return function(feature) {
if (!feature.getGeometry()) { if (!feature.getGeometry()) {
return null; return null;
} }

View File

@@ -259,10 +259,10 @@ describe('ol.interaction.Select', function() {
simulateEvent('singleclick', 10, -20, true); simulateEvent('singleclick', 10, -20, true);
expect(listenerSpy.callCount).to.be(2); expect(listenerSpy.callCount).to.be(1);
features = select.getFeatures(); features = select.getFeatures();
expect(features.getLength()).to.equal(0); expect(features.getLength()).to.equal(4);
}); });
}); });
@@ -377,8 +377,6 @@ describe('ol.interaction.Select', function() {
map.addInteraction(interaction); map.addInteraction(interaction);
expect(interaction.featureOverlay_).not.to.be(null);
simulateEvent('singleclick', 10, -20); simulateEvent('singleclick', 10, -20);
}); });
@@ -406,46 +404,4 @@ describe('ol.interaction.Select', function() {
}); });
}); });
describe('#setMap()', function() {
let interaction;
beforeEach(function() {
interaction = new Select();
expect(interaction.getActive()).to.be(true);
});
describe('#setMap(null)', function() {
beforeEach(function() {
map.addInteraction(interaction);
});
afterEach(function() {
map.removeInteraction(interaction);
});
describe('#setMap(null) when interaction is active', function() {
it('unsets the map from the feature overlay', function() {
const spy = sinon.spy(interaction.featureOverlay_, 'setMap');
interaction.setMap(null);
expect(spy.getCall(0).args[0]).to.be(null);
});
});
});
describe('#setMap(map)', function() {
describe('#setMap(map) when interaction is active', function() {
it('sets the map into the feature overlay', function() {
const spy = sinon.spy(interaction.featureOverlay_, 'setMap');
interaction.setMap(map);
expect(spy.getCall(0).args[0]).to.be(map);
});
});
});
});
describe('#getOverlay', function() {
it('returns the feature overlay layer', function() {
const select = new Select();
expect (select.getOverlay()).to.eql(select.featureOverlay_);
});
});
}); });