Merge pull request #10161 from ahocevar/vectorimage-getfeatures

Implement getFeatures() for ol/layer/VectorImage
This commit is contained in:
Andreas Hocevar
2019-10-23 11:26:08 +02:00
committed by GitHub
4 changed files with 121 additions and 26 deletions
+18 -21
View File
@@ -56,35 +56,32 @@ const featureOverlay = new VectorLayer({
let highlight; let highlight;
const displayFeatureInfo = function(pixel) { const displayFeatureInfo = function(pixel) {
const feature = map.forEachFeatureAtPixel(pixel, function(feature) { map.getLayers().item(0).getFeatures(pixel).then(function(features) {
return feature; const feature = features.length > 0 ? features[0] : undefined;
});
const info = document.getElementById('info'); const info = document.getElementById('info');
if (feature) {
info.innerHTML = feature.getId() + ': ' + feature.get('name');
} else {
info.innerHTML = ' ';
}
if (feature !== highlight) {
if (highlight) {
featureOverlay.getSource().removeFeature(highlight);
}
if (feature) { if (feature) {
featureOverlay.getSource().addFeature(feature); info.innerHTML = feature.getId() + ': ' + feature.get('name');
} else {
info.innerHTML = ' ';
} }
highlight = feature;
}
if (feature !== highlight) {
if (highlight) {
featureOverlay.getSource().removeFeature(highlight);
}
if (feature) {
featureOverlay.getSource().addFeature(feature);
}
highlight = feature;
}
});
}; };
map.on('pointermove', function(evt) { map.on('pointermove', function(evt) {
if (evt.dragging) { if (!evt.dragging) {
return; displayFeatureInfo(evt.pixel);
} }
const pixel = map.getEventPixel(evt.originalEvent);
displayFeatureInfo(pixel);
}); });
map.on('click', function(evt) { map.on('click', function(evt) {
+40 -5
View File
@@ -10,6 +10,7 @@ import CanvasVectorLayerRenderer from './VectorLayer.js';
import EventType from '../../events/EventType.js'; import EventType from '../../events/EventType.js';
import ImageState from '../../ImageState.js'; import ImageState from '../../ImageState.js';
import {renderDeclutterItems} from '../../render.js'; import {renderDeclutterItems} from '../../render.js';
import {apply, compose, create} from '../../transform.js';
/** /**
* @classdesc * @classdesc
@@ -36,6 +37,18 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
*/ */
this.layerImageRatio_ = layer.getImageRatio(); this.layerImageRatio_ = layer.getImageRatio();
/**
* @private
* @type {import("../../transform.js").Transform};
*/
this.coordinateToVectorPixelTransform_ = create();
/**
* @private
* @type {import("../../transform.js").Transform};
*/
this.renderedPixelToCoordinateTransform_ = null;
} }
/** /**
@@ -46,6 +59,22 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
super.disposeInternal(); super.disposeInternal();
} }
/**
* @inheritDoc
*/
getFeatures(pixel) {
if (this.vectorRenderer_) {
const vectorPixel = apply(this.coordinateToVectorPixelTransform_,
apply(this.renderedPixelToCoordinateTransform_, pixel.slice()));
return this.vectorRenderer_.getFeatures(vectorPixel);
} else {
const promise = new Promise(function(resolve, reject) {
resolve([]);
});
return promise;
}
}
/** /**
* @inheritDoc * @inheritDoc
*/ */
@@ -68,16 +97,15 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
renderedExtent = renderedExtent.slice(0); renderedExtent = renderedExtent.slice(0);
scaleFromCenter(renderedExtent, this.layerImageRatio_); scaleFromCenter(renderedExtent, this.layerImageRatio_);
} }
const width = getWidth(renderedExtent) / viewResolution;
const height = getHeight(renderedExtent) / viewResolution;
if (!hints[ViewHint.ANIMATING] && !hints[ViewHint.INTERACTING] && !isEmpty(renderedExtent)) { if (!hints[ViewHint.ANIMATING] && !hints[ViewHint.INTERACTING] && !isEmpty(renderedExtent)) {
vectorRenderer.useContainer(null, null, 1); vectorRenderer.useContainer(null, null, 1);
const context = vectorRenderer.context; const context = vectorRenderer.context;
const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign({}, frameState, { const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign({}, frameState, {
declutterItems: [], declutterItems: [],
size: [ size: [width, height],
getWidth(renderedExtent) / viewResolution,
getHeight(renderedExtent) / viewResolution
],
viewState: /** @type {import("../../View.js").State} */ (assign({}, frameState.viewState, { viewState: /** @type {import("../../View.js").State} */ (assign({}, frameState.viewState, {
rotation: 0 rotation: 0
})) }))
@@ -102,7 +130,14 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
const image = this.image_; const image = this.image_;
const imageResolution = image.getResolution(); const imageResolution = image.getResolution();
const imagePixelRatio = image.getPixelRatio(); const imagePixelRatio = image.getPixelRatio();
this.renderedResolution = imageResolution * pixelRatio / imagePixelRatio; const renderedResolution = imageResolution * pixelRatio / imagePixelRatio;
this.renderedResolution = renderedResolution;
this.renderedPixelToCoordinateTransform_ = frameState.pixelToCoordinateTransform.slice();
this.coordinateToVectorPixelTransform_ = compose(this.coordinateToVectorPixelTransform_,
width / 2, height / 2,
1 / renderedResolution, -1 / renderedResolution,
0,
-viewState.center[0], -viewState.center[1]);
} }
return !!this.image_; return !!this.image_;
+61
View File
@@ -0,0 +1,61 @@
import Feature from '../../../../src/ol/Feature.js';
import Point from '../../../../src/ol/geom/Point.js';
import Map from '../../../../src/ol/Map.js';
import View from '../../../../src/ol/View.js';
import VectorImageLayer from '../../../../src/ol/layer/VectorImage.js';
import VectorSource from '../../../../src/ol/source/Vector.js';
describe('ol/layer/VectorImage', function() {
describe('#getFeatures()', function() {
let map, layer;
beforeEach(function() {
layer = new VectorImageLayer({
source: new VectorSource({
features: [
new Feature({
geometry: new Point([-1000000, 0]),
name: 'feature1'
}),
new Feature({
geometry: new Point([1000000, 0]),
name: 'feture2'
})
]
})
});
const container = document.createElement('div');
container.style.width = '256px';
container.style.height = '256px';
document.body.appendChild(container);
map = new Map({
target: container,
layers: [
layer
],
view: new View({
zoom: 2,
center: [0, 0]
})
});
});
afterEach(function() {
document.body.removeChild(map.getTargetElement());
map.setTarget(null);
});
it('detects features properly', function(done) {
map.renderSync();
const pixel = map.getPixelFromCoordinate([-1000000, 0]);
layer.getFeatures(pixel).then(function(features) {
expect(features[0].get('name')).to.be('feature1');
done();
});
});
});
});
@@ -3,6 +3,7 @@ import VectorSource from '../../../../../src/ol/source/Vector.js';
import CanvasVectorImageLayerRenderer from '../../../../../src/ol/renderer/canvas/VectorImageLayer.js'; import CanvasVectorImageLayerRenderer from '../../../../../src/ol/renderer/canvas/VectorImageLayer.js';
import {get as getProjection} from '../../../../../src/ol/proj.js'; import {get as getProjection} from '../../../../../src/ol/proj.js';
import {scaleFromCenter} from '../../../../../src/ol/extent.js'; import {scaleFromCenter} from '../../../../../src/ol/extent.js';
import {create} from '../../../../../src/ol/transform.js';
describe('ol/renderer/canvas/VectorImageLayer', function() { describe('ol/renderer/canvas/VectorImageLayer', function() {
@@ -39,6 +40,7 @@ describe('ol/renderer/canvas/VectorImageLayer', function() {
layerIndex: 0, layerIndex: 0,
extent: extent, extent: extent,
viewHints: [], viewHints: [],
pixelToCoordinateTransform: create(),
viewState: { viewState: {
center: [0, 0], center: [0, 0],
projection: projection, projection: projection,