Create hit detection data per layer and without requestAnimationFrame
This commit is contained in:
@@ -61,9 +61,9 @@ class VectorRenderTile extends Tile {
|
||||
this.errorSourceTileKeys = {};
|
||||
|
||||
/**
|
||||
* @type {ImageData}
|
||||
* @type {Object<number, ImageData>}
|
||||
*/
|
||||
this.hitDetectionImageData = null;
|
||||
this.hitDetectionImageData = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user