From 6c052c0dab52c98bacd0b7a781d1ab27be3a0cec Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 23 Oct 2018 09:07:27 -0600 Subject: [PATCH] Split vector layer into Canvas and WebGL implementations --- src/ol/layer/BaseVector.js | 284 ++++++++++++++++++++++++++++++++++++ src/ol/layer/Vector.js | 240 ++---------------------------- src/ol/layer/WebGLVector.js | 41 ++++++ 3 files changed, 336 insertions(+), 229 deletions(-) create mode 100644 src/ol/layer/BaseVector.js create mode 100644 src/ol/layer/WebGLVector.js diff --git a/src/ol/layer/BaseVector.js b/src/ol/layer/BaseVector.js new file mode 100644 index 0000000000..2688bdbc5a --- /dev/null +++ b/src/ol/layer/BaseVector.js @@ -0,0 +1,284 @@ +/** + * @module ol/layer/BaseVector + */ +import LayerType from '../LayerType.js'; +import Layer from './Layer.js'; +import VectorRenderType from './VectorRenderType.js'; +import {assign} from '../obj.js'; +import {createDefaultStyle, toFunction as toStyleFunction} from '../style/Style.js'; + + +/** + * @typedef {Object} Options + * @property {number} [opacity=1] Opacity (0, 1). + * @property {boolean} [visible=true] Visibility. + * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be + * rendered outside of this extent. + * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers + * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed + * for layers that are added to the map's `layers` collection, or `Infinity` when the layer's `setMap()` + * method was used. + * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be + * visible. + * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will + * be visible. + * @property {import("../render.js").OrderFunction} [renderOrder] Render order. Function to be used when sorting + * features before rendering. By default features are drawn in the order that they are created. Use + * `null` to avoid the sort, but get an undefined draw order. + * @property {number} [renderBuffer=100] The buffer in pixels around the viewport extent used by the + * renderer when getting features from the vector source for the rendering or hit-detection. + * Recommended value: the size of the largest symbol, line width or label. + * @property {import("./VectorRenderType.js").default|string} [renderMode='vector'] Render mode for vector layers: + * * `'image'`: Vector layers are rendered as images. Great performance, but point symbols and + * texts are always rotated with the view and pixels are scaled during zoom animations. + * * `'vector'`: Vector layers are rendered as vectors. Most accurate rendering even during + * animations, but slower performance. + * @property {import("../source/Vector.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 + * temporary layers. The standard way to add a layer to a map and have it managed by the map is to + * 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. + * @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` and `renderMode` + * is `vector`, feature batches will be recreated during animations. This means that no + * vectors will be shown clipped, but the setting will have a performance impact for large + * amounts of vector data. When set to `false`, batches will be recreated when no animation + * is active. + * @property {boolean} [updateWhileInteracting=false] When set to `true` and `renderMode` + * is `vector`, feature batches will be recreated during interactions. See also + * `updateWhileAnimating`. + */ + + +/** + * @enum {string} + * @private + */ +const Property = { + RENDER_ORDER: 'renderOrder' +}; + + +/** + * @classdesc + * Vector data that is rendered client-side. + * Note that any property set in the options is set as a {@link module:ol/Object~BaseObject} + * property on the layer object; for example, setting `title: 'My Title'` in the + * options means that `title` is observable, and has get/set accessors. + * + * @api + */ +class BaseVectorLayer extends Layer { + /** + * @param {Options=} opt_options Options. + */ + constructor(opt_options) { + const options = opt_options ? + opt_options : /** @type {Options} */ ({}); + + const baseOptions = assign({}, options); + + delete baseOptions.style; + delete baseOptions.renderBuffer; + delete baseOptions.updateWhileAnimating; + delete baseOptions.updateWhileInteracting; + super(baseOptions); + + /** + * @private + * @type {boolean} + */ + this.declutter_ = options.declutter !== undefined ? options.declutter : false; + + /** + * @type {number} + * @private + */ + this.renderBuffer_ = options.renderBuffer !== undefined ? + options.renderBuffer : 100; + + /** + * User provided style. + * @type {import("../style/Style.js").StyleLike} + * @private + */ + this.style_ = null; + + /** + * Style function for use within the library. + * @type {import("../style/Style.js").StyleFunction|undefined} + * @private + */ + this.styleFunction_ = undefined; + + this.setStyle(options.style); + + /** + * @type {boolean} + * @private + */ + this.updateWhileAnimating_ = options.updateWhileAnimating !== undefined ? + options.updateWhileAnimating : false; + + /** + * @type {boolean} + * @private + */ + this.updateWhileInteracting_ = options.updateWhileInteracting !== undefined ? + options.updateWhileInteracting : false; + + /** + * @private + * @type {import("./VectorTileRenderType.js").default|string} + */ + this.renderMode_ = options.renderMode || VectorRenderType.VECTOR; + + /** + * The layer type. + * @protected + * @type {import("../LayerType.js").default} + */ + this.type = LayerType.VECTOR; + + /** + * @private + * @type {import("../renderer/Layer.js").default} + */ + this.renderer_ = null; + } + + /** + * @return {boolean} Declutter. + */ + getDeclutter() { + return this.declutter_; + } + + /** + * @param {boolean} declutter Declutter. + */ + setDeclutter(declutter) { + this.declutter_ = declutter; + } + + /** + * @return {number|undefined} Render buffer. + */ + getRenderBuffer() { + return this.renderBuffer_; + } + + /** + * @return {function(import("../Feature.js").default, import("../Feature.js").default): number|null|undefined} Render + * order. + */ + getRenderOrder() { + return ( + /** @type {import("../render.js").OrderFunction|null|undefined} */ (this.get(Property.RENDER_ORDER)) + ); + } + + /** + * Get the style for features. This returns whatever was passed to the `style` + * option at construction or to the `setStyle` method. + * @return {import("../style/Style.js").StyleLike} + * Layer style. + * @api + */ + getStyle() { + return this.style_; + } + + /** + * Get the style function. + * @return {import("../style/Style.js").StyleFunction|undefined} Layer style function. + * @api + */ + getStyleFunction() { + return this.styleFunction_; + } + + /** + * @return {boolean} Whether the rendered layer should be updated while + * animating. + */ + getUpdateWhileAnimating() { + return this.updateWhileAnimating_; + } + + /** + * @return {boolean} Whether the rendered layer should be updated while + * interacting. + */ + getUpdateWhileInteracting() { + return this.updateWhileInteracting_; + } + + /** + * @param {import("../render.js").OrderFunction|null|undefined} renderOrder + * Render order. + */ + setRenderOrder(renderOrder) { + this.set(Property.RENDER_ORDER, renderOrder); + } + + /** + * Set the style for features. This can be a single style object, an array + * of styles, or a function that takes a feature and resolution and returns + * an array of styles. If it is `undefined` the default style is used. If + * it is `null` the layer has no style (a `null` style), so only features + * that have their own styles will be rendered in the layer. See + * {@link module:ol/style} for information on the default style. + * @param {import("../style/Style.js").default|Array|import("../style/Style.js").StyleFunction|null|undefined} style Layer style. + * @api + */ + setStyle(style) { + this.style_ = style !== undefined ? style : createDefaultStyle; + this.styleFunction_ = style === null ? + undefined : toStyleFunction(this.style_); + this.changed(); + } + + /** + * @return {import("./VectorRenderType.js").default|string} The render mode. + */ + getRenderMode() { + return this.renderMode_; + } + + /** + * Get the renderer for this layer. + * @return {import("../renderer/Layer.js").default} The layer renderer. + */ + getRenderer() { + if (!this.renderer_) { + this.renderer_ = this.createRenderer(); + } + return this.renderer_; + } + + /** + * Create a renderer for this layer. + * @return {import("../renderer/Layer.js").default} A layer renderer. + * @protected + */ + createRenderer() { + return null; + } +} + + +/** + * Return the associated {@link module:ol/source/Vector vectorsource} of the layer. + * @function + * @return {import("../source/Vector.js").default} Source. + * @api + */ +BaseVectorLayer.prototype.getSource; + + +export default BaseVectorLayer; diff --git a/src/ol/layer/Vector.js b/src/ol/layer/Vector.js index bdf0c62344..0456b04ea0 100644 --- a/src/ol/layer/Vector.js +++ b/src/ol/layer/Vector.js @@ -1,68 +1,15 @@ /** * @module ol/layer/Vector */ -import LayerType from '../LayerType.js'; -import Layer from './Layer.js'; -import VectorRenderType from './VectorRenderType.js'; -import {assign} from '../obj.js'; -import {createDefaultStyle, toFunction as toStyleFunction} from '../style/Style.js'; +import BaseVectorLayer from './BaseVector.js'; +import CanvasVectorLayerRenderer from '../renderer/canvas/VectorLayer.js'; /** - * @typedef {Object} Options - * @property {number} [opacity=1] Opacity (0, 1). - * @property {boolean} [visible=true] Visibility. - * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be - * rendered outside of this extent. - * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers - * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed - * for layers that are added to the map's `layers` collection, or `Infinity` when the layer's `setMap()` - * method was used. - * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be - * visible. - * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will - * be visible. - * @property {import("../render.js").OrderFunction} [renderOrder] Render order. Function to be used when sorting - * features before rendering. By default features are drawn in the order that they are created. Use - * `null` to avoid the sort, but get an undefined draw order. - * @property {number} [renderBuffer=100] The buffer in pixels around the viewport extent used by the - * renderer when getting features from the vector source for the rendering or hit-detection. - * Recommended value: the size of the largest symbol, line width or label. - * @property {import("./VectorRenderType.js").default|string} [renderMode='vector'] Render mode for vector layers: - * * `'image'`: Vector layers are rendered as images. Great performance, but point symbols and - * texts are always rotated with the view and pixels are scaled during zoom animations. - * * `'vector'`: Vector layers are rendered as vectors. Most accurate rendering even during - * animations, but slower performance. - * @property {import("../source/Vector.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 - * temporary layers. The standard way to add a layer to a map and have it managed by the map is to - * 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. - * @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` and `renderMode` - * is `vector`, feature batches will be recreated during animations. This means that no - * vectors will be shown clipped, but the setting will have a performance impact for large - * amounts of vector data. When set to `false`, batches will be recreated when no animation - * is active. - * @property {boolean} [updateWhileInteracting=false] When set to `true` and `renderMode` - * is `vector`, feature batches will be recreated during interactions. See also - * `updateWhileAnimating`. + * @typedef {import("./BaseVector.js").Options} Options */ -/** - * @enum {string} - * @private - */ -const Property = { - RENDER_ORDER: 'renderOrder' -}; - - /** * @classdesc * Vector data that is rendered client-side. @@ -72,188 +19,23 @@ const Property = { * * @api */ -class VectorLayer extends Layer { +class VectorLayer extends BaseVectorLayer { /** * @param {Options=} opt_options Options. */ constructor(opt_options) { - const options = opt_options ? - opt_options : /** @type {Options} */ ({}); - - const baseOptions = assign({}, options); - - delete baseOptions.style; - delete baseOptions.renderBuffer; - delete baseOptions.updateWhileAnimating; - delete baseOptions.updateWhileInteracting; - super(baseOptions); - - /** - * @private - * @type {boolean} - */ - this.declutter_ = options.declutter !== undefined ? options.declutter : false; - - /** - * @type {number} - * @private - */ - this.renderBuffer_ = options.renderBuffer !== undefined ? - options.renderBuffer : 100; - - /** - * User provided style. - * @type {import("../style/Style.js").StyleLike} - * @private - */ - this.style_ = null; - - /** - * Style function for use within the library. - * @type {import("../style/Style.js").StyleFunction|undefined} - * @private - */ - this.styleFunction_ = undefined; - - this.setStyle(options.style); - - /** - * @type {boolean} - * @private - */ - this.updateWhileAnimating_ = options.updateWhileAnimating !== undefined ? - options.updateWhileAnimating : false; - - /** - * @type {boolean} - * @private - */ - this.updateWhileInteracting_ = options.updateWhileInteracting !== undefined ? - options.updateWhileInteracting : false; - - /** - * @private - * @type {import("./VectorTileRenderType.js").default|string} - */ - this.renderMode_ = options.renderMode || VectorRenderType.VECTOR; - - /** - * The layer type. - * @protected - * @type {import("../LayerType.js").default} - */ - this.type = LayerType.VECTOR; - + super(opt_options); } /** - * @return {boolean} Declutter. - */ - getDeclutter() { - return this.declutter_; - } - - /** - * @param {boolean} declutter Declutter. - */ - setDeclutter(declutter) { - this.declutter_ = declutter; - } - - /** - * @return {number|undefined} Render buffer. - */ - getRenderBuffer() { - return this.renderBuffer_; - } - - /** - * @return {function(import("../Feature.js").default, import("../Feature.js").default): number|null|undefined} Render - * order. - */ - getRenderOrder() { - return ( - /** @type {import("../render.js").OrderFunction|null|undefined} */ (this.get(Property.RENDER_ORDER)) - ); - } - - /** - * Get the style for features. This returns whatever was passed to the `style` - * option at construction or to the `setStyle` method. - * @return {import("../style/Style.js").StyleLike} - * Layer style. - * @api - */ - getStyle() { - return this.style_; - } - - /** - * Get the style function. - * @return {import("../style/Style.js").StyleFunction|undefined} Layer style function. - * @api - */ - getStyleFunction() { - return this.styleFunction_; - } - - /** - * @return {boolean} Whether the rendered layer should be updated while - * animating. - */ - getUpdateWhileAnimating() { - return this.updateWhileAnimating_; - } - - /** - * @return {boolean} Whether the rendered layer should be updated while - * interacting. - */ - getUpdateWhileInteracting() { - return this.updateWhileInteracting_; - } - - /** - * @param {import("../render.js").OrderFunction|null|undefined} renderOrder - * Render order. - */ - setRenderOrder(renderOrder) { - this.set(Property.RENDER_ORDER, renderOrder); - } - - /** - * Set the style for features. This can be a single style object, an array - * of styles, or a function that takes a feature and resolution and returns - * an array of styles. If it is `undefined` the default style is used. If - * it is `null` the layer has no style (a `null` style), so only features - * that have their own styles will be rendered in the layer. See - * {@link module:ol/style} for information on the default style. - * @param {import("../style/Style.js").default|Array|import("../style/Style.js").StyleFunction|null|undefined} style Layer style. - * @api - */ - setStyle(style) { - this.style_ = style !== undefined ? style : createDefaultStyle; - this.styleFunction_ = style === null ? - undefined : toStyleFunction(this.style_); - this.changed(); - } - - /** - * @return {import("./VectorRenderType.js").default|string} The render mode. - */ - getRenderMode() { - return this.renderMode_; + * Create a renderer for this layer. + * @return {import("../renderer/Layer.js").default} A layer renderer. + * @protected + */ + createRenderer() { + return new CanvasVectorLayerRenderer(this); } } -/** - * Return the associated {@link module:ol/source/Vector vectorsource} of the layer. - * @function - * @return {import("../source/Vector.js").default} Source. - * @api - */ -VectorLayer.prototype.getSource; - - export default VectorLayer; diff --git a/src/ol/layer/WebGLVector.js b/src/ol/layer/WebGLVector.js new file mode 100644 index 0000000000..03a2c6d109 --- /dev/null +++ b/src/ol/layer/WebGLVector.js @@ -0,0 +1,41 @@ +/** + * @module ol/layer/WebGLVector + */ +import BaseVectorLayer from './BaseVector.js'; + + +/** + * @typedef {import("./BaseVector.js").Options} Options + */ + + +/** + * @classdesc + * Vector data that is rendered client-side. + * Note that any property set in the options is set as a {@link module:ol/Object~BaseObject} + * property on the layer object; for example, setting `title: 'My Title'` in the + * options means that `title` is observable, and has get/set accessors. + * + * @api + */ +class WebGLVectorLayer extends BaseVectorLayer { + /** + * @param {Options=} opt_options Options. + */ + constructor(opt_options) { + super(opt_options); + } + + /** + * Create a renderer for this layer. + * @return {import("../renderer/Layer.js").default} A layer renderer. + * @protected + */ + createRenderer() { + // TODO: rework WebGL renderers to share context + return null; + } +} + + +export default WebGLVectorLayer;