Create hit detection data per layer and without requestAnimationFrame

This commit is contained in:
Andreas Hocevar
2019-11-17 21:01:12 +01:00
parent 32932a7fd3
commit 9317ad850e
3 changed files with 48 additions and 53 deletions

View File

@@ -61,9 +61,9 @@ class VectorRenderTile extends Tile {
this.errorSourceTileKeys = {};
/**
* @type {ImageData}
* @type {Object<number, ImageData>}
*/
this.hitDetectionImageData = null;
this.hitDetectionImageData = {};
/**
* @private

View File

@@ -232,49 +232,45 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
getFeatures(pixel) {
return new Promise(function(resolve, reject) {
if (!this.hitDetectionImageData_ && !this.animatingOrInteracting_) {
requestAnimationFrame(function() {
const size = [this.context.canvas.width, this.context.canvas.height];
apply(this.pixelTransform, size);
const center = this.renderedCenter_;
const resolution = this.renderedResolution_;
const rotation = this.renderedRotation_;
const projection = this.renderedProjection_;
const extent = this.renderedExtent_;
const layer = this.getLayer();
const transforms = [];
const width = size[0] / 2;
const height = size[1] / 2;
transforms.push(this.getRenderTransform(center, resolution, rotation, 0.5, width, height, 0).slice());
const source = layer.getSource();
const projectionExtent = projection.getExtent();
if (source.getWrapX() && projection.canWrapX() && !containsExtent(projectionExtent, extent)) {
let startX = extent[0];
const worldWidth = getWidth(projectionExtent);
let world = 0;
let offsetX;
while (startX < projectionExtent[0]) {
--world;
offsetX = worldWidth * world;
transforms.push(this.getRenderTransform(center, resolution, rotation, 0.5, width, height, offsetX).slice());
startX += worldWidth;
}
world = 0;
startX = extent[2];
while (startX > projectionExtent[2]) {
++world;
offsetX = worldWidth * world;
transforms.push(this.getRenderTransform(center, resolution, rotation, 0.5, width, height, offsetX).slice());
startX -= worldWidth;
}
const size = [this.context.canvas.width, this.context.canvas.height];
apply(this.pixelTransform, size);
const center = this.renderedCenter_;
const resolution = this.renderedResolution_;
const rotation = this.renderedRotation_;
const projection = this.renderedProjection_;
const extent = this.renderedExtent_;
const layer = this.getLayer();
const transforms = [];
const width = size[0] / 2;
const height = size[1] / 2;
transforms.push(this.getRenderTransform(center, resolution, rotation, 0.5, width, height, 0).slice());
const source = layer.getSource();
const projectionExtent = projection.getExtent();
if (source.getWrapX() && projection.canWrapX() && !containsExtent(projectionExtent, extent)) {
let startX = extent[0];
const worldWidth = getWidth(projectionExtent);
let world = 0;
let offsetX;
while (startX < projectionExtent[0]) {
--world;
offsetX = worldWidth * world;
transforms.push(this.getRenderTransform(center, resolution, rotation, 0.5, width, height, offsetX).slice());
startX += worldWidth;
}
world = 0;
startX = extent[2];
while (startX > projectionExtent[2]) {
++world;
offsetX = worldWidth * world;
transforms.push(this.getRenderTransform(center, resolution, rotation, 0.5, width, height, offsetX).slice());
startX -= worldWidth;
}
}
this.hitDetectionImageData_ = createHitDetectionImageData(size, transforms,
this.renderedFeatures_, layer.getStyleFunction(), extent, resolution, rotation);
resolve(hitDetect(pixel, this.renderedFeatures_, this.hitDetectionImageData_));
}.bind(this));
} else {
resolve(hitDetect(pixel, this.renderedFeatures_, this.hitDetectionImageData_));
this.hitDetectionImageData_ = createHitDetectionImageData(size, transforms,
this.renderedFeatures_, layer.getStyleFunction(), extent, resolution, rotation);
}
resolve(hitDetect(pixel, this.renderedFeatures_, this.hitDetectionImageData_));
}.bind(this));
}

View File

@@ -221,7 +221,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
executorGroups[i].dispose();
}
}
tile.hitDetectionImageData = null;
delete tile.hitDetectionImageData[layerUid];
tile.executorGroups[layerUid] = [];
for (let t = 0, tt = sourceTiles.length; t < tt; ++t) {
const sourceTile = sourceTiles[t];
@@ -341,6 +341,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
getFeatures(pixel) {
return new Promise(function(resolve, reject) {
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
const layerUid = getUid(layer);
const source = layer.getSource();
const projection = this.renderedProjection;
const projectionExtent = projection.getExtent();
@@ -377,7 +378,8 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
const features = tile.getSourceTiles().reduce(function(accumulator, sourceTile) {
return accumulator.concat(sourceTile.getFeatures());
}, []);
if (!tile.hitDetectionImageData) {
let hitDetectionImageData = tile.hitDetectionImageData[layerUid];
if (!hitDetectionImageData && !this.animatingOrInteracting_) {
const tileSize = toSize(tileGrid.getTileSize(tileGrid.getZForResolution(resolution)));
const size = [tileSize[0] / 2, tileSize[1] / 2];
const rotation = this.renderedRotation_;
@@ -385,16 +387,13 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
this.getRenderTransform(tileGrid.getTileCoordCenter(tile.wrappedTileCoord),
resolution, 0, 0.5, size[0], size[1], 0)
];
requestAnimationFrame(function() {
tile.hitDetectionImageData = createHitDetectionImageData(tileSize, transforms,
features, layer.getStyleFunction(),
tileGrid.getTileCoordExtent(tile.wrappedTileCoord),
tile.getReplayState(layer).renderedResolution, rotation);
resolve(hitDetect(tilePixel, features, tile.hitDetectionImageData));
});
} else {
resolve(hitDetect(tilePixel, features, tile.hitDetectionImageData));
hitDetectionImageData = createHitDetectionImageData(tileSize, transforms,
features, layer.getStyleFunction(),
tileGrid.getTileCoordExtent(tile.wrappedTileCoord),
tile.getReplayState(layer).renderedResolution, rotation);
tile.hitDetectionImageData[layerUid] = hitDetectionImageData;
}
resolve(hitDetect(tilePixel, features, hitDetectionImageData));
}.bind(this));
}