diff --git a/changelog/upgrade-notes.md b/changelog/upgrade-notes.md index 009fe780ca..5f9e6e299d 100644 --- a/changelog/upgrade-notes.md +++ b/changelog/upgrade-notes.md @@ -120,6 +120,11 @@ The non API `getChecksum` functions of the style is also removed. #### Other changes +##### Allow declutter in image render mode + +It is now possible to configure vector tile layers with `declutter: true` and `renderMode: 'image'`. However, note that decluttering will be done per tile, resulting in labels and point symbols getting cut off at tile boundaries. +Until now, using both options forced the render mode to be `hybrid`. + ##### Always load tiles while animating or interacting `ol/PluggableMap` and subclasses no longer support the `loadTilesWhileAnimating` and `loadTilesWhileInteracting` options. These options were used to enable tile loading during animations and interactions. With the new DOM composition render strategy, it is no longer necessary to postpone tile loading until after animations or interactions. diff --git a/src/ol/layer/VectorTile.js b/src/ol/layer/VectorTile.js index 900fb4fb20..9bf96d8128 100644 --- a/src/ol/layer/VectorTile.js +++ b/src/ol/layer/VectorTile.js @@ -33,12 +33,13 @@ import {assign} from '../obj.js'; * point symbol or line width. * @property {import("./VectorTileRenderType.js").default|string} [renderMode='hybrid'] Render mode for vector tiles: * * `'image'`: Vector tiles are rendered as images. Great performance, but point symbols and texts - * are always rotated with the view and pixels are scaled during zoom animations. + * are always rotated with the view and pixels are scaled during zoom animations. When `declutter` + * is set to `true`, the decluttering is done per tile resulting in labels and point symbols getting + * cut off at tile boundaries. * * `'hybrid'`: Polygon and line elements are rendered as images, so pixels are scaled during zoom * animations. Point symbols and texts are accurately rendered as vectors and can stay upright on * rotated views. * - * When `declutter` is set to `true`, `'hybrid'` will be used instead of `'image'`. * @property {import("../source/VectorTile.js").default} [source] Source. * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage * this layer in its layers collection, and the layer will be rendered on top. This is useful for @@ -46,8 +47,7 @@ import {assign} from '../obj.js'; * use {@link module:ol/Map#addLayer}. * @property {boolean} [declutter=false] Declutter images and text. Decluttering is applied to all * image and text styles, and the priority is defined by the z-index of the style. Lower z-index - * means higher priority. When set to `true`, a `renderMode` of `'image'` will be overridden with - * `'hybrid'`. + * means higher priority. * @property {import("../style/Style.js").StyleLike} [style] Layer style. See * {@link module:ol/style} for default style which will be used if this is not defined. * @property {boolean} [updateWhileAnimating=false] When set to `true`, feature batches will be @@ -86,16 +86,12 @@ class VectorTileLayer extends BaseVectorLayer { super(/** @type {import("./Vector.js").Options} */ (baseOptions)); - let renderMode = options.renderMode || VectorTileRenderType.HYBRID; + const renderMode = options.renderMode || VectorTileRenderType.HYBRID; assert(renderMode == undefined || renderMode == VectorTileRenderType.IMAGE || renderMode == VectorTileRenderType.HYBRID, 28); // `renderMode` must be `'image'` or `'hybrid'` - if (options.declutter && renderMode == VectorTileRenderType.IMAGE) { - renderMode = VectorTileRenderType.HYBRID; - } - /** * @private * @type {VectorTileRenderType} diff --git a/src/ol/renderer/canvas/VectorTileLayer.js b/src/ol/renderer/canvas/VectorTileLayer.js index 6d864173ce..361a018c5d 100644 --- a/src/ol/renderer/canvas/VectorTileLayer.js +++ b/src/ol/renderer/canvas/VectorTileLayer.js @@ -545,6 +545,10 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { const tile = this.renderTileImageQueue_[uid]; frameState.animate = true; delete this.renderTileImageQueue_[uid]; + const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer()); + if (this.declutterTree_ && layer.getRenderMode() === VectorTileRenderType.IMAGE) { + this.declutterTree_.clear(); + } this.renderTileImage_(tile, frameState.pixelRatio, frameState.viewState.projection); } clear(this.renderTileImageQueue_);