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 GeometryType from '../geom/GeometryType.js';
import Interaction from './Interaction.js';
import VectorLayer from '../layer/Vector.js';
import {clear} from '../obj.js';
import VectorSource from '../source/Vector.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;
const featureOverlay = new VectorLayer({
source: new VectorSource({
useSpatialIndex: false,
features: options.features,
wrapX: options.wrapX
}),
style: options.style ? options.style :
getDefaultStyleFunction(),
updateWhileAnimating: true,
updateWhileInteracting: true
});
/**
* @private
* @type {import("../style/Style.js").default|Array.<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction|null}
*/
this.style_ = options.style ? options.style : getDefaultStyleFunction();
/**
* An association between selected feature (key)
* and original style (value)
* @private
* @type {Object.<number, import("../style/Style.js").default|Array.<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction>}
*/
this.featureStyleAssociation_ = {};
/**
* @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} */
let layerFilter;
@@ -272,7 +273,7 @@ class Select extends Interaction {
* @api
*/
getFeatures() {
return this.featureOverlay_.getSource().getFeaturesCollection();
return this.features_;
}
/**
@@ -290,24 +291,15 @@ class Select extends Interaction {
* programmatic method like pushing features to
* {@link module:ol/interaction/Select~Select#getFeatures collection}.
* @param {import("../Feature.js").FeatureLike} feature Feature
* @return {VectorLayer} Layer.
* @return {import('../layer/Vector.js').default} Layer.
* @api
*/
getLayer(feature) {
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
* will be checked for features.
@@ -327,14 +319,12 @@ class Select extends Interaction {
*/
setMap(map) {
const currentMap = this.getMap();
const selectedFeatures = this.getFeatures();
if (currentMap) {
selectedFeatures.forEach(currentMap.unskipFeature.bind(currentMap));
if (currentMap && this.style_) {
this.features_.forEach(this.removeSelectedStyle_.bind(this));
}
super.setMap(map);
this.featureOverlay_.setMap(map);
if (map) {
selectedFeatures.forEach(map.skipFeature.bind(map));
if (map && this.style_) {
this.features_.forEach(this.giveSelectedStyle_.bind(this));
}
}
@@ -343,9 +333,9 @@ class Select extends Interaction {
* @private
*/
addFeature_(evt) {
const map = this.getMap();
if (map) {
map.skipFeature(/** @type {import("../Feature.js").default} */ (evt.element));
const feature = evt.element;
if (this.style_) {
this.giveSelectedStyle_(feature);
}
}
@@ -354,12 +344,32 @@ class Select extends Interaction {
* @private
*/
removeFeature_(evt) {
const map = this.getMap();
if (map) {
map.unskipFeature(/** @type {import("../Feature.js").default} */ (evt.element));
const feature = evt.element;
if (this.style_) {
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.
* @private
@@ -471,7 +481,7 @@ function getDefaultStyleFunction() {
extend(styles[GeometryType.POLYGON], styles[GeometryType.LINE_STRING]);
extend(styles[GeometryType.GEOMETRY_COLLECTION], styles[GeometryType.LINE_STRING]);
return function(feature, resolution) {
return function(feature) {
if (!feature.getGeometry()) {
return null;
}

View File

@@ -259,10 +259,10 @@ describe('ol.interaction.Select', function() {
simulateEvent('singleclick', 10, -20, true);
expect(listenerSpy.callCount).to.be(2);
expect(listenerSpy.callCount).to.be(1);
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);
expect(interaction.featureOverlay_).not.to.be(null);
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_);
});
});
});