Merge pull request #8848 from tschaub/renderers
Make layer renderers explicit layer dependencies
This commit is contained in:
@@ -3,7 +3,7 @@ layout: example.html
|
||||
title: Drag-and-Drop Image Vector
|
||||
shortdesc: Example of using the drag-and-drop interaction with image vector rendering.
|
||||
docs: >
|
||||
Example of using the drag-and-drop interaction with an `ol/layer/Vector` with `renderMode: 'image'`. Drag and drop GPX, GeoJSON, IGC, KML, or TopoJSON files on to the map. Each file is rendered to an image on the client.
|
||||
Example of using the drag-and-drop interaction with an `ol/layer/VectorImage` layer. Drag and drop GPX, GeoJSON, IGC, KML, or TopoJSON files on to the map. Each file is rendered to an image on the client.
|
||||
tags: "drag-and-drop-image-vector, gpx, geojson, igc, kml, topojson, vector, image"
|
||||
cloak:
|
||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
||||
|
||||
@@ -2,7 +2,7 @@ import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {GPX, GeoJSON, IGC, KML, TopoJSON} from '../src/ol/format.js';
|
||||
import {defaults as defaultInteractions, DragAndDrop} from '../src/ol/interaction.js';
|
||||
import {Vector as VectorLayer, Tile as TileLayer} from '../src/ol/layer.js';
|
||||
import {VectorImage as VectorImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
|
||||
import {BingMaps, Vector as VectorSource} from '../src/ol/source.js';
|
||||
|
||||
const dragAndDropInteraction = new DragAndDrop({
|
||||
@@ -36,8 +36,7 @@ dragAndDropInteraction.on('addfeatures', function(event) {
|
||||
const vectorSource = new VectorSource({
|
||||
features: event.features
|
||||
});
|
||||
map.addLayer(new VectorLayer({
|
||||
renderMode: 'image',
|
||||
map.addLayer(new VectorImageLayer({
|
||||
source: vectorSource
|
||||
}));
|
||||
map.getView().fit(vectorSource.getExtent());
|
||||
|
||||
@@ -2,7 +2,7 @@ import Feature from '../src/ol/Feature.js';
|
||||
import Map from '../src/ol/WebGLMap.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import Point from '../src/ol/geom/Point.js';
|
||||
import VectorLayer from '../src/ol/layer/Vector.js';
|
||||
import VectorLayer from '../src/ol/layer/WebGLVector.js';
|
||||
import VectorSource from '../src/ol/source/Vector.js';
|
||||
import {Icon, Style} from '../src/ol/style.js';
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Image Vector Layer
|
||||
shortdesc: Example of an image vector layer.
|
||||
title: Vector Image Layer
|
||||
shortdesc: Example of rendering vector data as an image layer.
|
||||
docs: >
|
||||
<p>This example uses <code>ol/layer/Vector</code> with `renderMode: 'image'`. This mode results in faster rendering during interaction and animations, at the cost of less accurate rendering.</p>
|
||||
<p>This example uses <code>ol/layer/VectorImage</code> for faster rendering during interaction and animations, at the cost of less accurate rendering.</p>
|
||||
tags: "vector, image"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||
import VectorImageLayer from '../src/ol/layer/VectorImage.js';
|
||||
import VectorLayer from '../src/ol/layer/Vector.js';
|
||||
import VectorSource from '../src/ol/source/Vector.js';
|
||||
import {Fill, Stroke, Style, Text} from '../src/ol/style.js';
|
||||
@@ -19,8 +20,7 @@ const style = new Style({
|
||||
|
||||
const map = new Map({
|
||||
layers: [
|
||||
new VectorLayer({
|
||||
renderMode: 'image',
|
||||
new VectorImageLayer({
|
||||
source: new VectorSource({
|
||||
url: 'data/geojson/countries.geojson',
|
||||
format: new GeoJSON()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Map from '../src/ol/WebGLMap.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {WEBGL} from '../src/ol/has.js';
|
||||
import TileLayer from '../src/ol/layer/Tile.js';
|
||||
import TileLayer from '../src/ol/layer/WebGLTile.js';
|
||||
import OSM from '../src/ol/source/OSM.js';
|
||||
|
||||
if (!WEBGL) {
|
||||
|
||||
@@ -2,12 +2,17 @@ import Map from '../src/ol/Map.js';
|
||||
import WebGLMap from '../src/ol/WebGLMap.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import TileLayer from '../src/ol/layer/Tile.js';
|
||||
import WebGLTileLayer from '../src/ol/layer/WebGLTile.js';
|
||||
import OSM from '../src/ol/source/OSM.js';
|
||||
|
||||
const layer = new TileLayer({
|
||||
source: new OSM()
|
||||
});
|
||||
|
||||
const webGLLayer = new WebGLTileLayer({
|
||||
source: new OSM()
|
||||
});
|
||||
|
||||
const view = new View({
|
||||
center: [0, 0],
|
||||
zoom: 1
|
||||
@@ -21,6 +26,6 @@ const map1 = new Map({
|
||||
|
||||
const map2 = new WebGLMap({
|
||||
target: 'webglMap',
|
||||
layers: [layer],
|
||||
layers: [webGLLayer],
|
||||
view: view
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import Feature from '../src/ol/Feature.js';
|
||||
import Map from '../src/ol/WebGLMap.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import Point from '../src/ol/geom/Point.js';
|
||||
import VectorLayer from '../src/ol/layer/Vector.js';
|
||||
import VectorLayer from '../src/ol/layer/WebGLVector.js';
|
||||
import VectorSource from '../src/ol/source/Vector.js';
|
||||
import {AtlasManager, Circle as CircleStyle, Fill, RegularShape, Stroke, Style} from '../src/ol/style.js';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Map from '../../../src/ol/Map.js';
|
||||
import Map from '../../../src/ol/CompositeMap.js';
|
||||
import View from '../../../src/ol/View.js';
|
||||
import Feature from '../../../src/ol/Feature.js';
|
||||
import LineString from '../../../src/ol/geom/LineString.js';
|
||||
|
||||
@@ -275,9 +275,13 @@ async function getOutdated(entries, options) {
|
||||
}
|
||||
|
||||
async function main(entries, options) {
|
||||
if (!options.force) {
|
||||
if (!options.force && !options.match) {
|
||||
entries = await getOutdated(entries, options);
|
||||
}
|
||||
if (options.match) {
|
||||
const exp = new RegExp(options.match);
|
||||
entries = entries.filter(entry => exp.test(entry));
|
||||
}
|
||||
if (!options.interactive && entries.length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -308,10 +312,9 @@ if (require.main === module) {
|
||||
type: 'number',
|
||||
default: 3000
|
||||
}).
|
||||
option('timeout', {
|
||||
describe: 'The timeout for loading pages (in milliseconds)',
|
||||
type: 'number',
|
||||
default: 60000
|
||||
option('match', {
|
||||
describe: 'Only run tests matching the provided string RegExp pattern',
|
||||
type: 'string'
|
||||
}).
|
||||
option('force', {
|
||||
describe: 'Run all tests (instead of just outdated tests)',
|
||||
@@ -328,6 +331,11 @@ if (require.main === module) {
|
||||
choices: ['trace', 'debug', 'info', 'warn', 'error', 'silent'],
|
||||
default: 'error'
|
||||
}).
|
||||
option('timeout', {
|
||||
describe: 'The timeout for loading pages (in milliseconds)',
|
||||
type: 'number',
|
||||
default: 60000
|
||||
}).
|
||||
option('headless', {
|
||||
describe: 'Launch Puppeteer in headless mode',
|
||||
type: 'boolean',
|
||||
|
||||
84
src/ol/CompositeMap.js
Normal file
84
src/ol/CompositeMap.js
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @module ol/CompositeMap
|
||||
*/
|
||||
import PluggableMap from './PluggableMap.js';
|
||||
import {defaults as defaultControls} from './control/util.js';
|
||||
import {defaults as defaultInteractions} from './interaction.js';
|
||||
import {assign} from './obj.js';
|
||||
import CompositeMapRenderer from './renderer/Composite.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* The map is the core component of OpenLayers. For a map to render, a view,
|
||||
* one or more layers, and a target container are needed:
|
||||
*
|
||||
* import Map from 'ol/Map';
|
||||
* import View from 'ol/View';
|
||||
* import TileLayer from 'ol/layer/Tile';
|
||||
* import OSM from 'ol/source/OSM';
|
||||
*
|
||||
* var map = new Map({
|
||||
* view: new View({
|
||||
* center: [0, 0],
|
||||
* zoom: 1
|
||||
* }),
|
||||
* layers: [
|
||||
* new TileLayer({
|
||||
* source: new OSM()
|
||||
* })
|
||||
* ],
|
||||
* target: 'map'
|
||||
* });
|
||||
*
|
||||
* The above snippet creates a map using a {@link module:ol/layer/Tile} to
|
||||
* display {@link module:ol/source/OSM~OSM} OSM data and render it to a DOM
|
||||
* element with the id `map`.
|
||||
*
|
||||
* The constructor places a viewport container (with CSS class name
|
||||
* `ol-viewport`) in the target element (see `getViewport()`), and then two
|
||||
* further elements within the viewport: one with CSS class name
|
||||
* `ol-overlaycontainer-stopevent` for controls and some overlays, and one with
|
||||
* CSS class name `ol-overlaycontainer` for other overlays (see the `stopEvent`
|
||||
* option of {@link module:ol/Overlay~Overlay} for the difference). The map
|
||||
* itself is placed in a further element within the viewport.
|
||||
*
|
||||
* Layers are stored as a {@link module:ol/Collection~Collection} in
|
||||
* layerGroups. A top-level group is provided by the library. This is what is
|
||||
* accessed by `getLayerGroup` and `setLayerGroup`. Layers entered in the
|
||||
* options are added to this group, and `addLayer` and `removeLayer` change the
|
||||
* layer collection in the group. `getLayers` is a convenience function for
|
||||
* `getLayerGroup().getLayers()`. Note that {@link module:ol/layer/Group~Group}
|
||||
* is a subclass of {@link module:ol/layer/Base}, so layers entered in the
|
||||
* options or added with `addLayer` can be groups, which can contain further
|
||||
* groups, and so on.
|
||||
*
|
||||
* @fires import("./MapBrowserEvent.js").MapBrowserEvent
|
||||
* @fires import("./MapEvent.js").MapEvent
|
||||
* @fires module:ol/render/Event~RenderEvent#postcompose
|
||||
* @fires module:ol/render/Event~RenderEvent#precompose
|
||||
* @api
|
||||
*/
|
||||
class CompositeMap extends PluggableMap {
|
||||
|
||||
/**
|
||||
* @param {import("./PluggableMap.js").MapOptions} options Map options.
|
||||
*/
|
||||
constructor(options) {
|
||||
options = assign({}, options);
|
||||
if (!options.controls) {
|
||||
options.controls = defaultControls();
|
||||
}
|
||||
if (!options.interactions) {
|
||||
options.interactions = defaultInteractions();
|
||||
}
|
||||
|
||||
super(options);
|
||||
}
|
||||
|
||||
createRenderer() {
|
||||
return new CompositeMapRenderer(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default CompositeMap;
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* @module ol/LayerType
|
||||
*/
|
||||
|
||||
/**
|
||||
* A layer type used when creating layer renderers.
|
||||
* @enum {string}
|
||||
*/
|
||||
export default {
|
||||
IMAGE: 'IMAGE',
|
||||
TILE: 'TILE',
|
||||
VECTOR_TILE: 'VECTOR_TILE',
|
||||
VECTOR: 'VECTOR'
|
||||
};
|
||||
@@ -5,11 +5,7 @@ import PluggableMap from './PluggableMap.js';
|
||||
import {defaults as defaultControls} from './control/util.js';
|
||||
import {defaults as defaultInteractions} from './interaction.js';
|
||||
import {assign} from './obj.js';
|
||||
import CanvasImageLayerRenderer from './renderer/canvas/ImageLayer.js';
|
||||
import CanvasMapRenderer from './renderer/canvas/Map.js';
|
||||
import CanvasTileLayerRenderer from './renderer/canvas/TileLayer.js';
|
||||
import CanvasVectorLayerRenderer from './renderer/canvas/VectorLayer.js';
|
||||
import CanvasVectorTileLayerRenderer from './renderer/canvas/VectorTileLayer.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
@@ -80,14 +76,7 @@ class Map extends PluggableMap {
|
||||
}
|
||||
|
||||
createRenderer() {
|
||||
const renderer = new CanvasMapRenderer(this);
|
||||
renderer.registerLayerRenderers([
|
||||
CanvasImageLayerRenderer,
|
||||
CanvasTileLayerRenderer,
|
||||
CanvasVectorLayerRenderer,
|
||||
CanvasVectorTileLayerRenderer
|
||||
]);
|
||||
return renderer;
|
||||
return new CanvasMapRenderer(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,7 @@ import PluggableMap from './PluggableMap.js';
|
||||
import {defaults as defaultControls} from './control.js';
|
||||
import {defaults as defaultInteractions} from './interaction.js';
|
||||
import {assign} from './obj.js';
|
||||
import WebGLImageLayerRenderer from './renderer/webgl/ImageLayer.js';
|
||||
import WebGLMapRenderer from './renderer/webgl/Map.js';
|
||||
import WebGLTileLayerRenderer from './renderer/webgl/TileLayer.js';
|
||||
import WebGLVectorLayerRenderer from './renderer/webgl/VectorLayer.js';
|
||||
|
||||
|
||||
/**
|
||||
@@ -80,13 +77,7 @@ class WebGLMap extends PluggableMap {
|
||||
}
|
||||
|
||||
createRenderer() {
|
||||
const renderer = new WebGLMapRenderer(this);
|
||||
renderer.registerLayerRenderers([
|
||||
WebGLImageLayerRenderer,
|
||||
WebGLTileLayerRenderer,
|
||||
WebGLVectorLayerRenderer
|
||||
]);
|
||||
return renderer;
|
||||
return new WebGLMapRenderer(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,3 +79,46 @@ export function removeChildren(node) {
|
||||
node.removeChild(node.lastChild);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the children of a parent node so they match the
|
||||
* provided list of children. This function aims to efficiently
|
||||
* remove, add, and reorder child nodes while maintaining a simple
|
||||
* implementation (it is not guaranteed to minimize DOM operations).
|
||||
* @param {Node} node The parent node whose children need reworking.
|
||||
* @param {Array<Node>} children The desired children.
|
||||
*/
|
||||
export function replaceChildren(node, children) {
|
||||
const oldChildren = node.childNodes;
|
||||
|
||||
for (let i = 0; true; ++i) {
|
||||
const oldChild = oldChildren[i];
|
||||
const newChild = children[i];
|
||||
|
||||
// check if our work is done
|
||||
if (!oldChild && !newChild) {
|
||||
break;
|
||||
}
|
||||
|
||||
// check if children match
|
||||
if (oldChild === newChild) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if a new child needs to be added
|
||||
if (!oldChild) {
|
||||
node.appendChild(newChild);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if an old child needs to be removed
|
||||
if (!newChild) {
|
||||
node.removeChild(oldChild);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
// reorder
|
||||
node.insertBefore(newChild, oldChild);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,4 +9,5 @@ export {default as Image} from './layer/Image.js';
|
||||
export {default as Layer} from './layer/Layer.js';
|
||||
export {default as Tile} from './layer/Tile.js';
|
||||
export {default as Vector} from './layer/Vector.js';
|
||||
export {default as VectorImage} from './layer/VectorImage.js';
|
||||
export {default as VectorTile} from './layer/VectorTile.js';
|
||||
|
||||
@@ -65,21 +65,6 @@ class BaseLayer extends BaseObject {
|
||||
*/
|
||||
this.state_ = null;
|
||||
|
||||
/**
|
||||
* The layer type.
|
||||
* @type {import("../LayerType.js").default}
|
||||
* @protected;
|
||||
*/
|
||||
this.type;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the layer type (used when creating a layer renderer).
|
||||
* @return {import("../LayerType.js").default} The layer type.
|
||||
*/
|
||||
getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
60
src/ol/layer/BaseImage.js
Normal file
60
src/ol/layer/BaseImage.js
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @module ol/layer/BaseImage
|
||||
*/
|
||||
import Layer from './Layer.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("../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 {import("../source/Image.js").default} [source] Source for this layer.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Server-rendered images that are available for arbitrary extents and
|
||||
* resolutions.
|
||||
* 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.
|
||||
*
|
||||
* @fires import("../render/Event.js").RenderEvent
|
||||
* @api
|
||||
*/
|
||||
class BaseImageLayer extends Layer {
|
||||
|
||||
/**
|
||||
* @param {Options=} opt_options Layer options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
super(options);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the associated {@link module:ol/source/Image source} of the image layer.
|
||||
* @function
|
||||
* @return {import("../source/Image.js").default} Source.
|
||||
* @api
|
||||
*/
|
||||
BaseImageLayer.prototype.getSource;
|
||||
export default BaseImageLayer;
|
||||
114
src/ol/layer/BaseTile.js
Normal file
114
src/ol/layer/BaseTile.js
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* @module ol/layer/BaseTile
|
||||
*/
|
||||
import Layer from './Layer.js';
|
||||
import TileProperty from './TileProperty.js';
|
||||
import {assign} from '../obj.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 {number} [preload=0] Preload. Load low-resolution tiles up to `preload` levels. `0`
|
||||
* means no preloading.
|
||||
* @property {import("../source/Tile.js").default} [source] Source for this layer.
|
||||
* @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} [useInterimTilesOnError=true] Use interim tiles on error.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* For layer sources that provide pre-rendered, tiled images in grids that are
|
||||
* organized by zoom levels for specific resolutions.
|
||||
* 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 BaseTileLayer extends Layer {
|
||||
/**
|
||||
* @param {Options=} opt_options Tile layer options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const baseOptions = assign({}, options);
|
||||
|
||||
delete baseOptions.preload;
|
||||
delete baseOptions.useInterimTilesOnError;
|
||||
super(baseOptions);
|
||||
|
||||
this.setPreload(options.preload !== undefined ? options.preload : 0);
|
||||
this.setUseInterimTilesOnError(options.useInterimTilesOnError !== undefined ?
|
||||
options.useInterimTilesOnError : true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the level as number to which we will preload tiles up to.
|
||||
* @return {number} The level to preload tiles up to.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getPreload() {
|
||||
return /** @type {number} */ (this.get(TileProperty.PRELOAD));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the level as number to which we will preload tiles up to.
|
||||
* @param {number} preload The level to preload tiles up to.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setPreload(preload) {
|
||||
this.set(TileProperty.PRELOAD, preload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether we use interim tiles on error.
|
||||
* @return {boolean} Use interim tiles on error.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getUseInterimTilesOnError() {
|
||||
return /** @type {boolean} */ (this.get(TileProperty.USE_INTERIM_TILES_ON_ERROR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether we use interim tiles on error.
|
||||
* @param {boolean} useInterimTilesOnError Use interim tiles on error.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setUseInterimTilesOnError(useInterimTilesOnError) {
|
||||
this.set(TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the associated {@link module:ol/source/Tile tilesource} of the layer.
|
||||
* @function
|
||||
* @return {import("../source/Tile.js").default} Source.
|
||||
* @api
|
||||
*/
|
||||
BaseTileLayer.prototype.getSource;
|
||||
|
||||
|
||||
export default BaseTileLayer;
|
||||
231
src/ol/layer/BaseVector.js
Normal file
231
src/ol/layer/BaseVector.js
Normal file
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* @module ol/layer/BaseVector
|
||||
*/
|
||||
import Layer from './Layer.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("../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`, 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`, 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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @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").default>|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 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;
|
||||
@@ -34,11 +34,6 @@ import Style from '../style/Style.js';
|
||||
* @property {string|function(import("../Feature.js").default):number} [weight='weight'] The feature
|
||||
* attribute to use for the weight or a function that returns a weight from a feature. Weight values
|
||||
* should range from 0 to 1 (and values outside will be clamped to that range).
|
||||
* @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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,29 +1,12 @@
|
||||
/**
|
||||
* @module ol/layer/Image
|
||||
*/
|
||||
import LayerType from '../LayerType.js';
|
||||
import Layer from './Layer.js';
|
||||
import BaseImageLayer from './BaseImage.js';
|
||||
import CanvasImageLayerRenderer from '../renderer/canvas/ImageLayer.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("../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 {import("../source/Image.js").default} [source] Source for this layer.
|
||||
* @typedef {import("./BaseImage.js").Options} Options
|
||||
*/
|
||||
|
||||
|
||||
@@ -38,32 +21,25 @@ import Layer from './Layer.js';
|
||||
* @fires import("../render/Event.js").RenderEvent
|
||||
* @api
|
||||
*/
|
||||
class ImageLayer extends Layer {
|
||||
class ImageLayer extends BaseImageLayer {
|
||||
|
||||
/**
|
||||
* @param {Options=} opt_options Layer options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
super(options);
|
||||
|
||||
/**
|
||||
* The layer type.
|
||||
* @protected
|
||||
* @type {import("../LayerType.js").default}
|
||||
*/
|
||||
this.type = LayerType.IMAGE;
|
||||
super(opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a renderer for this layer.
|
||||
* @param {import("../renderer/Map.js").default} mapRenderer The map renderer.
|
||||
* @return {import("../renderer/Layer.js").default} A layer renderer.
|
||||
* @protected
|
||||
*/
|
||||
createRenderer(mapRenderer) {
|
||||
return new CanvasImageLayerRenderer(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the associated {@link module:ol/source/Image source} of the image layer.
|
||||
* @function
|
||||
* @return {import("../source/Image.js").default} Source.
|
||||
* @api
|
||||
*/
|
||||
ImageLayer.prototype.getSource;
|
||||
export default ImageLayer;
|
||||
|
||||
@@ -92,6 +92,12 @@ class Layer extends BaseLayer {
|
||||
*/
|
||||
this.sourceChangeKey_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("../renderer/Layer.js").default}
|
||||
*/
|
||||
this.renderer_ = null;
|
||||
|
||||
if (options.map) {
|
||||
this.setMap(options.map);
|
||||
}
|
||||
@@ -215,6 +221,29 @@ class Layer extends BaseLayer {
|
||||
setSource(source) {
|
||||
this.set(LayerProperty.SOURCE, source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the renderer for this layer.
|
||||
* @param {import("../renderer/Map.js").default} mapRenderer The map renderer.
|
||||
* @return {import("../renderer/Layer.js").default} The layer renderer.
|
||||
*/
|
||||
getRenderer(mapRenderer) {
|
||||
if (!this.renderer_) {
|
||||
this.renderer_ = this.createRenderer(mapRenderer);
|
||||
}
|
||||
return this.renderer_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a renderer for this layer.
|
||||
* @param {import("../renderer/Map.js").default} mapRenderer The map renderer.
|
||||
* @return {import("../renderer/Layer.js").default} A layer renderer.
|
||||
* @protected
|
||||
*/
|
||||
createRenderer(mapRenderer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +1,15 @@
|
||||
/**
|
||||
* @module ol/layer/Tile
|
||||
*/
|
||||
import LayerType from '../LayerType.js';
|
||||
import Layer from './Layer.js';
|
||||
import TileProperty from './TileProperty.js';
|
||||
import {assign} from '../obj.js';
|
||||
import BaseTileLayer from './BaseTile.js';
|
||||
import CanvasTileLayerRenderer from '../renderer/canvas/TileLayer.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 {number} [preload=0] Preload. Load low-resolution tiles up to `preload` levels. `0`
|
||||
* means no preloading.
|
||||
* @property {import("../source/Tile.js").default} [source] Source for this layer.
|
||||
* @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} [useInterimTilesOnError=true] Use interim tiles on error.
|
||||
* @typedef {import("./BaseTile.js").Options} Options
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* For layer sources that provide pre-rendered, tiled images in grids that are
|
||||
@@ -41,81 +20,25 @@ import {assign} from '../obj.js';
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class TileLayer extends Layer {
|
||||
class TileLayer extends BaseTileLayer {
|
||||
|
||||
/**
|
||||
* @param {Options=} opt_options Tile layer options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const baseOptions = assign({}, options);
|
||||
|
||||
delete baseOptions.preload;
|
||||
delete baseOptions.useInterimTilesOnError;
|
||||
super(baseOptions);
|
||||
|
||||
this.setPreload(options.preload !== undefined ? options.preload : 0);
|
||||
this.setUseInterimTilesOnError(options.useInterimTilesOnError !== undefined ?
|
||||
options.useInterimTilesOnError : true);
|
||||
|
||||
/**
|
||||
* The layer type.
|
||||
* @protected
|
||||
* @type {import("../LayerType.js").default}
|
||||
*/
|
||||
this.type = LayerType.TILE;
|
||||
|
||||
super(opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the level as number to which we will preload tiles up to.
|
||||
* @return {number} The level to preload tiles up to.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getPreload() {
|
||||
return /** @type {number} */ (this.get(TileProperty.PRELOAD));
|
||||
* Create a renderer for this layer.
|
||||
* @param {import("../renderer/Map.js").default} mapRenderer The map renderer.
|
||||
* @return {import("../renderer/Layer.js").default} A layer renderer.
|
||||
* @protected
|
||||
*/
|
||||
createRenderer(mapRenderer) {
|
||||
return new CanvasTileLayerRenderer(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the level as number to which we will preload tiles up to.
|
||||
* @param {number} preload The level to preload tiles up to.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setPreload(preload) {
|
||||
this.set(TileProperty.PRELOAD, preload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether we use interim tiles on error.
|
||||
* @return {boolean} Use interim tiles on error.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getUseInterimTilesOnError() {
|
||||
return /** @type {boolean} */ (this.get(TileProperty.USE_INTERIM_TILES_ON_ERROR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether we use interim tiles on error.
|
||||
* @param {boolean} useInterimTilesOnError Use interim tiles on error.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setUseInterimTilesOnError(useInterimTilesOnError) {
|
||||
this.set(TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the associated {@link module:ol/source/Tile tilesource} of the layer.
|
||||
* @function
|
||||
* @return {import("../source/Tile.js").default} Source.
|
||||
* @api
|
||||
*/
|
||||
TileLayer.prototype.getSource;
|
||||
|
||||
|
||||
export default TileLayer;
|
||||
|
||||
@@ -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,24 @@ 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").default>|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.
|
||||
* @param {import("../renderer/Map.js").default} mapRenderer The map renderer.
|
||||
* @return {import("../renderer/Layer.js").default} A layer renderer.
|
||||
* @protected
|
||||
*/
|
||||
createRenderer(mapRenderer) {
|
||||
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;
|
||||
|
||||
41
src/ol/layer/VectorImage.js
Normal file
41
src/ol/layer/VectorImage.js
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @module ol/layer/VectorImage
|
||||
*/
|
||||
import BaseVectorLayer from './BaseVector.js';
|
||||
import CanvasVectorImageLayerRenderer from '../renderer/canvas/VectorImageLayer.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 VectorImageLayer extends BaseVectorLayer {
|
||||
/**
|
||||
* @param {Options=} opt_options Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super(opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a renderer for this layer.
|
||||
* @param {import("../renderer/Map.js").default} mapRenderer The map renderer.
|
||||
* @return {import("../renderer/Layer.js").default} A layer renderer.
|
||||
* @protected
|
||||
*/
|
||||
createRenderer(mapRenderer) {
|
||||
return new CanvasVectorImageLayerRenderer(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default VectorImageLayer;
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* @module ol/layer/VectorRenderType
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
* 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.
|
||||
* @api
|
||||
*/
|
||||
export default {
|
||||
IMAGE: 'image',
|
||||
VECTOR: 'vector'
|
||||
};
|
||||
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* @module ol/layer/VectorTile
|
||||
*/
|
||||
import LayerType from '../LayerType.js';
|
||||
import {assert} from '../asserts.js';
|
||||
import TileProperty from './TileProperty.js';
|
||||
import VectorLayer from './Vector.js';
|
||||
import BaseVectorLayer from './BaseVector.js';
|
||||
import VectorTileRenderType from './VectorTileRenderType.js';
|
||||
import CanvasVectorTileLayerRenderer from '../renderer/canvas/VectorTileLayer.js';
|
||||
import {assign} from '../obj.js';
|
||||
|
||||
|
||||
@@ -78,41 +78,57 @@ import {assign} from '../obj.js';
|
||||
* @param {Options=} opt_options Options.
|
||||
* @api
|
||||
*/
|
||||
class VectorTileLayer extends VectorLayer {
|
||||
class VectorTileLayer extends BaseVectorLayer {
|
||||
/**
|
||||
* @param {Options=} opt_options Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
let renderMode = options.renderMode || VectorTileRenderType.HYBRID;
|
||||
assert(renderMode == undefined ||
|
||||
renderMode == VectorTileRenderType.IMAGE ||
|
||||
renderMode == VectorTileRenderType.HYBRID ||
|
||||
renderMode == VectorTileRenderType.VECTOR,
|
||||
28); // `renderMode` must be `'image'`, `'hybrid'` or `'vector'`
|
||||
if (options.declutter && renderMode == VectorTileRenderType.IMAGE) {
|
||||
renderMode = VectorTileRenderType.HYBRID;
|
||||
}
|
||||
options.renderMode = renderMode;
|
||||
|
||||
const baseOptions = /** @type {Object} */ (assign({}, options));
|
||||
delete baseOptions.preload;
|
||||
delete baseOptions.useInterimTilesOnError;
|
||||
|
||||
super(/** @type {import("./Vector.js").Options} */ (baseOptions));
|
||||
|
||||
let renderMode = options.renderMode || VectorTileRenderType.HYBRID;
|
||||
assert(renderMode == undefined ||
|
||||
renderMode == VectorTileRenderType.IMAGE ||
|
||||
renderMode == VectorTileRenderType.HYBRID ||
|
||||
renderMode == VectorTileRenderType.VECTOR,
|
||||
28); // `renderMode` must be `'image'`, `'hybrid'` or `'vector'`
|
||||
|
||||
if (options.declutter && renderMode == VectorTileRenderType.IMAGE) {
|
||||
renderMode = VectorTileRenderType.HYBRID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {VectorTileRenderType}
|
||||
*/
|
||||
this.renderMode_ = renderMode;
|
||||
|
||||
this.setPreload(options.preload ? options.preload : 0);
|
||||
this.setUseInterimTilesOnError(options.useInterimTilesOnError !== undefined ?
|
||||
options.useInterimTilesOnError : true);
|
||||
|
||||
/**
|
||||
* The layer type.
|
||||
* @protected
|
||||
* @type {import("../LayerType.js").default}
|
||||
*/
|
||||
this.type = LayerType.VECTOR_TILE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a renderer for this layer.
|
||||
* @param {import("../renderer/Map.js").default} mapRenderer The map renderer.
|
||||
* @return {import("../renderer/Layer.js").default} A layer renderer.
|
||||
* @protected
|
||||
*/
|
||||
createRenderer(mapRenderer) {
|
||||
return new CanvasVectorTileLayerRenderer(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {VectorTileRenderType} The render mode.
|
||||
*/
|
||||
getRenderMode() {
|
||||
return this.renderMode_;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
45
src/ol/layer/WebGLImage.js
Normal file
45
src/ol/layer/WebGLImage.js
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @module ol/layer/WebGLImage
|
||||
*/
|
||||
import BaseImageLayer from './BaseImage.js';
|
||||
import WebGLImageLayerRenderer from '../renderer/webgl/ImageLayer.js';
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {import("./BaseImage.js").Options} Options
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Server-rendered images that are available for arbitrary extents and
|
||||
* resolutions.
|
||||
* 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.
|
||||
*
|
||||
* @fires import("../render/Event.js").RenderEvent
|
||||
* @api
|
||||
*/
|
||||
class WebGLImageLayer extends BaseImageLayer {
|
||||
|
||||
/**
|
||||
* @param {Options=} opt_options Layer options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super(opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a renderer for this layer.
|
||||
* @param {import("../renderer/webgl/Map.js").default} mapRenderer The map renderer.
|
||||
* @return {import("../renderer/Layer.js").default} A layer renderer.
|
||||
* @protected
|
||||
*/
|
||||
createRenderer(mapRenderer) {
|
||||
return new WebGLImageLayerRenderer(mapRenderer, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default WebGLImageLayer;
|
||||
43
src/ol/layer/WebGLTile.js
Normal file
43
src/ol/layer/WebGLTile.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @module ol/layer/WebGLTile
|
||||
*/
|
||||
import BaseTileLayer from './BaseTile.js';
|
||||
import WebGLTileLayerRenderer from '../renderer/webgl/TileLayer.js';
|
||||
|
||||
/**
|
||||
* @typedef {import("./BaseTile.js").Options} Options
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* For layer sources that provide pre-rendered, tiled images in grids that are
|
||||
* organized by zoom levels for specific resolutions.
|
||||
* 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 WebGLTileLayer extends BaseTileLayer {
|
||||
|
||||
/**
|
||||
* @param {Options=} opt_options Tile layer options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super(opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a renderer for this layer.
|
||||
* @param {import("../renderer/webgl/Map.js").default} mapRenderer The map renderer.
|
||||
* @return {import("../renderer/Layer.js").default} A layer renderer.
|
||||
* @protected
|
||||
*/
|
||||
createRenderer(mapRenderer) {
|
||||
return new WebGLTileLayerRenderer(mapRenderer, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default WebGLTileLayer;
|
||||
42
src/ol/layer/WebGLVector.js
Normal file
42
src/ol/layer/WebGLVector.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @module ol/layer/WebGLVector
|
||||
*/
|
||||
import BaseVectorLayer from './BaseVector.js';
|
||||
import WebGLVectorLayerRenderer from '../renderer/webgl/VectorLayer.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.
|
||||
* @param {import("../renderer/webgl/Map.js").default} mapRenderer The map renderer.
|
||||
* @return {import("../renderer/Layer.js").default} A layer renderer.
|
||||
* @protected
|
||||
*/
|
||||
createRenderer(mapRenderer) {
|
||||
return new WebGLVectorLayerRenderer(mapRenderer, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default WebGLVectorLayer;
|
||||
151
src/ol/renderer/Composite.js
Normal file
151
src/ol/renderer/Composite.js
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* @module ol/renderer/canvas/Map
|
||||
*/
|
||||
import {apply as applyTransform} from '../transform.js';
|
||||
import {stableSort} from '../array.js';
|
||||
import {CLASS_UNSELECTABLE} from '../css.js';
|
||||
import {visibleAtResolution} from '../layer/Layer.js';
|
||||
import RenderEvent from '../render/Event.js';
|
||||
import RenderEventType from '../render/EventType.js';
|
||||
import MapRenderer, {sortByZIndex} from './Map.js';
|
||||
import SourceState from '../source/State.js';
|
||||
import {replaceChildren} from '../dom.js';
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Canvas map renderer.
|
||||
* @api
|
||||
*/
|
||||
class CompositeMapRenderer extends MapRenderer {
|
||||
|
||||
/**
|
||||
* @param {import("../PluggableMap.js").default} map Map.
|
||||
*/
|
||||
constructor(map) {
|
||||
super(map);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLDivElement}
|
||||
*/
|
||||
this.element_ = document.createElement('div');
|
||||
|
||||
this.element_.style.width = '100%';
|
||||
this.element_.style.height = '100%';
|
||||
this.element_.className = CLASS_UNSELECTABLE;
|
||||
|
||||
const container = map.getViewport();
|
||||
container.insertBefore(this.element_, container.firstChild || null);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<HTMLElement>}
|
||||
*/
|
||||
this.children_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderedVisible_ = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../render/EventType.js").default} type Event type.
|
||||
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
|
||||
*/
|
||||
dispatchRenderEvent(type, frameState) {
|
||||
const map = this.getMap();
|
||||
if (map.hasListener(type)) {
|
||||
const event = new RenderEvent(type, undefined, frameState);
|
||||
map.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
renderFrame(frameState) {
|
||||
if (!frameState) {
|
||||
if (this.renderedVisible_) {
|
||||
this.element_.style.display = 'none';
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.calculateMatrices2D(frameState);
|
||||
this.dispatchRenderEvent(RenderEventType.PRECOMPOSE, frameState);
|
||||
|
||||
const layerStatesArray = frameState.layerStatesArray;
|
||||
stableSort(layerStatesArray, sortByZIndex);
|
||||
|
||||
const rotation = frameState.viewState.rotation;
|
||||
if (rotation) {
|
||||
// TODO: apply rotation
|
||||
}
|
||||
|
||||
const viewResolution = frameState.viewState.resolution;
|
||||
|
||||
this.children_.length = 0;
|
||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||
const layerState = layerStatesArray[i];
|
||||
if (!visibleAtResolution(layerState, viewResolution) || layerState.sourceState != SourceState.READY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const layer = layerState.layer;
|
||||
const layerRenderer = this.getLayerRenderer(layer);
|
||||
if (layerRenderer.prepareFrame(frameState, layerState)) {
|
||||
const element = layerRenderer.renderFrame(frameState, layerState);
|
||||
// TODO: deal with opacity
|
||||
this.children_.push(element);
|
||||
}
|
||||
}
|
||||
|
||||
replaceChildren(this.element_, this.children_);
|
||||
|
||||
this.dispatchRenderEvent(RenderEventType.POSTCOMPOSE, frameState);
|
||||
|
||||
if (!this.renderedVisible_) {
|
||||
this.element_.style.display = '';
|
||||
this.renderedVisible_ = true;
|
||||
}
|
||||
|
||||
this.scheduleRemoveUnusedLayerRenderers(frameState);
|
||||
this.scheduleExpireIconCache(frameState);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
forEachLayerAtPixel(pixel, frameState, hitTolerance, callback, thisArg, layerFilter, thisArg2) {
|
||||
let result;
|
||||
const viewState = frameState.viewState;
|
||||
const viewResolution = viewState.resolution;
|
||||
|
||||
const layerStates = frameState.layerStatesArray;
|
||||
const numLayers = layerStates.length;
|
||||
|
||||
const coordinate = applyTransform(
|
||||
frameState.pixelToCoordinateTransform, pixel.slice());
|
||||
|
||||
for (let i = numLayers - 1; i >= 0; --i) {
|
||||
const layerState = layerStates[i];
|
||||
const layer = layerState.layer;
|
||||
if (visibleAtResolution(layerState, viewResolution) && layerFilter.call(thisArg2, layer)) {
|
||||
const layerRenderer = this.getLayerRenderer(layer);
|
||||
result = layerRenderer.forEachLayerAtCoordinate(coordinate, frameState, hitTolerance, callback, thisArg);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default CompositeMapRenderer;
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @module ol/renderer/Layer
|
||||
*/
|
||||
import {getUid} from '../util.js';
|
||||
import {getUid, abstract} from '../util.js';
|
||||
import ImageState from '../ImageState.js';
|
||||
import Observable from '../Observable.js';
|
||||
import TileState from '../TileState.js';
|
||||
@@ -26,6 +26,28 @@ class LayerRenderer extends Observable {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether render should be called.
|
||||
* @abstract
|
||||
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
|
||||
* @param {import("../layer/Layer.js").State} layerState Layer state.
|
||||
* @return {boolean} Layer is ready to be rendered.
|
||||
*/
|
||||
prepareFrame(frameState, layerState) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the layer.
|
||||
* @abstract
|
||||
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
|
||||
* @param {import("../layer/Layer.js").State} layerState Layer state.
|
||||
* @return {HTMLElement} The rendered element.
|
||||
*/
|
||||
renderFrame(frameState, layerState) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a function that adds loaded tiles to the tile lookup.
|
||||
* @param {import("../source/Tile.js").default} source Tile source.
|
||||
@@ -68,6 +90,21 @@ class LayerRenderer extends Observable {
|
||||
*/
|
||||
forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback) {}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {import("../coordinate.js").Coordinate} coordinate Coordinate.
|
||||
* @param {import("../PluggableMap.js").FrameState} frameState FrameState.
|
||||
* @param {number} hitTolerance Hit tolerance in pixels.
|
||||
* @param {function(this: S, import("../layer/Layer.js").default, (Uint8ClampedArray|Uint8Array)): T} callback Layer
|
||||
* callback.
|
||||
* @param {S} thisArg Value to use as `this` when executing `callback`.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template S,T
|
||||
*/
|
||||
forEachLayerAtCoordinate(coordinate, frameState, hitTolerance, callback, thisArg) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("../layer/Layer.js").default} Layer.
|
||||
*/
|
||||
|
||||
@@ -40,12 +40,6 @@ class MapRenderer extends Disposable {
|
||||
*/
|
||||
this.layerRendererListeners_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<typeof import("./Layer.js").default>}
|
||||
*/
|
||||
this.layerRendererConstructors_ = [];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,14 +51,6 @@ class MapRenderer extends Disposable {
|
||||
abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register layer renderer constructors.
|
||||
* @param {Array<typeof import("./Layer.js").default>} constructors Layer renderers.
|
||||
*/
|
||||
registerLayerRenderers(constructors) {
|
||||
this.layerRendererConstructors_.push.apply(this.layerRendererConstructors_, constructors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../PluggableMap.js").FrameState} frameState FrameState.
|
||||
* @protected
|
||||
@@ -151,10 +137,10 @@ class MapRenderer extends Disposable {
|
||||
let i;
|
||||
for (i = numLayers - 1; i >= 0; --i) {
|
||||
const layerState = layerStates[i];
|
||||
const layer = layerState.layer;
|
||||
const layer = /** @type {import("../layer/Layer.js").default} */ (layerState.layer);
|
||||
if (visibleAtResolution(layerState, viewResolution) && layerFilter.call(thisArg2, layer)) {
|
||||
const layerRenderer = this.getLayerRenderer(layer);
|
||||
const source = /** @type {import("../layer/Layer.js").default} */ (layer).getSource();
|
||||
const source = layer.getSource();
|
||||
if (source) {
|
||||
result = layerRenderer.forEachFeatureAtCoordinate(
|
||||
source.getWrapX() ? translatedCoordinate : coordinate,
|
||||
@@ -208,7 +194,7 @@ class MapRenderer extends Disposable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../layer/Base.js").default} layer Layer.
|
||||
* @param {import("../layer/Layer.js").default} layer Layer.
|
||||
* @protected
|
||||
* @return {import("./Layer.js").default} Layer renderer.
|
||||
*/
|
||||
@@ -216,24 +202,16 @@ class MapRenderer extends Disposable {
|
||||
const layerKey = getUid(layer);
|
||||
if (layerKey in this.layerRenderers_) {
|
||||
return this.layerRenderers_[layerKey];
|
||||
} else {
|
||||
let renderer;
|
||||
for (let i = 0, ii = this.layerRendererConstructors_.length; i < ii; ++i) {
|
||||
const candidate = this.layerRendererConstructors_[i];
|
||||
if (candidate['handles'](layer)) {
|
||||
renderer = candidate['create'](this, layer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (renderer) {
|
||||
this.layerRenderers_[layerKey] = renderer;
|
||||
this.layerRendererListeners_[layerKey] = listen(renderer,
|
||||
EventType.CHANGE, this.handleLayerRendererChange_, this);
|
||||
} else {
|
||||
throw new Error('Unable to create renderer for layer: ' + layer.getType());
|
||||
}
|
||||
return renderer;
|
||||
}
|
||||
|
||||
const renderer = layer.getRenderer(this);
|
||||
if (!renderer) {
|
||||
throw new Error('Unable to create renderer for layer');
|
||||
}
|
||||
|
||||
this.layerRenderers_[layerKey] = renderer;
|
||||
this.layerRendererListeners_[layerKey] = listen(renderer, EventType.CHANGE, this.handleLayerRendererChange_, this);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,14 +2,8 @@
|
||||
* @module ol/renderer/canvas/ImageLayer
|
||||
*/
|
||||
import {ENABLE_RASTER_REPROJECTION} from '../../reproj/common.js';
|
||||
import ImageCanvas from '../../ImageCanvas.js';
|
||||
import LayerType from '../../LayerType.js';
|
||||
import ViewHint from '../../ViewHint.js';
|
||||
import {equals} from '../../array.js';
|
||||
import {getHeight, getIntersection, getWidth, isEmpty} from '../../extent.js';
|
||||
import VectorRenderType from '../../layer/VectorRenderType.js';
|
||||
import {assign} from '../../obj.js';
|
||||
import {layerRendererConstructors} from './Map.js';
|
||||
import {getIntersection, isEmpty} from '../../extent.js';
|
||||
import IntermediateCanvasRenderer from './IntermediateCanvas.js';
|
||||
import {create as createTransform, compose as composeTransform} from '../../transform.js';
|
||||
|
||||
@@ -21,55 +15,23 @@ import {create as createTransform, compose as composeTransform} from '../../tran
|
||||
class CanvasImageLayerRenderer extends IntermediateCanvasRenderer {
|
||||
|
||||
/**
|
||||
* @param {import("../../layer/Image.js").default|import("../../layer/Vector.js").default} imageLayer Image or vector layer.
|
||||
* @param {import("../../layer/Image.js").default} imageLayer Image layer.
|
||||
*/
|
||||
constructor(imageLayer) {
|
||||
|
||||
super(imageLayer);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @protected
|
||||
* @type {?import("../../ImageBase.js").default}
|
||||
*/
|
||||
this.image_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @protected
|
||||
* @type {import("../../transform.js").Transform}
|
||||
*/
|
||||
this.imageTransform_ = createTransform();
|
||||
|
||||
/**
|
||||
* @type {!Array<string>}
|
||||
*/
|
||||
this.skippedFeatures_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("./VectorLayer.js").default}
|
||||
*/
|
||||
this.vectorRenderer_ = null;
|
||||
|
||||
if (imageLayer.getType() === LayerType.VECTOR) {
|
||||
for (let i = 0, ii = layerRendererConstructors.length; i < ii; ++i) {
|
||||
const ctor = layerRendererConstructors[i];
|
||||
if (ctor !== CanvasImageLayerRenderer && ctor['handles'](imageLayer)) {
|
||||
this.vectorRenderer_ = /** @type {import("./VectorLayer.js").default} */ (new ctor(imageLayer));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
disposeInternal() {
|
||||
if (this.vectorRenderer_) {
|
||||
this.vectorRenderer_.dispose();
|
||||
}
|
||||
super.disposeInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,9 +65,8 @@ class CanvasImageLayerRenderer extends IntermediateCanvasRenderer {
|
||||
|
||||
const hints = frameState.viewHints;
|
||||
|
||||
const vectorRenderer = this.vectorRenderer_;
|
||||
let renderedExtent = frameState.extent;
|
||||
if (!vectorRenderer && layerState.extent !== undefined) {
|
||||
if (layerState.extent !== undefined) {
|
||||
renderedExtent = getIntersection(renderedExtent, layerState.extent);
|
||||
}
|
||||
|
||||
@@ -118,37 +79,9 @@ class CanvasImageLayerRenderer extends IntermediateCanvasRenderer {
|
||||
projection = sourceProjection;
|
||||
}
|
||||
}
|
||||
let skippedFeatures = this.skippedFeatures_;
|
||||
if (vectorRenderer) {
|
||||
const context = vectorRenderer.context;
|
||||
const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign({}, frameState, {
|
||||
size: [
|
||||
getWidth(renderedExtent) / viewResolution,
|
||||
getHeight(renderedExtent) / viewResolution
|
||||
],
|
||||
viewState: /** @type {import("../../View.js").State} */ (assign({}, frameState.viewState, {
|
||||
rotation: 0
|
||||
}))
|
||||
}));
|
||||
const newSkippedFeatures = Object.keys(imageFrameState.skippedFeatureUids).sort();
|
||||
image = new ImageCanvas(renderedExtent, viewResolution, pixelRatio, context.canvas, function(callback) {
|
||||
if (vectorRenderer.prepareFrame(imageFrameState, layerState) &&
|
||||
(vectorRenderer.replayGroupChanged ||
|
||||
!equals(skippedFeatures, newSkippedFeatures))) {
|
||||
context.canvas.width = imageFrameState.size[0] * pixelRatio;
|
||||
context.canvas.height = imageFrameState.size[1] * pixelRatio;
|
||||
vectorRenderer.compose(context, imageFrameState, layerState);
|
||||
skippedFeatures = newSkippedFeatures;
|
||||
callback();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
image = imageSource.getImage(
|
||||
renderedExtent, viewResolution, pixelRatio, projection);
|
||||
}
|
||||
const image = imageSource.getImage(renderedExtent, viewResolution, pixelRatio, projection);
|
||||
if (image && this.loadImage(image)) {
|
||||
this.image_ = image;
|
||||
this.skippedFeatures_ = skippedFeatures;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,40 +110,7 @@ class CanvasImageLayerRenderer extends IntermediateCanvasRenderer {
|
||||
return !!this.image_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback) {
|
||||
if (this.vectorRenderer_) {
|
||||
return this.vectorRenderer_.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback);
|
||||
} else {
|
||||
return super.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if this renderer handles the provided layer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The candidate layer.
|
||||
* @return {boolean} The renderer can render the layer.
|
||||
*/
|
||||
CanvasImageLayerRenderer['handles'] = function(layer) {
|
||||
return layer.getType() === LayerType.IMAGE ||
|
||||
layer.getType() === LayerType.VECTOR &&
|
||||
/** @type {import("../../layer/Vector.js").default} */ (layer).getRenderMode() === VectorRenderType.IMAGE;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a layer renderer.
|
||||
* @param {import("../Map.js").default} mapRenderer The map renderer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The layer to be rendererd.
|
||||
* @return {CanvasImageLayerRenderer} The layer renderer.
|
||||
*/
|
||||
CanvasImageLayerRenderer['create'] = function(mapRenderer, layer) {
|
||||
return new CanvasImageLayerRenderer(/** @type {import("../../layer/Image.js").default} */ (layer));
|
||||
};
|
||||
|
||||
|
||||
export default CanvasImageLayerRenderer;
|
||||
|
||||
@@ -136,6 +136,25 @@ class CanvasLayerRenderer extends LayerRenderer {
|
||||
this.dispatchComposeEvent_(RenderEventType.PRECOMPOSE, context, frameState, opt_transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
|
||||
* @param {import("../../transform.js").Transform=} opt_transform Transform.
|
||||
* @protected
|
||||
*/
|
||||
preRender(frameState, opt_transform) {
|
||||
// TODO: pre-render event
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
|
||||
* @param {import("../../layer/Layer.js").State} layerState Layer state.
|
||||
* @param {import("../../transform.js").Transform=} opt_transform Transform.
|
||||
* @protected
|
||||
*/
|
||||
postRender(frameState, layerState, opt_transform) {
|
||||
// TODO: pre-render event
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {CanvasRenderingContext2D} context Context.
|
||||
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
|
||||
@@ -175,15 +194,6 @@ class CanvasLayerRenderer extends LayerRenderer {
|
||||
abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
|
||||
* @param {import("../../layer/Layer.js").State} layerState Layer state.
|
||||
* @return {boolean} whether composeFrame should be called.
|
||||
*/
|
||||
prepareFrame(frameState, layerState) {
|
||||
return abstract();
|
||||
}
|
||||
}
|
||||
|
||||
export default CanvasLayerRenderer;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @module ol/renderer/canvas/Map
|
||||
*/
|
||||
import {create as createTransform, apply as applyTransform, compose as composeTransform} from '../../transform.js';
|
||||
import {includes, stableSort} from '../../array.js';
|
||||
import {stableSort} from '../../array.js';
|
||||
import {CLASS_UNSELECTABLE} from '../../css.js';
|
||||
import {createCanvasContext2D} from '../../dom.js';
|
||||
import {visibleAtResolution} from '../../layer/Layer.js';
|
||||
@@ -14,11 +14,6 @@ import MapRenderer, {sortByZIndex} from '../Map.js';
|
||||
import SourceState from '../../source/State.js';
|
||||
|
||||
|
||||
/**
|
||||
* @type {Array<typeof import("../Layer.js").default>}
|
||||
*/
|
||||
export const layerRendererConstructors = [];
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Canvas map renderer.
|
||||
@@ -204,18 +199,6 @@ class CanvasMapRenderer extends MapRenderer {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
registerLayerRenderers(constructors) {
|
||||
super.registerLayerRenderers(constructors);
|
||||
for (let i = 0, ii = constructors.length; i < ii; ++i) {
|
||||
const ctor = constructors[i];
|
||||
if (!includes(layerRendererConstructors, ctor)) {
|
||||
layerRendererConstructors.push(ctor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* @module ol/renderer/canvas/TileLayer
|
||||
*/
|
||||
import {getUid} from '../../util.js';
|
||||
import LayerType from '../../LayerType.js';
|
||||
import TileRange from '../../TileRange.js';
|
||||
import TileState from '../../TileState.js';
|
||||
import ViewHint from '../../ViewHint.js';
|
||||
@@ -369,27 +368,6 @@ class CanvasTileLayerRenderer extends IntermediateCanvasRenderer {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if this renderer handles the provided layer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The candidate layer.
|
||||
* @return {boolean} The renderer can render the layer.
|
||||
*/
|
||||
CanvasTileLayerRenderer['handles'] = function(layer) {
|
||||
return layer.getType() === LayerType.TILE;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a layer renderer.
|
||||
* @param {import("../Map.js").default} mapRenderer The map renderer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The layer to be rendererd.
|
||||
* @return {CanvasTileLayerRenderer} The layer renderer.
|
||||
*/
|
||||
CanvasTileLayerRenderer['create'] = function(mapRenderer, layer) {
|
||||
return new CanvasTileLayerRenderer(/** @type {import("../../layer/Tile.js").default} */ (layer));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @return {import("../../layer/Tile.js").default|import("../../layer/VectorTile.js").default}
|
||||
|
||||
129
src/ol/renderer/canvas/VectorImageLayer.js
Normal file
129
src/ol/renderer/canvas/VectorImageLayer.js
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* @module ol/renderer/canvas/ImageLayer
|
||||
*/
|
||||
import ImageCanvas from '../../ImageCanvas.js';
|
||||
import ViewHint from '../../ViewHint.js';
|
||||
import {equals} from '../../array.js';
|
||||
import {getHeight, getWidth, isEmpty} from '../../extent.js';
|
||||
import {assign} from '../../obj.js';
|
||||
import CanvasImageLayerRenderer from './ImageLayer.js';
|
||||
import {compose as composeTransform} from '../../transform.js';
|
||||
import CanvasVectorLayerRenderer from './VectorLayer.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Canvas renderer for image layers.
|
||||
* @api
|
||||
*/
|
||||
class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
|
||||
|
||||
/**
|
||||
* @param {import("../../layer/VectorImage.js").default} layer Vector image layer.
|
||||
*/
|
||||
constructor(layer) {
|
||||
super(layer);
|
||||
|
||||
/**
|
||||
* @type {!Array<string>}
|
||||
*/
|
||||
this.skippedFeatures_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("./VectorLayer.js").default}
|
||||
*/
|
||||
this.vectorRenderer_ = new CanvasVectorLayerRenderer(layer);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
disposeInternal() {
|
||||
this.vectorRenderer_.dispose();
|
||||
super.disposeInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
prepareFrame(frameState, layerState) {
|
||||
const pixelRatio = frameState.pixelRatio;
|
||||
const size = frameState.size;
|
||||
const viewState = frameState.viewState;
|
||||
const viewCenter = viewState.center;
|
||||
const viewResolution = viewState.resolution;
|
||||
|
||||
const hints = frameState.viewHints;
|
||||
const vectorRenderer = this.vectorRenderer_;
|
||||
const renderedExtent = frameState.extent;
|
||||
|
||||
if (!hints[ViewHint.ANIMATING] && !hints[ViewHint.INTERACTING] && !isEmpty(renderedExtent)) {
|
||||
let skippedFeatures = this.skippedFeatures_;
|
||||
const context = vectorRenderer.context;
|
||||
const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign({}, frameState, {
|
||||
size: [
|
||||
getWidth(renderedExtent) / viewResolution,
|
||||
getHeight(renderedExtent) / viewResolution
|
||||
],
|
||||
viewState: /** @type {import("../../View.js").State} */ (assign({}, frameState.viewState, {
|
||||
rotation: 0
|
||||
}))
|
||||
}));
|
||||
const newSkippedFeatures = Object.keys(imageFrameState.skippedFeatureUids).sort();
|
||||
const image = new ImageCanvas(renderedExtent, viewResolution, pixelRatio, context.canvas, function(callback) {
|
||||
if (vectorRenderer.prepareFrame(imageFrameState, layerState) &&
|
||||
(vectorRenderer.replayGroupChanged ||
|
||||
!equals(skippedFeatures, newSkippedFeatures))) {
|
||||
context.canvas.width = imageFrameState.size[0] * pixelRatio;
|
||||
context.canvas.height = imageFrameState.size[1] * pixelRatio;
|
||||
vectorRenderer.compose(context, imageFrameState, layerState);
|
||||
skippedFeatures = newSkippedFeatures;
|
||||
callback();
|
||||
}
|
||||
});
|
||||
if (this.loadImage(image)) {
|
||||
this.image_ = image;
|
||||
this.skippedFeatures_ = skippedFeatures;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.image_) {
|
||||
const image = this.image_;
|
||||
const imageExtent = image.getExtent();
|
||||
const imageResolution = image.getResolution();
|
||||
const imagePixelRatio = image.getPixelRatio();
|
||||
const scale = pixelRatio * imageResolution /
|
||||
(viewResolution * imagePixelRatio);
|
||||
const transform = composeTransform(this.imageTransform_,
|
||||
pixelRatio * size[0] / 2, pixelRatio * size[1] / 2,
|
||||
scale, scale,
|
||||
0,
|
||||
imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution,
|
||||
imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution);
|
||||
composeTransform(this.coordinateToCanvasPixelTransform,
|
||||
pixelRatio * size[0] / 2 - transform[4], pixelRatio * size[1] / 2 - transform[5],
|
||||
pixelRatio / viewResolution, -pixelRatio / viewResolution,
|
||||
0,
|
||||
-viewCenter[0], -viewCenter[1]);
|
||||
|
||||
this.renderedResolution = imageResolution * pixelRatio / imagePixelRatio;
|
||||
}
|
||||
|
||||
return !!this.image_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback) {
|
||||
if (this.vectorRenderer_) {
|
||||
return this.vectorRenderer_.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback);
|
||||
} else {
|
||||
return super.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default CanvasVectorImageLayerRenderer;
|
||||
@@ -2,7 +2,6 @@
|
||||
* @module ol/renderer/canvas/VectorLayer
|
||||
*/
|
||||
import {getUid} from '../../util.js';
|
||||
import LayerType from '../../LayerType.js';
|
||||
import ViewHint from '../../ViewHint.js';
|
||||
import {createCanvasContext2D} from '../../dom.js';
|
||||
import {listen, unlisten} from '../../events.js';
|
||||
@@ -83,7 +82,6 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
||||
this.context = createCanvasContext2D();
|
||||
|
||||
listen(labelCache, EventType.CLEAR, this.handleFontsChanged_, this);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,6 +224,114 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
||||
this.postCompose(context, frameState, layerState, transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
|
||||
* @param {import("../../layer/Layer.js").State} layerState Layer state.
|
||||
*/
|
||||
render(frameState, layerState) {
|
||||
const replayGroup = this.replayGroup_;
|
||||
if (!replayGroup || replayGroup.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const context = this.context;
|
||||
const canvas = context.canvas;
|
||||
|
||||
const extent = frameState.extent;
|
||||
const pixelRatio = frameState.pixelRatio;
|
||||
const viewState = frameState.viewState;
|
||||
const projection = viewState.projection;
|
||||
const rotation = viewState.rotation;
|
||||
const projectionExtent = projection.getExtent();
|
||||
const vectorSource = /** @type {import("../../source/Vector.js").default} */ (this.getLayer().getSource());
|
||||
|
||||
// clipped rendering if layer extent is set
|
||||
const clipExtent = layerState.extent;
|
||||
const clipped = clipExtent !== undefined;
|
||||
if (clipped) {
|
||||
this.clip(context, frameState, /** @type {import("../../extent.js").Extent} */ (clipExtent));
|
||||
}
|
||||
|
||||
if (this.declutterTree_) {
|
||||
this.declutterTree_.clear();
|
||||
}
|
||||
|
||||
// resize and clear
|
||||
let width = Math.round(frameState.size[0] * pixelRatio);
|
||||
let height = Math.round(frameState.size[1] * pixelRatio);
|
||||
if (rotation) {
|
||||
const size = Math.round(Math.sqrt(width * width + height * height));
|
||||
width = height = size;
|
||||
}
|
||||
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]);
|
||||
|
||||
// TODO: deal with rotation (this should not be necessary)
|
||||
if (rotation) {
|
||||
rotateAtOffset(context, -rotation, width / 2, height / 2);
|
||||
}
|
||||
|
||||
let transform = this.getTransform(frameState, 0);
|
||||
const skippedFeatureUids = layerState.managed ? frameState.skippedFeatureUids : {};
|
||||
replayGroup.replay(context, transform, rotation, skippedFeatureUids, snapToPixel);
|
||||
|
||||
if (vectorSource.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;
|
||||
transform = this.getTransform(frameState, offsetX);
|
||||
replayGroup.replay(context, transform, rotation, skippedFeatureUids, snapToPixel);
|
||||
startX += worldWidth;
|
||||
}
|
||||
world = 0;
|
||||
startX = extent[2];
|
||||
while (startX > projectionExtent[2]) {
|
||||
++world;
|
||||
offsetX = worldWidth * world;
|
||||
transform = this.getTransform(frameState, offsetX);
|
||||
replayGroup.replay(context, transform, rotation, skippedFeatureUids, snapToPixel);
|
||||
startX -= worldWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: deal with rotation (this should not be necessary)
|
||||
if (rotation) {
|
||||
rotateAtOffset(context, rotation, width / 2, height / 2);
|
||||
}
|
||||
|
||||
if (this.getLayer().hasListener(RenderEventType.RENDER)) {
|
||||
this.dispatchRenderEvent(context, frameState, transform);
|
||||
}
|
||||
|
||||
if (clipped) {
|
||||
context.restore();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
renderFrame(frameState, layerState) {
|
||||
const transform = this.getTransform(frameState, 0);
|
||||
this.preRender(frameState, transform);
|
||||
this.render(frameState, layerState);
|
||||
this.postRender(frameState, layerState, transform);
|
||||
return this.context.canvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -413,25 +519,4 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if this renderer handles the provided layer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The candidate layer.
|
||||
* @return {boolean} The renderer can render the layer.
|
||||
*/
|
||||
CanvasVectorLayerRenderer['handles'] = function(layer) {
|
||||
return layer.getType() === LayerType.VECTOR;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a layer renderer.
|
||||
* @param {import("../Map.js").default} mapRenderer The map renderer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The layer to be rendererd.
|
||||
* @return {CanvasVectorLayerRenderer} The layer renderer.
|
||||
*/
|
||||
CanvasVectorLayerRenderer['create'] = function(mapRenderer, layer) {
|
||||
return new CanvasVectorLayerRenderer(/** @type {import("../../layer/Vector.js").default} */ (layer));
|
||||
};
|
||||
|
||||
|
||||
export default CanvasVectorLayerRenderer;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* @module ol/renderer/canvas/VectorTileLayer
|
||||
*/
|
||||
import {getUid} from '../../util.js';
|
||||
import LayerType from '../../LayerType.js';
|
||||
import TileState from '../../TileState.js';
|
||||
import ViewHint from '../../ViewHint.js';
|
||||
import {createCanvasContext2D} from '../../dom.js';
|
||||
@@ -134,7 +133,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
||||
* @inheritDoc
|
||||
*/
|
||||
prepareFrame(frameState, layerState) {
|
||||
const layer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
|
||||
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
|
||||
const layerRevision = layer.getRevision();
|
||||
if (this.renderedLayerRevision_ != layerRevision) {
|
||||
this.renderedTiles.length = 0;
|
||||
@@ -328,7 +327,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
||||
* @inheritDoc
|
||||
*/
|
||||
postCompose(context, frameState, layerState) {
|
||||
const layer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
|
||||
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
|
||||
const renderMode = layer.getRenderMode();
|
||||
if (renderMode != VectorTileRenderType.IMAGE) {
|
||||
const declutterReplays = layer.getDeclutter() ? {} : null;
|
||||
@@ -447,7 +446,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
||||
* @private
|
||||
*/
|
||||
renderTileImage_(tile, pixelRatio, projection) {
|
||||
const layer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
|
||||
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
|
||||
const replayState = tile.getReplayState(layer);
|
||||
const revision = layer.getRevision();
|
||||
const replays = IMAGE_REPLAYS[layer.getRenderMode()];
|
||||
@@ -481,25 +480,4 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if this renderer handles the provided layer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The candidate layer.
|
||||
* @return {boolean} The renderer can render the layer.
|
||||
*/
|
||||
CanvasVectorTileLayerRenderer['handles'] = function(layer) {
|
||||
return layer.getType() === LayerType.VECTOR_TILE;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a layer renderer.
|
||||
* @param {import("../Map.js").default} mapRenderer The map renderer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The layer to be rendererd.
|
||||
* @return {CanvasVectorTileLayerRenderer} The layer renderer.
|
||||
*/
|
||||
CanvasVectorTileLayerRenderer['create'] = function(mapRenderer, layer) {
|
||||
return new CanvasVectorTileLayerRenderer(/** @type {import("../../layer/VectorTile.js").default} */ (layer));
|
||||
};
|
||||
|
||||
|
||||
export default CanvasVectorTileLayerRenderer;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* @module ol/renderer/webgl/ImageLayer
|
||||
*/
|
||||
import {ENABLE_RASTER_REPROJECTION} from '../../reproj/common.js';
|
||||
import LayerType from '../../LayerType.js';
|
||||
import ViewHint from '../../ViewHint.js';
|
||||
import {createCanvasContext2D} from '../../dom.js';
|
||||
import {getIntersection, isEmpty} from '../../extent.js';
|
||||
@@ -269,28 +268,4 @@ class WebGLImageLayerRenderer extends WebGLLayerRenderer {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if this renderer handles the provided layer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The candidate layer.
|
||||
* @return {boolean} The renderer can render the layer.
|
||||
*/
|
||||
WebGLImageLayerRenderer['handles'] = function(layer) {
|
||||
return layer.getType() === LayerType.IMAGE;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a layer renderer.
|
||||
* @param {import("../Map.js").default} mapRenderer The map renderer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The layer to be rendererd.
|
||||
* @return {WebGLImageLayerRenderer} The layer renderer.
|
||||
*/
|
||||
WebGLImageLayerRenderer['create'] = function(mapRenderer, layer) {
|
||||
return new WebGLImageLayerRenderer(
|
||||
/** @type {import("./Map.js").default} */ (mapRenderer),
|
||||
/** @type {import("../../layer/Image.js").default} */ (layer)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default WebGLImageLayerRenderer;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
// FIXME large resolutions lead to too large framebuffers :-(
|
||||
// FIXME animated shaders! check in redraw
|
||||
|
||||
import LayerType from '../../LayerType.js';
|
||||
import ImageTile from '../../ImageTile.js';
|
||||
import TileRange from '../../TileRange.js';
|
||||
import TileState from '../../TileState.js';
|
||||
@@ -396,28 +395,4 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if this renderer handles the provided layer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The candidate layer.
|
||||
* @return {boolean} The renderer can render the layer.
|
||||
*/
|
||||
WebGLTileLayerRenderer['handles'] = function(layer) {
|
||||
return layer.getType() === LayerType.TILE;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a layer renderer.
|
||||
* @param {import("../Map.js").default} mapRenderer The map renderer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The layer to be rendererd.
|
||||
* @return {WebGLTileLayerRenderer} The layer renderer.
|
||||
*/
|
||||
WebGLTileLayerRenderer['create'] = function(mapRenderer, layer) {
|
||||
return new WebGLTileLayerRenderer(
|
||||
/** @type {import("./Map.js").default} */ (mapRenderer),
|
||||
/** @type {import("../../layer/Tile.js").default} */ (layer)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default WebGLTileLayerRenderer;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* @module ol/renderer/webgl/VectorLayer
|
||||
*/
|
||||
import {getUid} from '../../util.js';
|
||||
import LayerType from '../../LayerType.js';
|
||||
import ViewHint from '../../ViewHint.js';
|
||||
import {buffer, containsExtent, createEmpty} from '../../extent.js';
|
||||
import WebGLReplayGroup from '../../render/webgl/ReplayGroup.js';
|
||||
@@ -304,28 +303,4 @@ class WebGLVectorLayerRenderer extends WebGLLayerRenderer {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if this renderer handles the provided layer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The candidate layer.
|
||||
* @return {boolean} The renderer can render the layer.
|
||||
*/
|
||||
WebGLVectorLayerRenderer['handles'] = function(layer) {
|
||||
return layer.getType() === LayerType.VECTOR;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a layer renderer.
|
||||
* @param {import("../Map.js").default} mapRenderer The map renderer.
|
||||
* @param {import("../../layer/Layer.js").default} layer The layer to be rendererd.
|
||||
* @return {WebGLVectorLayerRenderer} The layer renderer.
|
||||
*/
|
||||
WebGLVectorLayerRenderer['create'] = function(mapRenderer, layer) {
|
||||
return new WebGLVectorLayerRenderer(
|
||||
/** @type {import("./Map.js").default} */ (mapRenderer),
|
||||
/** @type {import("../../layer/Vector.js").default} */ (layer)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default WebGLVectorLayerRenderer;
|
||||
|
||||
@@ -10,15 +10,14 @@ import Event from '../events/Event.js';
|
||||
import EventType from '../events/EventType.js';
|
||||
import {Processor} from 'pixelworks/lib/index';
|
||||
import {equals, getCenter, getHeight, getWidth} from '../extent.js';
|
||||
import LayerType from '../LayerType.js';
|
||||
import ImageLayer from '../layer/Image.js';
|
||||
import TileLayer from '../layer/Tile.js';
|
||||
import {assign} from '../obj.js';
|
||||
import CanvasImageLayerRenderer from '../renderer/canvas/ImageLayer.js';
|
||||
import CanvasTileLayerRenderer from '../renderer/canvas/TileLayer.js';
|
||||
import ImageSource from './Image.js';
|
||||
import SourceState from './State.js';
|
||||
import {create as createTransform} from '../transform.js';
|
||||
import ImageSource from './Image.js';
|
||||
import TileSource from './Tile.js';
|
||||
import SourceState from './State.js';
|
||||
import Source from './Source.js';
|
||||
|
||||
|
||||
/**
|
||||
@@ -113,7 +112,7 @@ class RasterSourceEvent extends Event {
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {Array<import("./Source.js").default|import("../layer/Layer.js").default>} sources Input
|
||||
* sources or layers. Vector layers must be configured with `renderMode: 'image'`.
|
||||
* sources or layers. For vector data, use an VectorImage layer.
|
||||
* @property {Operation} [operation] Raster operation.
|
||||
* The operation will be called with data from input sources
|
||||
* and the output will be assigned to the raster source.
|
||||
@@ -490,42 +489,18 @@ function createRenderers(sources) {
|
||||
* @return {import("../renderer/canvas/Layer.js").default} The renderer.
|
||||
*/
|
||||
function createRenderer(layerOrSource) {
|
||||
const tileSource = /** @type {import("./Tile.js").default} */ (layerOrSource);
|
||||
const imageSource = /** @type {import("./Image.js").default} */ (layerOrSource);
|
||||
const layer = /** @type {import("../layer/Layer.js").default} */ (layerOrSource);
|
||||
let renderer = null;
|
||||
if (typeof tileSource.getTile === 'function') {
|
||||
renderer = createTileRenderer(tileSource);
|
||||
} else if (typeof imageSource.getImage === 'function') {
|
||||
renderer = createImageRenderer(imageSource);
|
||||
} else if (layer.getType() === LayerType.TILE) {
|
||||
renderer = new CanvasTileLayerRenderer(/** @type {import("../layer/Tile.js").default} */ (layer));
|
||||
} else if (layer.getType() == LayerType.IMAGE || layer.getType() == LayerType.VECTOR) {
|
||||
renderer = new CanvasImageLayerRenderer(/** @type {import("../layer/Image.js").default} */ (layer));
|
||||
// @type {import("../layer/Layer.js").default}
|
||||
let layer;
|
||||
if (layerOrSource instanceof Source) {
|
||||
if (layerOrSource instanceof TileSource) {
|
||||
layer = new TileLayer({source: layerOrSource});
|
||||
} else if (layerOrSource instanceof ImageSource) {
|
||||
layer = new ImageLayer({source: layerOrSource});
|
||||
}
|
||||
} else {
|
||||
layer = layerOrSource;
|
||||
}
|
||||
return renderer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create an image renderer for the provided source.
|
||||
* @param {import("./Image.js").default} source The source.
|
||||
* @return {import("../renderer/canvas/Layer.js").default} The renderer.
|
||||
*/
|
||||
function createImageRenderer(source) {
|
||||
const layer = new ImageLayer({source: source});
|
||||
return new CanvasImageLayerRenderer(layer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a tile renderer for the provided source.
|
||||
* @param {import("./Tile.js").default} source The source.
|
||||
* @return {import("../renderer/canvas/Layer.js").default} The renderer.
|
||||
*/
|
||||
function createTileRenderer(source) {
|
||||
const layer = new TileLayer({source: source});
|
||||
return new CanvasTileLayerRenderer(layer);
|
||||
return layer ? /** @type {import("../renderer/canvas/Layer.js").default} */ (layer.createRenderer()) : null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import Map from '../../../../src/ol/Map.js';
|
||||
import WebGLMap from '../../../../src/ol/WebGLMap.js';
|
||||
import View from '../../../../src/ol/View.js';
|
||||
import ImageLayer from '../../../../src/ol/layer/Image.js';
|
||||
import WebGLImageLayer from '../../../../src/ol/layer/Image.js';
|
||||
import {assign} from '../../../../src/ol/obj.js';
|
||||
import {get as getProjection, transform, transformExtent} from '../../../../src/ol/proj.js';
|
||||
import Static from '../../../../src/ol/source/ImageStatic.js';
|
||||
@@ -12,10 +14,10 @@ describe('ol.rendering.layer.Image', function() {
|
||||
let map;
|
||||
|
||||
function createMap(renderer) {
|
||||
map = new Map({
|
||||
const MapConstructor = renderer === 'webgl' ? WebGLMap : Map;
|
||||
map = new MapConstructor({
|
||||
pixelRatio: 1,
|
||||
target: createMapDiv(50, 50),
|
||||
renderer: renderer,
|
||||
view: new View({
|
||||
center: transform(
|
||||
[-122.416667, 37.783333], 'EPSG:4326', 'EPSG:3857'),
|
||||
@@ -31,7 +33,8 @@ describe('ol.rendering.layer.Image', function() {
|
||||
map = null;
|
||||
});
|
||||
|
||||
function waitForImages(sources, layerOptions, onImagesLoaded) {
|
||||
function waitForImages(renderer, sources, layerOptions, onImagesLoaded) {
|
||||
const LayerConstructor = renderer === 'webgl' ? WebGLImageLayer : ImageLayer;
|
||||
let imagesLoading = 0;
|
||||
let imagesLoaded = 0;
|
||||
|
||||
@@ -57,7 +60,7 @@ describe('ol.rendering.layer.Image', function() {
|
||||
source: source
|
||||
};
|
||||
assign(options, layerOptions);
|
||||
map.addLayer(new ImageLayer(options));
|
||||
map.addLayer(new LayerConstructor(options));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -75,7 +78,7 @@ describe('ol.rendering.layer.Image', function() {
|
||||
|
||||
it('tests the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
waitForImages([source], {}, function() {
|
||||
waitForImages('canvas', [source], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/image-canvas.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -84,7 +87,7 @@ describe('ol.rendering.layer.Image', function() {
|
||||
where('WebGL').it('tests the WebGL renderer', function(done) {
|
||||
assertWebGL();
|
||||
createMap('webgl');
|
||||
waitForImages([source], {}, function() {
|
||||
waitForImages('webgl', [source], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/image-webgl.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -104,7 +107,7 @@ describe('ol.rendering.layer.Image', function() {
|
||||
|
||||
it('renders correctly', function(done) {
|
||||
createMap('canvas');
|
||||
waitForImages([source], {}, function() {
|
||||
waitForImages('canvas', [source], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/image-scaled.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import Map from '../../../../src/ol/Map.js';
|
||||
import WebGLMap from '../../../../src/ol/WebGLMap.js';
|
||||
import View from '../../../../src/ol/View.js';
|
||||
import {getSize} from '../../../../src/ol/extent.js';
|
||||
import Point from '../../../../src/ol/geom/Point.js';
|
||||
import TileLayer from '../../../../src/ol/layer/Tile.js';
|
||||
import WebGLTileLayer from '../../../../src/ol/layer/WebGLTile.js';
|
||||
import {assign} from '../../../../src/ol/obj.js';
|
||||
import {transform} from '../../../../src/ol/proj.js';
|
||||
import TileImage from '../../../../src/ol/source/TileImage.js';
|
||||
@@ -18,12 +20,12 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
let map;
|
||||
|
||||
function createMap(renderer, opt_center, opt_size, opt_pixelRatio, opt_resolutions) {
|
||||
const MapConstructor = renderer === 'webgl' ? WebGLMap : Map;
|
||||
const size = opt_size !== undefined ? opt_size : [50, 50];
|
||||
|
||||
map = new Map({
|
||||
map = new MapConstructor({
|
||||
pixelRatio: opt_pixelRatio || 1,
|
||||
target: createMapDiv(size[0], size[1]),
|
||||
renderer: renderer,
|
||||
view: new View({
|
||||
center: opt_center !== undefined ? opt_center : transform(
|
||||
[-122.416667, 37.783333], 'EPSG:4326', 'EPSG:3857'),
|
||||
@@ -40,7 +42,8 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
map = null;
|
||||
});
|
||||
|
||||
function waitForTiles(sources, layerOptions, onTileLoaded) {
|
||||
function waitForTiles(renderer, sources, layerOptions, onTileLoaded) {
|
||||
const LayerConstructor = renderer === 'webgl' ? WebGLTileLayer : TileLayer;
|
||||
let tilesLoading = 0;
|
||||
let tileLoaded = 0;
|
||||
|
||||
@@ -66,7 +69,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
source: source
|
||||
};
|
||||
assign(options, layerOptions[i] || layerOptions);
|
||||
map.addLayer(new TileLayer(options));
|
||||
map.addLayer(new LayerConstructor(options));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,7 +79,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
const source = new XYZ({
|
||||
url: 'rendering/ol/data/tiles/osm/{z}/{x}/{y}.png'
|
||||
});
|
||||
waitForTiles([source], {}, function() {
|
||||
waitForTiles('canvas', [source], {}, function() {
|
||||
setTimeout(function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/osm-canvas.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
@@ -97,7 +100,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
|
||||
it('tests the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
waitForTiles([source], {}, function() {
|
||||
waitForTiles('canvas', [source], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/osm-canvas.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -106,7 +109,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
where('WebGL').it('tests the WebGL renderer', function(done) {
|
||||
assertWebGL();
|
||||
createMap('webgl');
|
||||
waitForTiles([source], {}, function() {
|
||||
waitForTiles('webgl', [source], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/osm-webgl.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -130,7 +133,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
where('WebGL').it('tests the WebGL renderer', function(done) {
|
||||
assertWebGL();
|
||||
createMap('webgl');
|
||||
waitForTiles([source1, source2], {}, function() {
|
||||
waitForTiles('webgl', [source1, source2], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/2-layers-webgl.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -145,7 +148,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
|
||||
it('tests canvas layer extent clipping', function(done) {
|
||||
createMap('canvas');
|
||||
waitForTiles([source1, source2], [{}, {extent: centerExtent(map)}], function() {
|
||||
waitForTiles('canvas', [source1, source2], [{}, {extent: centerExtent(map)}], function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/2-layers-canvas-extent.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -154,7 +157,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
it('tests canvas layer extent clipping with rotation', function(done) {
|
||||
createMap('canvas');
|
||||
map.getView().setRotation(Math.PI / 2);
|
||||
waitForTiles([source1, source2], [{}, {extent: centerExtent(map)}], function() {
|
||||
waitForTiles('canvas', [source1, source2], [{}, {extent: centerExtent(map)}], function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/2-layers-canvas-extent-rotate.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -162,7 +165,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
|
||||
it('tests canvas layer extent clipping (HiDPI)', function(done) {
|
||||
createMap('canvas', undefined, undefined, 2);
|
||||
waitForTiles([source1, source2], [{}, {extent: centerExtent(map)}], function() {
|
||||
waitForTiles('canvas', [source1, source2], [{}, {extent: centerExtent(map)}], function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/2-layers-canvas-extent-hidpi.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -171,7 +174,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
it('tests canvas layer extent clipping with rotation (HiDPI)', function(done) {
|
||||
createMap('canvas', undefined, undefined, 2);
|
||||
map.getView().setRotation(Math.PI / 2);
|
||||
waitForTiles([source1, source2], [{}, {extent: centerExtent(map)}], function() {
|
||||
waitForTiles('canvas', [source1, source2], [{}, {extent: centerExtent(map)}], function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/2-layers-canvas-extent-rotate-hidpi.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -191,7 +194,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
|
||||
it('tests the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
waitForTiles([source], {opacity: 0.2}, function() {
|
||||
waitForTiles('canvas', [source], {opacity: 0.2}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/opacity-canvas.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -200,7 +203,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
where('WebGL').it('tests the WebGL renderer', function(done) {
|
||||
assertWebGL();
|
||||
createMap('webgl');
|
||||
waitForTiles([source], {opacity: 0.2}, function() {
|
||||
waitForTiles('webgl', [source], {opacity: 0.2}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/opacity-webgl.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -222,7 +225,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
it('512x256 renders correcly using the canvas renderer', function(done) {
|
||||
const source = createSource('512x256');
|
||||
createMap('canvas', [-10997148, 4569099]);
|
||||
waitForTiles([source], {}, function() {
|
||||
waitForTiles('canvas', [source], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/512x256-canvas.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -232,7 +235,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
assertWebGL();
|
||||
const source = createSource('512x256');
|
||||
createMap('webgl', [-10997148, 4569099]);
|
||||
waitForTiles([source], {}, function() {
|
||||
waitForTiles('webgl', [source], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/512x256-webgl.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -242,7 +245,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
const source = createSource('192x256');
|
||||
createMap('canvas', [-11271098, 3747248], [100, 100], undefined,
|
||||
source.getTileGrid().getResolutions());
|
||||
waitForTiles([source], {}, function() {
|
||||
waitForTiles('canvas', [source], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/192x256-canvas.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -253,7 +256,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
const source = createSource('192x256');
|
||||
createMap('webgl', [-11271098, 3747248], [100, 100], undefined,
|
||||
source.getTileGrid().getResolutions());
|
||||
waitForTiles([source], {}, function() {
|
||||
waitForTiles('webgl', [source], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/192x256-webgl.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
@@ -284,7 +287,7 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
it('works with the canvas renderer', function(done) {
|
||||
createMap('canvas', undefined, [100, 100]);
|
||||
map.getLayers().on('add', onAddLayer);
|
||||
waitForTiles([source], {}, function() {
|
||||
waitForTiles('canvas', [source], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/render-canvas.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
|
||||
@@ -20,11 +20,10 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
const center = [1825927.7316762917, 6143091.089223046];
|
||||
|
||||
let map;
|
||||
function createMap(renderer) {
|
||||
function createMap() {
|
||||
map = new Map({
|
||||
pixelRatio: 1,
|
||||
target: createMapDiv(80, 80),
|
||||
renderer: renderer,
|
||||
view: new View({
|
||||
center: center,
|
||||
zoom: 13
|
||||
@@ -74,7 +73,7 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
|
||||
it('renders opacity correctly with the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
const smallLine = new Feature(new LineString([
|
||||
[center[0], center[1] - 1],
|
||||
[center[0], center[1] + 1]
|
||||
@@ -99,35 +98,8 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('renders opacity correctly with renderMode: \'image\'', function(done) {
|
||||
createMap('canvas');
|
||||
const smallLine = new Feature(new LineString([
|
||||
[center[0], center[1] - 1],
|
||||
[center[0], center[1] + 1]
|
||||
]));
|
||||
smallLine.setStyle(new Style({
|
||||
zIndex: -99,
|
||||
stroke: new Stroke({width: 75, color: 'red'})
|
||||
}));
|
||||
source.addFeature(smallLine);
|
||||
addPolygon(100);
|
||||
addCircle(200);
|
||||
addPolygon(250);
|
||||
addCircle(500);
|
||||
addPolygon(600);
|
||||
addPolygon(720);
|
||||
map.addLayer(new VectorLayer({
|
||||
renerMode: 'image',
|
||||
source: source
|
||||
}));
|
||||
map.once('postrender', function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas.png',
|
||||
17, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders transparent layers correctly with the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
const smallLine = new Feature(new LineString([
|
||||
[center[0], center[1] - 1],
|
||||
[center[0], center[1] + 1]
|
||||
@@ -165,48 +137,8 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('renders transparent layers correctly with renderMode: \'image\'', function(done) {
|
||||
createMap('canvas');
|
||||
const smallLine = new Feature(new LineString([
|
||||
[center[0], center[1] - 1],
|
||||
[center[0], center[1] + 1]
|
||||
]));
|
||||
smallLine.setStyle([
|
||||
new Style({
|
||||
stroke: new Stroke({width: 75, color: 'red'})
|
||||
}),
|
||||
new Style({
|
||||
stroke: new Stroke({width: 45, color: 'white'})
|
||||
})
|
||||
]);
|
||||
source.addFeature(smallLine);
|
||||
const smallLine2 = new Feature(new LineString([
|
||||
[center[0], center[1] - 1000],
|
||||
[center[0], center[1] + 1000]
|
||||
]));
|
||||
smallLine2.setStyle([
|
||||
new Style({
|
||||
stroke: new Stroke({width: 35, color: 'blue'})
|
||||
}),
|
||||
new Style({
|
||||
stroke: new Stroke({width: 15, color: 'green'})
|
||||
})
|
||||
]);
|
||||
source.addFeature(smallLine2);
|
||||
|
||||
map.addLayer(new VectorLayer({
|
||||
renderMode: 'image',
|
||||
source: source,
|
||||
opacity: 0.5
|
||||
}));
|
||||
map.once('postrender', function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-transparent.png',
|
||||
7, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders rotation correctly with the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
map.getView().setRotation(Math.PI + Math.PI / 4);
|
||||
addPolygon(300);
|
||||
addCircle(500);
|
||||
@@ -225,55 +157,8 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('renders rotation correctly with renderMode: \'image\'', function(done) {
|
||||
createMap('canvas');
|
||||
map.getView().setRotation(Math.PI + Math.PI / 4);
|
||||
addPolygon(300);
|
||||
addCircle(500);
|
||||
map.addLayer(new VectorLayer({
|
||||
renderMode: 'image',
|
||||
source: source,
|
||||
style: new Style({
|
||||
stroke: new Stroke({
|
||||
width: 2,
|
||||
color: 'black'
|
||||
})
|
||||
})
|
||||
}));
|
||||
map.once('postrender', function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-rotated.png',
|
||||
2.9, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('unskips features correctly with renderMode: \'image\'', function(done) {
|
||||
createMap('canvas');
|
||||
addCircle(500);
|
||||
addPolygon(300);
|
||||
map.skipFeature(source.getFeatures()[1]);
|
||||
map.addLayer(new VectorLayer({
|
||||
renderMode: 'image',
|
||||
source: source,
|
||||
style: new Style({
|
||||
fill: new Fill({
|
||||
color: 'rgba(255,0,0,0.5)'
|
||||
}),
|
||||
stroke: new Stroke({
|
||||
width: 2,
|
||||
color: 'black'
|
||||
})
|
||||
})
|
||||
}));
|
||||
map.renderSync();
|
||||
map.unskipFeature(source.getFeatures()[1]);
|
||||
map.once('postrender', function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders fill/stroke batches correctly with the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
source = new VectorSource({
|
||||
overlaps: false
|
||||
});
|
||||
@@ -299,7 +184,7 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
|
||||
it('renders stroke batches correctly with the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
source = new VectorSource({
|
||||
overlaps: false
|
||||
});
|
||||
@@ -323,7 +208,7 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
|
||||
it('interrupts fill/stroke batches correctly with the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
let color;
|
||||
function createSource(overlaps) {
|
||||
color = '#3399CC';
|
||||
@@ -376,7 +261,7 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
|
||||
it('interrupts stroke batches correctly with the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
let color;
|
||||
function createSource(overlaps) {
|
||||
color = '#3399CC';
|
||||
@@ -583,7 +468,7 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
|
||||
it('declutters text', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
const layer = new VectorLayer({
|
||||
source: source
|
||||
});
|
||||
@@ -622,49 +507,8 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('declutters text with renderMode: \'image\'', function(done) {
|
||||
createMap('canvas');
|
||||
const layer = new VectorLayer({
|
||||
renderMode: 'image',
|
||||
source: source
|
||||
});
|
||||
map.addLayer(layer);
|
||||
|
||||
const centerFeature = new Feature({
|
||||
geometry: new Point(center),
|
||||
text: 'center'
|
||||
});
|
||||
source.addFeature(centerFeature);
|
||||
source.addFeature(new Feature({
|
||||
geometry: new Point([center[0] - 540, center[1]]),
|
||||
text: 'west'
|
||||
}));
|
||||
source.addFeature(new Feature({
|
||||
geometry: new Point([center[0] + 540, center[1]]),
|
||||
text: 'east'
|
||||
}));
|
||||
|
||||
layer.setDeclutter(true);
|
||||
layer.setStyle(function(feature) {
|
||||
return new Style({
|
||||
text: new Text({
|
||||
text: feature.get('text'),
|
||||
font: '12px sans-serif'
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
map.once('postrender', function() {
|
||||
const hitDetected = map.getFeaturesAtPixel([42, 42]);
|
||||
expect(hitDetected).to.have.length(1);
|
||||
expect(hitDetected[0]).to.equal(centerFeature);
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-declutter.png',
|
||||
2.2, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('declutters text and respects z-index', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
const layer = new VectorLayer({
|
||||
source: source
|
||||
});
|
||||
@@ -704,7 +548,7 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
|
||||
it('declutters images', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
const layer = new VectorLayer({
|
||||
source: source
|
||||
});
|
||||
@@ -742,48 +586,8 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('declutters images with renderMode: \'image\'', function(done) {
|
||||
createMap('canvas');
|
||||
const layer = new VectorLayer({
|
||||
renderMode: 'image',
|
||||
source: source
|
||||
});
|
||||
map.addLayer(layer);
|
||||
|
||||
const centerFeature = new Feature({
|
||||
geometry: new Point(center)
|
||||
});
|
||||
source.addFeature(centerFeature);
|
||||
source.addFeature(new Feature({
|
||||
geometry: new Point([center[0] - 540, center[1]])
|
||||
}));
|
||||
source.addFeature(new Feature({
|
||||
geometry: new Point([center[0] + 540, center[1]])
|
||||
}));
|
||||
|
||||
layer.setDeclutter(true);
|
||||
layer.setStyle(function(feature) {
|
||||
return new Style({
|
||||
image: new CircleStyle({
|
||||
radius: 15,
|
||||
stroke: new Stroke({
|
||||
color: 'blue'
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
map.once('postrender', function() {
|
||||
const hitDetected = map.getFeaturesAtPixel([40, 40]);
|
||||
expect(hitDetected).to.have.length(1);
|
||||
expect(hitDetected[0]).to.equal(centerFeature);
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-declutter-image.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('declutters images and respects z-index', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
const layer = new VectorLayer({
|
||||
source: source
|
||||
});
|
||||
@@ -822,7 +626,7 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
|
||||
it('declutters image & text groups', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
const layer = new VectorLayer({
|
||||
source: source
|
||||
});
|
||||
@@ -866,50 +670,7 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
|
||||
it('declutters text along lines and images', function(done) {
|
||||
createMap('canvas');
|
||||
const layer = new VectorLayer({
|
||||
source: source
|
||||
});
|
||||
map.addLayer(layer);
|
||||
|
||||
const point = new Feature(new Point(center));
|
||||
point.setStyle(new Style({
|
||||
image: new CircleStyle({
|
||||
radius: 8,
|
||||
stroke: new Stroke({
|
||||
color: 'blue'
|
||||
})
|
||||
})
|
||||
}));
|
||||
const line = new Feature(new LineString([
|
||||
[center[0] - 650, center[1] - 200],
|
||||
[center[0] + 650, center[1] - 200]
|
||||
]));
|
||||
line.setStyle(new Style({
|
||||
stroke: new Stroke({
|
||||
color: '#CCC',
|
||||
width: 12
|
||||
}),
|
||||
text: new Text({
|
||||
placement: 'line',
|
||||
text: 'east-west',
|
||||
font: '12px sans-serif'
|
||||
})
|
||||
}));
|
||||
|
||||
source.addFeature(point);
|
||||
source.addFeature(line);
|
||||
|
||||
layer.setDeclutter(true);
|
||||
|
||||
map.once('postrender', function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-declutter-line.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('declutters text along lines and images with renderMode: \'image\'', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
const layer = new VectorLayer({
|
||||
source: source
|
||||
});
|
||||
@@ -952,7 +713,7 @@ describe('ol.rendering.layer.Vector', function() {
|
||||
});
|
||||
|
||||
it('declutters text along lines and images with z-index', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
const layer = new VectorLayer({
|
||||
source: source
|
||||
});
|
||||
|
||||
288
test/rendering/ol/layer/vectorimage.test.js
Normal file
288
test/rendering/ol/layer/vectorimage.test.js
Normal file
@@ -0,0 +1,288 @@
|
||||
import Circle from '../../../../src/ol/geom/Circle.js';
|
||||
import CircleStyle from '../../../../src/ol/style/Circle.js';
|
||||
import Feature from '../../../../src/ol/Feature.js';
|
||||
import Fill from '../../../../src/ol/style/Fill.js';
|
||||
import LineString from '../../../../src/ol/geom/LineString.js';
|
||||
import Map from '../../../../src/ol/Map.js';
|
||||
import Point from '../../../../src/ol/geom/Point.js';
|
||||
import Polygon from '../../../../src/ol/geom/Polygon.js';
|
||||
import Stroke from '../../../../src/ol/style/Stroke.js';
|
||||
import Style from '../../../../src/ol/style/Style.js';
|
||||
import Text from '../../../../src/ol/style/Text.js';
|
||||
import VectorImageLayer from '../../../../src/ol/layer/VectorImage.js';
|
||||
import VectorSource from '../../../../src/ol/source/Vector.js';
|
||||
import View from '../../../../src/ol/View.js';
|
||||
|
||||
describe('ol.rendering.layer.VectorImage', function() {
|
||||
|
||||
const center = [1825927.7316762917, 6143091.089223046];
|
||||
|
||||
let map, source;
|
||||
function createMap() {
|
||||
source = new VectorSource();
|
||||
map = new Map({
|
||||
pixelRatio: 1,
|
||||
target: createMapDiv(80, 80),
|
||||
view: new View({
|
||||
center: center,
|
||||
zoom: 13
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
afterEach(function() {
|
||||
if (map) {
|
||||
disposeMap(map);
|
||||
}
|
||||
map = null;
|
||||
});
|
||||
|
||||
function addCircle(r) {
|
||||
source.addFeature(new Feature(new Circle(center, r)));
|
||||
}
|
||||
|
||||
function addPolygon(r) {
|
||||
source.addFeature(new Feature(new Polygon([
|
||||
[
|
||||
[center[0] - r, center[1] - r],
|
||||
[center[0] + r, center[1] - r],
|
||||
[center[0] + r, center[1] + r],
|
||||
[center[0] - r, center[1] + r],
|
||||
[center[0] - r, center[1] - r]
|
||||
]
|
||||
])));
|
||||
}
|
||||
|
||||
it('renders opacity correctly', function(done) {
|
||||
createMap();
|
||||
const smallLine = new Feature(new LineString([
|
||||
[center[0], center[1] - 1],
|
||||
[center[0], center[1] + 1]
|
||||
]));
|
||||
smallLine.setStyle(new Style({
|
||||
zIndex: -99,
|
||||
stroke: new Stroke({width: 75, color: 'red'})
|
||||
}));
|
||||
source.addFeature(smallLine);
|
||||
addPolygon(100);
|
||||
addCircle(200);
|
||||
addPolygon(250);
|
||||
addCircle(500);
|
||||
addPolygon(600);
|
||||
addPolygon(720);
|
||||
map.addLayer(new VectorImageLayer({
|
||||
source: source
|
||||
}));
|
||||
map.once('postrender', function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas.png',
|
||||
17, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders transparent layers correctly', function(done) {
|
||||
createMap();
|
||||
const smallLine = new Feature(new LineString([
|
||||
[center[0], center[1] - 1],
|
||||
[center[0], center[1] + 1]
|
||||
]));
|
||||
smallLine.setStyle([
|
||||
new Style({
|
||||
stroke: new Stroke({width: 75, color: 'red'})
|
||||
}),
|
||||
new Style({
|
||||
stroke: new Stroke({width: 45, color: 'white'})
|
||||
})
|
||||
]);
|
||||
source.addFeature(smallLine);
|
||||
const smallLine2 = new Feature(new LineString([
|
||||
[center[0], center[1] - 1000],
|
||||
[center[0], center[1] + 1000]
|
||||
]));
|
||||
smallLine2.setStyle([
|
||||
new Style({
|
||||
stroke: new Stroke({width: 35, color: 'blue'})
|
||||
}),
|
||||
new Style({
|
||||
stroke: new Stroke({width: 15, color: 'green'})
|
||||
})
|
||||
]);
|
||||
source.addFeature(smallLine2);
|
||||
|
||||
map.addLayer(new VectorImageLayer({
|
||||
source: source,
|
||||
opacity: 0.5
|
||||
}));
|
||||
map.once('postrender', function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-transparent.png',
|
||||
7, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders rotation correctly', function(done) {
|
||||
createMap();
|
||||
map.getView().setRotation(Math.PI + Math.PI / 4);
|
||||
addPolygon(300);
|
||||
addCircle(500);
|
||||
map.addLayer(new VectorImageLayer({
|
||||
source: source,
|
||||
style: new Style({
|
||||
stroke: new Stroke({
|
||||
width: 2,
|
||||
color: 'black'
|
||||
})
|
||||
})
|
||||
}));
|
||||
map.once('postrender', function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-rotated.png',
|
||||
2.9, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('unskips features correctly', function(done) {
|
||||
createMap();
|
||||
addCircle(500);
|
||||
addPolygon(300);
|
||||
map.skipFeature(source.getFeatures()[1]);
|
||||
map.addLayer(new VectorImageLayer({
|
||||
source: source,
|
||||
style: new Style({
|
||||
fill: new Fill({
|
||||
color: 'rgba(255,0,0,0.5)'
|
||||
}),
|
||||
stroke: new Stroke({
|
||||
width: 2,
|
||||
color: 'black'
|
||||
})
|
||||
})
|
||||
}));
|
||||
map.renderSync();
|
||||
map.unskipFeature(source.getFeatures()[1]);
|
||||
map.once('postrender', function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('declutters text', function(done) {
|
||||
createMap();
|
||||
const layer = new VectorImageLayer({
|
||||
source: source
|
||||
});
|
||||
map.addLayer(layer);
|
||||
|
||||
const centerFeature = new Feature({
|
||||
geometry: new Point(center),
|
||||
text: 'center'
|
||||
});
|
||||
source.addFeature(centerFeature);
|
||||
source.addFeature(new Feature({
|
||||
geometry: new Point([center[0] - 540, center[1]]),
|
||||
text: 'west'
|
||||
}));
|
||||
source.addFeature(new Feature({
|
||||
geometry: new Point([center[0] + 540, center[1]]),
|
||||
text: 'east'
|
||||
}));
|
||||
|
||||
layer.setDeclutter(true);
|
||||
layer.setStyle(function(feature) {
|
||||
return new Style({
|
||||
text: new Text({
|
||||
text: feature.get('text'),
|
||||
font: '12px sans-serif'
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
map.once('postrender', function() {
|
||||
const hitDetected = map.getFeaturesAtPixel([42, 42]);
|
||||
expect(hitDetected).to.have.length(1);
|
||||
expect(hitDetected[0]).to.equal(centerFeature);
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-declutter.png',
|
||||
2.2, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('declutters images', function(done) {
|
||||
createMap();
|
||||
const layer = new VectorImageLayer({
|
||||
source: source
|
||||
});
|
||||
map.addLayer(layer);
|
||||
|
||||
const centerFeature = new Feature({
|
||||
geometry: new Point(center)
|
||||
});
|
||||
source.addFeature(centerFeature);
|
||||
source.addFeature(new Feature({
|
||||
geometry: new Point([center[0] - 540, center[1]])
|
||||
}));
|
||||
source.addFeature(new Feature({
|
||||
geometry: new Point([center[0] + 540, center[1]])
|
||||
}));
|
||||
|
||||
layer.setDeclutter(true);
|
||||
layer.setStyle(function(feature) {
|
||||
return new Style({
|
||||
image: new CircleStyle({
|
||||
radius: 15,
|
||||
stroke: new Stroke({
|
||||
color: 'blue'
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
map.once('postrender', function() {
|
||||
const hitDetected = map.getFeaturesAtPixel([40, 40]);
|
||||
expect(hitDetected).to.have.length(1);
|
||||
expect(hitDetected[0]).to.equal(centerFeature);
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-declutter-image.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('declutters text along lines and images', function(done) {
|
||||
createMap();
|
||||
const layer = new VectorImageLayer({
|
||||
source: source
|
||||
});
|
||||
map.addLayer(layer);
|
||||
|
||||
const point = new Feature(new Point(center));
|
||||
point.setStyle(new Style({
|
||||
image: new CircleStyle({
|
||||
radius: 8,
|
||||
stroke: new Stroke({
|
||||
color: 'blue'
|
||||
})
|
||||
})
|
||||
}));
|
||||
const line = new Feature(new LineString([
|
||||
[center[0] - 650, center[1] - 200],
|
||||
[center[0] + 650, center[1] - 200]
|
||||
]));
|
||||
line.setStyle(new Style({
|
||||
stroke: new Stroke({
|
||||
color: '#CCC',
|
||||
width: 12
|
||||
}),
|
||||
text: new Text({
|
||||
placement: 'line',
|
||||
text: 'east-west',
|
||||
font: '12px sans-serif'
|
||||
})
|
||||
}));
|
||||
|
||||
source.addFeature(point);
|
||||
source.addFeature(line);
|
||||
|
||||
layer.setDeclutter(true);
|
||||
|
||||
map.once('postrender', function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vector-canvas-declutter-line.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -19,12 +19,11 @@ describe('ol.rendering.layer.VectorTile', function() {
|
||||
|
||||
let map;
|
||||
|
||||
function createMap(renderer, opt_pixelRatio, opt_size) {
|
||||
function createMap(opt_pixelRatio, opt_size) {
|
||||
const size = opt_size || 50;
|
||||
map = new Map({
|
||||
pixelRatio: opt_pixelRatio || 1,
|
||||
target: createMapDiv(size, size),
|
||||
renderer: renderer,
|
||||
view: new View({
|
||||
center: [1825927.7316762917, 6143091.089223046],
|
||||
zoom: 14
|
||||
@@ -78,7 +77,7 @@ describe('ol.rendering.layer.VectorTile', function() {
|
||||
});
|
||||
|
||||
it('renders correctly with the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
waitForTiles(source, {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vectortile-canvas.png',
|
||||
22, done);
|
||||
@@ -86,7 +85,7 @@ describe('ol.rendering.layer.VectorTile', function() {
|
||||
});
|
||||
|
||||
it('renders rotated view correctly with the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
map.getView().setRotation(Math.PI / 4);
|
||||
waitForTiles(source, {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vectortile-canvas-rotated.png',
|
||||
@@ -95,7 +94,7 @@ describe('ol.rendering.layer.VectorTile', function() {
|
||||
});
|
||||
|
||||
it('renders rotated view correctly with vector layer on top', function(done) {
|
||||
createMap('canvas');
|
||||
createMap();
|
||||
const vectorSource = new VectorSource({
|
||||
features: [
|
||||
new Feature(new Point([1825727.7316762917, 6143091.089223046]))
|
||||
@@ -121,7 +120,7 @@ describe('ol.rendering.layer.VectorTile', function() {
|
||||
});
|
||||
|
||||
it('renders correctly with the canvas renderer (HiDPI)', function(done) {
|
||||
createMap('canvas', 2);
|
||||
createMap(2);
|
||||
waitForTiles(source, {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vectortile-canvas-hidpi.png',
|
||||
11.3, done);
|
||||
@@ -129,7 +128,7 @@ describe('ol.rendering.layer.VectorTile', function() {
|
||||
});
|
||||
|
||||
it('renders rotated view correctly with the canvas renderer (HiDPI)', function(done) {
|
||||
createMap('canvas', 2);
|
||||
createMap(2);
|
||||
map.getView().setRotation(Math.PI / 4);
|
||||
waitForTiles(source, {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/vectortile-canvas-rotated-hidpi.png',
|
||||
@@ -138,7 +137,7 @@ describe('ol.rendering.layer.VectorTile', function() {
|
||||
});
|
||||
|
||||
it('declutters text and images', function(done) {
|
||||
createMap('canvas', 1, 100);
|
||||
createMap(1, 100);
|
||||
map.getView().setZoom(13.8);
|
||||
const style = function(feature, resolution) {
|
||||
const geom = feature.getGeometry();
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import Feature from '../../../src/ol/Feature.js';
|
||||
import Point from '../../../src/ol/geom/Point.js';
|
||||
import Map from '../../../src/ol/Map.js';
|
||||
import WebGLMap from '../../../src/ol/WebGLMap.js';
|
||||
import View from '../../../src/ol/View.js';
|
||||
import VectorLayer from '../../../src/ol/layer/Vector.js';
|
||||
import WebGLVectorLayer from '../../../src/ol/layer/WebGLVector.js';
|
||||
import VectorSource from '../../../src/ol/source/Vector.js';
|
||||
|
||||
|
||||
@@ -10,7 +12,10 @@ describe('ol.rendering.Map', function() {
|
||||
|
||||
let map;
|
||||
function createMap(renderer) {
|
||||
const vectorLayer = new VectorLayer({
|
||||
const MapConstructor = renderer === 'webgl' ? WebGLMap : Map;
|
||||
const LayerConstructor = renderer === 'webgl' ? WebGLVectorLayer : VectorLayer;
|
||||
|
||||
const vectorLayer = new LayerConstructor({
|
||||
source: new VectorSource({
|
||||
features: [new Feature({
|
||||
geometry: new Point([0, 0])
|
||||
@@ -18,10 +23,9 @@ describe('ol.rendering.Map', function() {
|
||||
})
|
||||
});
|
||||
|
||||
map = new Map({
|
||||
map = new MapConstructor({
|
||||
pixelRatio: 1,
|
||||
target: createMapDiv(50, 50),
|
||||
renderer: renderer,
|
||||
layers: [vectorLayer],
|
||||
view: new View({
|
||||
projection: 'EPSG:4326',
|
||||
|
||||
@@ -27,11 +27,10 @@ where('Uint8ClampedArray').describe('ol.rendering.source.Raster', function() {
|
||||
}
|
||||
|
||||
let map;
|
||||
function createMap(renderer, pixelRatio) {
|
||||
function createMap(pixelRatio) {
|
||||
map = new Map({
|
||||
target: createMapDiv(200, 200),
|
||||
pixelRatio: pixelRatio,
|
||||
renderer: renderer,
|
||||
view: new View({
|
||||
center: [0, 0],
|
||||
zoom: 0
|
||||
@@ -48,7 +47,7 @@ where('Uint8ClampedArray').describe('ol.rendering.source.Raster', function() {
|
||||
|
||||
describe('raster source rendering', function() {
|
||||
it('renders the result of an operation', function(done) {
|
||||
createMap('canvas', 1);
|
||||
createMap(1);
|
||||
|
||||
const source = new XYZ({
|
||||
url: 'rendering/ol/data/tiles/osm/{z}/{x}/{y}.png',
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import WebGLMap from '../../../../src/ol/WebGLMap.js';
|
||||
import Map from '../../../../src/ol/Map.js';
|
||||
import View from '../../../../src/ol/View.js';
|
||||
import TileLayer from '../../../../src/ol/layer/Tile.js';
|
||||
import WebGLTileLayer from '../../../../src/ol/layer/WebGLTile.js';
|
||||
import TileWMS from '../../../../src/ol/source/TileWMS.js';
|
||||
|
||||
describe('ol.rendering.source.TileWMS', function() {
|
||||
@@ -25,10 +27,11 @@ describe('ol.rendering.source.TileWMS', function() {
|
||||
|
||||
let map;
|
||||
function createMap(renderer, pixelRatio) {
|
||||
map = new Map({
|
||||
const MapConstructor = renderer === 'webgl' ? WebGLMap : Map;
|
||||
|
||||
map = new MapConstructor({
|
||||
target: createMapDiv(200, 200),
|
||||
pixelRatio: pixelRatio,
|
||||
renderer: renderer,
|
||||
view: new View({
|
||||
center: [0, 0],
|
||||
zoom: 5
|
||||
@@ -74,7 +77,7 @@ describe('ol.rendering.source.TileWMS', function() {
|
||||
tilesLoaded(source, function() {
|
||||
expectResemble(map, 'rendering/ol/source/expected/0_1.webgl.png', IMAGE_TOLERANCE, done);
|
||||
});
|
||||
map.addLayer(new TileLayer({
|
||||
map.addLayer(new WebGLTileLayer({
|
||||
source: source
|
||||
}));
|
||||
});
|
||||
@@ -99,7 +102,7 @@ describe('ol.rendering.source.TileWMS', function() {
|
||||
tilesLoaded(source, function() {
|
||||
expectResemble(map, 'rendering/ol/source/expected/0_2.webgl.png', IMAGE_TOLERANCE, done);
|
||||
});
|
||||
map.addLayer(new TileLayer({
|
||||
map.addLayer(new WebGLTileLayer({
|
||||
source: source
|
||||
}));
|
||||
});
|
||||
@@ -125,7 +128,7 @@ describe('ol.rendering.source.TileWMS', function() {
|
||||
tilesLoaded(source, function() {
|
||||
expectResemble(map, 'rendering/ol/source/expected/20_1.webgl.png', IMAGE_TOLERANCE, done);
|
||||
});
|
||||
map.addLayer(new TileLayer({
|
||||
map.addLayer(new WebGLTileLayer({
|
||||
source: source
|
||||
}));
|
||||
});
|
||||
@@ -150,7 +153,7 @@ describe('ol.rendering.source.TileWMS', function() {
|
||||
tilesLoaded(source, function() {
|
||||
expectResemble(map, 'rendering/ol/source/expected/20_2.webgl.png', IMAGE_TOLERANCE, done);
|
||||
});
|
||||
map.addLayer(new TileLayer({
|
||||
map.addLayer(new WebGLTileLayer({
|
||||
source: source
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -2,8 +2,10 @@ import Feature from '../../../../src/ol/Feature.js';
|
||||
import Point from '../../../../src/ol/geom/Point.js';
|
||||
import MultiPoint from '../../../../src/ol/geom/MultiPoint.js';
|
||||
import Map from '../../../../src/ol/Map.js';
|
||||
import WebGLMap from '../../../../src/ol/WebGLMap.js';
|
||||
import View from '../../../../src/ol/View.js';
|
||||
import VectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import WebGLVectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import VectorSource from '../../../../src/ol/source/Vector.js';
|
||||
import CircleStyle from '../../../../src/ol/style/Circle.js';
|
||||
import Fill from '../../../../src/ol/style/Fill.js';
|
||||
@@ -16,15 +18,17 @@ describe('ol.rendering.style.Circle', function() {
|
||||
let map, vectorSource;
|
||||
|
||||
function createMap(renderer) {
|
||||
const MapConstructor = renderer === 'webgl' ? WebGLMap : Map;
|
||||
const LayerConstructor = renderer === 'webgl' ? WebGLVectorLayer : VectorLayer;
|
||||
|
||||
vectorSource = new VectorSource();
|
||||
const vectorLayer = new VectorLayer({
|
||||
const vectorLayer = new LayerConstructor({
|
||||
source: vectorSource
|
||||
});
|
||||
|
||||
map = new Map({
|
||||
map = new MapConstructor({
|
||||
pixelRatio: 1,
|
||||
target: createMapDiv(50, 50),
|
||||
renderer: renderer,
|
||||
layers: [vectorLayer],
|
||||
view: new View({
|
||||
projection: 'EPSG:4326',
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import Feature from '../../../../src/ol/Feature.js';
|
||||
import Point from '../../../../src/ol/geom/Point.js';
|
||||
import Map from '../../../../src/ol/Map.js';
|
||||
import WebGLMap from '../../../../src/ol/WebGLMap.js';
|
||||
import View from '../../../../src/ol/View.js';
|
||||
import VectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import WebGLVectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import VectorSource from '../../../../src/ol/source/Vector.js';
|
||||
import Icon from '../../../../src/ol/style/Icon.js';
|
||||
import Style from '../../../../src/ol/style/Style.js';
|
||||
@@ -22,15 +24,17 @@ describe('ol.rendering.style.Icon', function() {
|
||||
};
|
||||
|
||||
function createMap(renderer, width, height) {
|
||||
const MapConstructor = renderer === 'webgl' ? WebGLMap : Map;
|
||||
const LayerConstructor = renderer === 'webgl' ? WebGLVectorLayer : VectorLayer;
|
||||
|
||||
vectorSource = new VectorSource();
|
||||
const vectorLayer = new VectorLayer({
|
||||
const vectorLayer = new LayerConstructor({
|
||||
source: vectorSource
|
||||
});
|
||||
|
||||
map = new Map({
|
||||
map = new MapConstructor({
|
||||
pixelRatio: 1,
|
||||
target: createMapDiv(width ? width : 50, height ? height : 50),
|
||||
renderer: renderer,
|
||||
layers: [vectorLayer],
|
||||
view: new View({
|
||||
projection: 'EPSG:4326',
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import Feature from '../../../../src/ol/Feature.js';
|
||||
import LineString from '../../../../src/ol/geom/LineString.js';
|
||||
import Map from '../../../../src/ol/Map.js';
|
||||
import WebGLMap from '../../../../src/ol/WebGLMap.js';
|
||||
import View from '../../../../src/ol/View.js';
|
||||
import VectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import WebGLVectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import VectorSource from '../../../../src/ol/source/Vector.js';
|
||||
import Style from '../../../../src/ol/style/Style.js';
|
||||
import Stroke from '../../../../src/ol/style/Stroke.js';
|
||||
@@ -13,15 +15,17 @@ describe('ol.rendering.style.LineString', function() {
|
||||
let map, vectorSource;
|
||||
|
||||
function createMap(renderer, opt_pixelRatio) {
|
||||
const MapConstructor = renderer === 'webgl' ? WebGLMap : Map;
|
||||
const LayerConstructor = renderer === 'webgl' ? WebGLVectorLayer : VectorLayer;
|
||||
|
||||
vectorSource = new VectorSource();
|
||||
const vectorLayer = new VectorLayer({
|
||||
const vectorLayer = new LayerConstructor({
|
||||
source: vectorSource
|
||||
});
|
||||
|
||||
map = new Map({
|
||||
map = new MapConstructor({
|
||||
pixelRatio: opt_pixelRatio || 1,
|
||||
target: createMapDiv(50, 50),
|
||||
renderer: renderer,
|
||||
layers: [vectorLayer],
|
||||
view: new View({
|
||||
projection: 'EPSG:4326',
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import Feature from '../../../../src/ol/Feature.js';
|
||||
import Polygon from '../../../../src/ol/geom/Polygon.js';
|
||||
import Map from '../../../../src/ol/Map.js';
|
||||
import WebGLMap from '../../../../src/ol/WebGLMap.js';
|
||||
import View from '../../../../src/ol/View.js';
|
||||
import VectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import WebGLVectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import VectorSource from '../../../../src/ol/source/Vector.js';
|
||||
import Fill from '../../../../src/ol/style/Fill.js';
|
||||
import Style from '../../../../src/ol/style/Style.js';
|
||||
@@ -14,17 +16,19 @@ describe('ol.rendering.style.Polygon', function() {
|
||||
let map, vectorSource;
|
||||
|
||||
function createMap(renderer, opt_size) {
|
||||
const MapConstructor = renderer === 'webgl' ? WebGLMap : Map;
|
||||
const LayerConstructor = renderer === 'webgl' ? WebGLVectorLayer : VectorLayer;
|
||||
|
||||
const size = opt_size || 50;
|
||||
|
||||
vectorSource = new VectorSource();
|
||||
const vectorLayer = new VectorLayer({
|
||||
const vectorLayer = new LayerConstructor({
|
||||
source: vectorSource
|
||||
});
|
||||
|
||||
map = new Map({
|
||||
map = new MapConstructor({
|
||||
pixelRatio: 1,
|
||||
target: createMapDiv(size, size),
|
||||
renderer: renderer,
|
||||
layers: [vectorLayer],
|
||||
view: new View({
|
||||
projection: 'EPSG:4326',
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import Feature from '../../../../src/ol/Feature.js';
|
||||
import Point from '../../../../src/ol/geom/Point.js';
|
||||
import Map from '../../../../src/ol/Map.js';
|
||||
import WebGLMap from '../../../../src/ol/WebGLMap.js';
|
||||
import View from '../../../../src/ol/View.js';
|
||||
import VectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import WebGLVectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import VectorSource from '../../../../src/ol/source/Vector.js';
|
||||
import Fill from '../../../../src/ol/style/Fill.js';
|
||||
import RegularShape from '../../../../src/ol/style/RegularShape.js';
|
||||
@@ -15,15 +17,17 @@ describe('ol.rendering.style.RegularShape', function() {
|
||||
let map, vectorSource;
|
||||
|
||||
function createMap(renderer) {
|
||||
const MapConstructor = renderer === 'webgl' ? WebGLMap : Map;
|
||||
const LayerConstructor = renderer === 'webgl' ? WebGLVectorLayer : VectorLayer;
|
||||
|
||||
vectorSource = new VectorSource();
|
||||
const vectorLayer = new VectorLayer({
|
||||
const vectorLayer = new LayerConstructor({
|
||||
source: vectorSource
|
||||
});
|
||||
|
||||
map = new Map({
|
||||
map = new MapConstructor({
|
||||
pixelRatio: 1,
|
||||
target: createMapDiv(50, 50),
|
||||
renderer: renderer,
|
||||
layers: [vectorLayer],
|
||||
view: new View({
|
||||
projection: 'EPSG:4326',
|
||||
|
||||
@@ -5,8 +5,10 @@ import MultiPolygon from '../../../../src/ol/geom/MultiPolygon.js';
|
||||
import Point from '../../../../src/ol/geom/Point.js';
|
||||
import Polygon from '../../../../src/ol/geom/Polygon.js';
|
||||
import Map from '../../../../src/ol/Map.js';
|
||||
import WebGLMap from '../../../../src/ol/WebGLMap.js';
|
||||
import View from '../../../../src/ol/View.js';
|
||||
import VectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import WebGLVectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import VectorSource from '../../../../src/ol/source/Vector.js';
|
||||
import Text from '../../../../src/ol/style/Text.js';
|
||||
import Fill from '../../../../src/ol/style/Fill.js';
|
||||
@@ -18,16 +20,18 @@ describe('ol.rendering.style.Text', function() {
|
||||
let map, vectorSource;
|
||||
|
||||
function createMap(renderer, opt_pixelRatio) {
|
||||
const MapConstructor = renderer === 'webgl' ? WebGLMap : Map;
|
||||
const LayerConstructor = renderer === 'webgl' ? WebGLVectorLayer : VectorLayer;
|
||||
|
||||
const pixelRatio = opt_pixelRatio || 1;
|
||||
vectorSource = new VectorSource();
|
||||
const vectorLayer = new VectorLayer({
|
||||
const vectorLayer = new LayerConstructor({
|
||||
source: vectorSource
|
||||
});
|
||||
|
||||
map = new Map({
|
||||
map = new MapConstructor({
|
||||
pixelRatio: pixelRatio,
|
||||
target: createMapDiv(200 / pixelRatio, 200 / pixelRatio),
|
||||
renderer: renderer,
|
||||
layers: [vectorLayer],
|
||||
view: new View({
|
||||
projection: 'EPSG:4326',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {createCanvasContext2D, outerWidth, outerHeight} from '../../../../src/ol/dom.js';
|
||||
import {createCanvasContext2D, outerWidth, outerHeight, replaceChildren} from '../../../../src/ol/dom.js';
|
||||
|
||||
describe('ol.dom', function() {
|
||||
|
||||
@@ -344,4 +344,164 @@ describe('ol.dom', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('replaceChildren()', function() {
|
||||
|
||||
function assertChildrenMatch(parent, children) {
|
||||
const actual = parent.childNodes;
|
||||
expect(actual).to.have.length(children.length);
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
expect(actual[i]).to.be(children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
it('adds new children to an empty parent', function() {
|
||||
const parent = document.createElement('div');
|
||||
const children = [
|
||||
document.createElement('a'),
|
||||
document.createElement('b'),
|
||||
document.createElement('c')
|
||||
];
|
||||
|
||||
replaceChildren(parent, children);
|
||||
assertChildrenMatch(parent, children);
|
||||
});
|
||||
|
||||
it('removes children', function() {
|
||||
const parent = document.createElement('div');
|
||||
const existingChildren = [
|
||||
document.createElement('a'),
|
||||
document.createElement('b'),
|
||||
document.createElement('c')
|
||||
];
|
||||
existingChildren.forEach(function(child) {
|
||||
parent.appendChild(child);
|
||||
});
|
||||
|
||||
replaceChildren(parent, []);
|
||||
expect(parent.childNodes).to.have.length(0);
|
||||
});
|
||||
|
||||
it('swaps children', function() {
|
||||
const parent = document.createElement('div');
|
||||
const existingChildren = [
|
||||
document.createElement('a'),
|
||||
document.createElement('b'),
|
||||
document.createElement('c')
|
||||
];
|
||||
existingChildren.forEach(function(child) {
|
||||
parent.appendChild(child);
|
||||
});
|
||||
|
||||
const newChildren = [
|
||||
document.createElement('d'),
|
||||
document.createElement('e'),
|
||||
document.createElement('f')
|
||||
];
|
||||
|
||||
replaceChildren(parent, newChildren);
|
||||
assertChildrenMatch(parent, newChildren);
|
||||
});
|
||||
|
||||
it('appends children', function() {
|
||||
const parent = document.createElement('div');
|
||||
const existingChildren = [
|
||||
document.createElement('a'),
|
||||
document.createElement('b'),
|
||||
document.createElement('c')
|
||||
];
|
||||
existingChildren.forEach(function(child) {
|
||||
parent.appendChild(child);
|
||||
});
|
||||
|
||||
const newChildren = [
|
||||
document.createElement('d'),
|
||||
document.createElement('e'),
|
||||
document.createElement('f')
|
||||
];
|
||||
|
||||
const allChildren = existingChildren.concat(newChildren);
|
||||
|
||||
replaceChildren(parent, allChildren);
|
||||
assertChildrenMatch(parent, allChildren);
|
||||
});
|
||||
|
||||
it('prunes children', function() {
|
||||
const parent = document.createElement('div');
|
||||
const existingChildren = [
|
||||
document.createElement('a'),
|
||||
document.createElement('b'),
|
||||
document.createElement('c'),
|
||||
document.createElement('d'),
|
||||
document.createElement('e')
|
||||
];
|
||||
existingChildren.forEach(function(child) {
|
||||
parent.appendChild(child);
|
||||
});
|
||||
|
||||
const desiredChildren = [
|
||||
existingChildren[1],
|
||||
existingChildren[3]
|
||||
];
|
||||
|
||||
replaceChildren(parent, desiredChildren);
|
||||
assertChildrenMatch(parent, desiredChildren);
|
||||
});
|
||||
|
||||
it('reorders children', function() {
|
||||
const parent = document.createElement('div');
|
||||
const existingChildren = [
|
||||
document.createElement('a'),
|
||||
document.createElement('b'),
|
||||
document.createElement('c'),
|
||||
document.createElement('d'),
|
||||
document.createElement('e')
|
||||
];
|
||||
existingChildren.forEach(function(child) {
|
||||
parent.appendChild(child);
|
||||
});
|
||||
|
||||
const desiredChildren = [
|
||||
existingChildren[1],
|
||||
existingChildren[3],
|
||||
existingChildren[0],
|
||||
existingChildren[4],
|
||||
existingChildren[2]
|
||||
];
|
||||
|
||||
replaceChildren(parent, desiredChildren);
|
||||
assertChildrenMatch(parent, desiredChildren);
|
||||
});
|
||||
|
||||
it('reorders, prunes, and appends children', function() {
|
||||
const parent = document.createElement('div');
|
||||
const existingChildren = [
|
||||
document.createElement('a'),
|
||||
document.createElement('b'),
|
||||
document.createElement('c'),
|
||||
document.createElement('d'),
|
||||
document.createElement('e')
|
||||
];
|
||||
existingChildren.forEach(function(child) {
|
||||
parent.appendChild(child);
|
||||
});
|
||||
|
||||
const desiredChildren = [
|
||||
document.createElement('f'),
|
||||
existingChildren[3],
|
||||
document.createElement('g'),
|
||||
existingChildren[0],
|
||||
existingChildren[2]
|
||||
];
|
||||
|
||||
const clone = desiredChildren.slice();
|
||||
|
||||
replaceChildren(parent, desiredChildren);
|
||||
assertChildrenMatch(parent, desiredChildren);
|
||||
|
||||
// confirm we haven't modified the input
|
||||
expect(desiredChildren).to.eql(clone);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,45 +1,16 @@
|
||||
import Map from '../../../../../src/ol/Map.js';
|
||||
import View from '../../../../../src/ol/View.js';
|
||||
import ImageLayer from '../../../../../src/ol/layer/Image.js';
|
||||
import VectorLayer from '../../../../../src/ol/layer/Vector.js';
|
||||
import VectorImageLayer from '../../../../../src/ol/layer/VectorImage.js';
|
||||
import Feature from '../../../../../src/ol/Feature.js';
|
||||
import Point from '../../../../../src/ol/geom/Point.js';
|
||||
import Projection from '../../../../../src/ol/proj/Projection.js';
|
||||
import Static from '../../../../../src/ol/source/ImageStatic.js';
|
||||
import VectorSource from '../../../../../src/ol/source/Vector.js';
|
||||
import CanvasImageLayerRenderer from '../../../../../src/ol/renderer/canvas/ImageLayer.js';
|
||||
import CanvasVectorLayerRenderer from '../../../../../src/ol/renderer/canvas/VectorLayer.js';
|
||||
|
||||
|
||||
describe('ol.renderer.canvas.ImageLayer', function() {
|
||||
|
||||
describe('#dispose()', function() {
|
||||
let layer, imageRenderer, vectorRenderer;
|
||||
|
||||
beforeEach(function() {
|
||||
layer = new VectorLayer({
|
||||
renderMode: 'image',
|
||||
source: new VectorSource()
|
||||
});
|
||||
imageRenderer = new CanvasImageLayerRenderer(layer);
|
||||
vectorRenderer = new CanvasVectorLayerRenderer(layer);
|
||||
imageRenderer.vectorRenderer_ = vectorRenderer;
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
imageRenderer.dispose();
|
||||
vectorRenderer.dispose();
|
||||
layer.dispose();
|
||||
});
|
||||
|
||||
it('cleans up CanvasVectorRenderer', function() {
|
||||
const vectorRenderer = imageRenderer.vectorRenderer_;
|
||||
const spy = sinon.spy(vectorRenderer, 'dispose');
|
||||
imageRenderer.dispose();
|
||||
expect(spy.called).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#forEachLayerAtCoordinate', function() {
|
||||
|
||||
let map, target, source;
|
||||
@@ -99,8 +70,7 @@ describe('ol.renderer.canvas.ImageLayer', function() {
|
||||
let map, div, layer;
|
||||
|
||||
beforeEach(function() {
|
||||
layer = new VectorLayer({
|
||||
renderMode: 'image',
|
||||
layer = new VectorImageLayer({
|
||||
source: new VectorSource({
|
||||
features: [new Feature(new Point([0, 0]))]
|
||||
})
|
||||
|
||||
21
test/spec/ol/renderer/canvas/vectorimage.test.js
Normal file
21
test/spec/ol/renderer/canvas/vectorimage.test.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import VectorImageLayer from '../../../../../src/ol/layer/VectorImage.js';
|
||||
import VectorSource from '../../../../../src/ol/source/Vector.js';
|
||||
import CanvasVectorImageLayerRenderer from '../../../../../src/ol/renderer/canvas/VectorImageLayer.js';
|
||||
|
||||
describe('ol/renderer/canvas/VectorImageLayer', function() {
|
||||
|
||||
describe('#dispose()', function() {
|
||||
|
||||
it('cleans up CanvasVectorRenderer', function() {
|
||||
const layer = new VectorImageLayer({
|
||||
source: new VectorSource()
|
||||
});
|
||||
const renderer = new CanvasVectorImageLayerRenderer(layer);
|
||||
const spy = sinon.spy(renderer.vectorRenderer_, 'dispose');
|
||||
renderer.dispose();
|
||||
expect(spy.called).to.be(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -2,7 +2,7 @@ import Map from '../../../../src/ol/Map.js';
|
||||
import TileState from '../../../../src/ol/TileState.js';
|
||||
import View from '../../../../src/ol/View.js';
|
||||
import ImageLayer from '../../../../src/ol/layer/Image.js';
|
||||
import VectorLayer from '../../../../src/ol/layer/Vector.js';
|
||||
import VectorImageLayer from '../../../../src/ol/layer/VectorImage.js';
|
||||
import Projection from '../../../../src/ol/proj/Projection.js';
|
||||
import Static from '../../../../src/ol/source/ImageStatic.js';
|
||||
import RasterSource from '../../../../src/ol/source/Raster.js';
|
||||
@@ -47,8 +47,7 @@ where('Uint8ClampedArray').describe('ol.source.Raster', function() {
|
||||
imageExtent: extent
|
||||
});
|
||||
|
||||
blueSource = new VectorLayer({
|
||||
renderMode: 'image',
|
||||
blueSource = new VectorImageLayer({
|
||||
source: new VectorSource({
|
||||
features: [new Feature(new Point([0, 0]))]
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user