Implement getFeatures() for ol/layer/VectorImage

This commit is contained in:
Andreas Hocevar
2019-10-22 11:19:07 +02:00
parent a3c137cff1
commit 39012a58f8
4 changed files with 121 additions and 26 deletions

View File

@@ -56,35 +56,32 @@ const featureOverlay = new VectorLayer({
let highlight;
const displayFeatureInfo = function(pixel) {
const feature = map.forEachFeatureAtPixel(pixel, function(feature) {
return feature;
});
map.getLayers().item(0).getFeatures(pixel).then(function(features) {
const feature = features.length > 0 ? features[0] : undefined;
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);
}
const info = document.getElementById('info');
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) {
if (evt.dragging) {
return;
if (!evt.dragging) {
displayFeatureInfo(evt.pixel);
}
const pixel = map.getEventPixel(evt.originalEvent);
displayFeatureInfo(pixel);
});
map.on('click', function(evt) {

View File

@@ -10,6 +10,7 @@ import CanvasVectorLayerRenderer from './VectorLayer.js';
import EventType from '../../events/EventType.js';
import ImageState from '../../ImageState.js';
import {renderDeclutterItems} from '../../render.js';
import {apply, compose, create} from '../../transform.js';
/**
* @classdesc
@@ -36,6 +37,18 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
*/
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();
}
/**
* @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
*/
@@ -68,16 +97,15 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
renderedExtent = renderedExtent.slice(0);
scaleFromCenter(renderedExtent, this.layerImageRatio_);
}
const width = getWidth(renderedExtent) / viewResolution;
const height = getHeight(renderedExtent) / viewResolution;
if (!hints[ViewHint.ANIMATING] && !hints[ViewHint.INTERACTING] && !isEmpty(renderedExtent)) {
vectorRenderer.useContainer(null, null, 1);
const context = vectorRenderer.context;
const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign({}, frameState, {
declutterItems: [],
size: [
getWidth(renderedExtent) / viewResolution,
getHeight(renderedExtent) / viewResolution
],
size: [width, height],
viewState: /** @type {import("../../View.js").State} */ (assign({}, frameState.viewState, {
rotation: 0
}))
@@ -102,7 +130,14 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
const image = this.image_;
const imageResolution = image.getResolution();
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_;

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();
});
});
});
});

View File

@@ -3,6 +3,7 @@ import VectorSource from '../../../../../src/ol/source/Vector.js';
import CanvasVectorImageLayerRenderer from '../../../../../src/ol/renderer/canvas/VectorImageLayer.js';
import {get as getProjection} from '../../../../../src/ol/proj.js';
import {scaleFromCenter} from '../../../../../src/ol/extent.js';
import {create} from '../../../../../src/ol/transform.js';
describe('ol/renderer/canvas/VectorImageLayer', function() {
@@ -39,6 +40,7 @@ describe('ol/renderer/canvas/VectorImageLayer', function() {
layerIndex: 0,
extent: extent,
viewHints: [],
pixelToCoordinateTransform: create(),
viewState: {
center: [0, 0],
projection: projection,