diff --git a/src/ol/renderer/canvas/VectorImageLayer.js b/src/ol/renderer/canvas/VectorImageLayer.js index 73446597bf..91ca356ace 100644 --- a/src/ol/renderer/canvas/VectorImageLayer.js +++ b/src/ol/renderer/canvas/VectorImageLayer.js @@ -77,7 +77,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer { !equals(skippedFeatures, newSkippedFeatures))) { context.canvas.width = imageFrameState.size[0] * pixelRatio; context.canvas.height = imageFrameState.size[1] * pixelRatio; - vectorRenderer.render(imageFrameState, layerState); + vectorRenderer.renderFrame(imageFrameState, layerState); skippedFeatures = newSkippedFeatures; callback(); } diff --git a/src/ol/renderer/canvas/VectorLayer.js b/src/ol/renderer/canvas/VectorLayer.js index 4fd36b7455..78ffb866d4 100644 --- a/src/ol/renderer/canvas/VectorLayer.js +++ b/src/ol/renderer/canvas/VectorLayer.js @@ -13,6 +13,7 @@ import CanvasBuilderGroup from '../../render/canvas/BuilderGroup.js'; import InstructionsGroupExecutor from '../../render/canvas/ExecutorGroup.js'; import CanvasLayerRenderer from './Layer.js'; import {defaultOrder as defaultRenderOrder, getTolerance as getRenderTolerance, getSquaredTolerance as getSquaredRenderTolerance, renderFeature} from '../vector.js'; +import {toString as transformToString} from '../../transform.js'; /** * @classdesc @@ -88,23 +89,42 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { } /** - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. - * @param {import("../../layer/Layer.js").State} layerState Layer state. + * @inheritDoc */ - render(frameState, layerState) { - const replayGroup = this.replayGroup_; + renderFrame(frameState, layerState) { const context = this.context; const canvas = context.canvas; + const replayGroup = this.replayGroup_; if (!replayGroup || replayGroup.isEmpty()) { if (canvas.width > 0) { canvas.width = 0; } - return; + return canvas; } - const extent = frameState.extent; const pixelRatio = frameState.pixelRatio; + + // a scale transform (we could add a createScale function in ol/transform) + const pixelTransform = [1 / pixelRatio, 0, 0, 1 / pixelRatio, 0, 0]; + + // resize and clear + const width = Math.round(frameState.size[0] * pixelRatio); + const height = Math.round(frameState.size[1] * pixelRatio); + if (canvas.width != width || canvas.height != height) { + canvas.width = width; + canvas.height = height; + const canvasTransform = transformToString(pixelTransform); + if (canvas.style.transform !== canvasTransform) { + canvas.style.transform = canvasTransform; + } + } else { + context.clearRect(0, 0, width, height); + } + + this.preRender(context, frameState, pixelTransform); + + const extent = frameState.extent; const viewState = frameState.viewState; const projection = viewState.projection; const rotation = viewState.rotation; @@ -122,22 +142,11 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { this.declutterTree_.clear(); } - // resize and clear - const width = Math.round(frameState.size[0] * pixelRatio); - const height = Math.round(frameState.size[1] * pixelRatio); - if (canvas.width != width || canvas.height != height) { - canvas.width = width; - canvas.height = height; - canvas.style.width = (width / pixelRatio) + 'px'; - canvas.style.height = (height / pixelRatio) + 'px'; - } else { - context.clearRect(0, 0, width, height); - } const viewHints = frameState.viewHints; const snapToPixel = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]); - let transform = this.getRenderTransform(frameState, width, height, 0); + const transform = this.getRenderTransform(frameState, width, height, 0); const skippedFeatureUids = layerState.managed ? frameState.skippedFeatureUids : {}; replayGroup.execute(context, transform, rotation, skippedFeatureUids, snapToPixel); @@ -149,7 +158,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { while (startX < projectionExtent[0]) { --world; offsetX = worldWidth * world; - transform = this.getRenderTransform(frameState, width, height, offsetX); + const transform = this.getRenderTransform(frameState, width, height, offsetX); replayGroup.execute(context, transform, rotation, skippedFeatureUids, snapToPixel); startX += worldWidth; } @@ -158,31 +167,21 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { while (startX > projectionExtent[2]) { ++world; offsetX = worldWidth * world; - transform = this.getRenderTransform(frameState, width, height, offsetX); + const transform = this.getRenderTransform(frameState, width, height, offsetX); replayGroup.execute(context, transform, rotation, skippedFeatureUids, snapToPixel); startX -= worldWidth; } } if (this.getLayer().hasListener(RenderEventType.RENDER)) { - this.dispatchRenderEvent(context, frameState, transform); + this.dispatchRenderEvent(context, frameState, pixelTransform); } if (clipped) { context.restore(); } - } - /** - * @inheritDoc - */ - renderFrame(frameState, layerState) { - const context = this.context; - this.preRender(context, frameState); - this.render(frameState, layerState); - this.postRender(context, frameState); - - const canvas = context.canvas; + this.postRender(context, frameState, pixelTransform); const opacity = layerState.opacity; if (opacity !== canvas.style.opacity) { @@ -302,7 +301,9 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { const replayGroup = new CanvasBuilderGroup( getRenderTolerance(resolution, pixelRatio), extent, resolution, pixelRatio, vectorSource.getOverlaps(), this.declutterTree_, vectorLayer.getRenderBuffer()); + vectorSource.loadFeatures(extent, resolution, projection); + /** * @param {import("../../Feature.js").default} feature Feature. * @this {CanvasVectorLayerRenderer} diff --git a/src/ol/renderer/canvas/VectorTileLayer.js b/src/ol/renderer/canvas/VectorTileLayer.js index b288731e14..c5ffec5768 100644 --- a/src/ol/renderer/canvas/VectorTileLayer.js +++ b/src/ol/renderer/canvas/VectorTileLayer.js @@ -405,7 +405,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { } const tileCoord = tile.tileCoord; const worldOffset = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent)[0] - tile.extent[0]; - let transform = undefined; + const transform = this.getRenderTransform(frameState, width, height, worldOffset); for (let t = 0, tt = tile.tileKeys.length; t < tt; ++t) { const sourceTile = tile.getTile(tile.tileKeys[t]); if (sourceTile.getState() != TileState.LOADED) { @@ -417,9 +417,6 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { // called, or it has no replays of the types we want to render continue; } - if (!transform) { - transform = this.getRenderTransform(frameState, width, height, worldOffset); - } const currentZ = sourceTile.tileCoord[0]; const currentClip = executorGroup.getClipCoords(transform); context.save(); diff --git a/src/ol/transform.js b/src/ol/transform.js index 36630dee84..65c3b4f2f1 100644 --- a/src/ol/transform.js +++ b/src/ol/transform.js @@ -236,3 +236,7 @@ export function invert(transform) { export function determinant(mat) { return mat[0] * mat[3] - mat[1] * mat[2]; } + +export function toString(mat) { + return 'matrix(' + mat.join(', ') + ')'; +}