diff --git a/changelog/upgrade-notes.md b/changelog/upgrade-notes.md index 0863018dba..3e9a5cb41b 100644 --- a/changelog/upgrade-notes.md +++ b/changelog/upgrade-notes.md @@ -22,6 +22,10 @@ Inserting with `setAt` or `insertAt` beyond the current length used to create a The control will now by default keep displaying the last mouse position when the mouse leaves the viewport. With `placeholder: ' '` you can keep the old behaviour. The `placeholder` option no longer accepts `false` as a valid value, instead simply omit the option. The `undefinedHTML` option has been removed. You should use `placeholder` instead. +#### ol/PluggableMap + +The `PluggableMap` class has been removed. If you want to create a custom map class, extend the `Map` class instead. + ### 6.15.0 #### Deprecated `tilePixelRatio` option for data tile sources. diff --git a/src/ol/Map.js b/src/ol/Map.js index e051162613..ac1b67c97e 100644 --- a/src/ol/Map.js +++ b/src/ol/Map.js @@ -1,10 +1,184 @@ /** * @module ol/Map */ +import BaseObject from './Object.js'; +import Collection from './Collection.js'; +import CollectionEventType from './CollectionEventType.js'; import CompositeMapRenderer from './renderer/Composite.js'; -import PluggableMap from './PluggableMap.js'; +import EventType from './events/EventType.js'; +import Layer from './layer/Layer.js'; +import LayerGroup, {GroupEvent} from './layer/Group.js'; +import MapBrowserEvent from './MapBrowserEvent.js'; +import MapBrowserEventHandler from './MapBrowserEventHandler.js'; +import MapBrowserEventType from './MapBrowserEventType.js'; +import MapEvent from './MapEvent.js'; +import MapEventType from './MapEventType.js'; +import MapProperty from './MapProperty.js'; +import ObjectEventType from './ObjectEventType.js'; +import PointerEventType from './pointer/EventType.js'; +import RenderEventType from './render/EventType.js'; +import TileQueue, {getTilePriority} from './TileQueue.js'; +import View from './View.js'; +import ViewHint from './ViewHint.js'; +import {DEVICE_PIXEL_RATIO, PASSIVE_EVENT_LISTENERS} from './has.js'; +import {TRUE} from './functions.js'; +import { + apply as applyTransform, + create as createTransform, +} from './transform.js'; +import {assert} from './asserts.js'; +import { + clone, + createOrUpdateEmpty, + equals, + getForViewAndSize, + isEmpty, +} from './extent.js'; import {defaults as defaultControls} from './control.js'; import {defaults as defaultInteractions} from './interaction.js'; +import {fromUserCoordinate, toUserCoordinate} from './proj.js'; +import {getUid} from './util.js'; +import {hasArea} from './size.js'; +import {listen, unlistenByKey} from './events.js'; +import {removeNode} from './dom.js'; + +/** + * State of the current frame. Only `pixelRatio`, `time` and `viewState` should + * be used in applications. + * @typedef {Object} FrameState + * @property {number} pixelRatio The pixel ratio of the frame. + * @property {number} time The time when rendering of the frame was requested. + * @property {import("./View.js").State} viewState The state of the current view. + * @property {boolean} animate Animate. + * @property {import("./transform.js").Transform} coordinateToPixelTransform CoordinateToPixelTransform. + * @property {import("rbush").default} declutterTree DeclutterTree. + * @property {null|import("./extent.js").Extent} extent Extent. + * @property {import("./extent.js").Extent} [nextExtent] Next extent during an animation series. + * @property {number} index Index. + * @property {Array} layerStatesArray LayerStatesArray. + * @property {number} layerIndex LayerIndex. + * @property {import("./transform.js").Transform} pixelToCoordinateTransform PixelToCoordinateTransform. + * @property {Array} postRenderFunctions PostRenderFunctions. + * @property {import("./size.js").Size} size Size. + * @property {TileQueue} tileQueue TileQueue. + * @property {!Object>} usedTiles UsedTiles. + * @property {Array} viewHints ViewHints. + * @property {!Object>} wantedTiles WantedTiles. + * @property {string} mapId The id of the map. + * @property {Object} renderTargets Identifiers of previously rendered elements. + */ + +/** + * @typedef {function(Map, ?FrameState): any} PostRenderFunction + */ + +/** + * @typedef {Object} AtPixelOptions + * @property {undefined|function(import("./layer/Layer.js").default): boolean} [layerFilter] Layer filter + * function. The filter function will receive one argument, the + * {@link module:ol/layer/Layer~Layer layer-candidate} and it should return a boolean value. + * Only layers which are visible and for which this function returns `true` + * will be tested for features. By default, all visible layers will be tested. + * @property {number} [hitTolerance=0] Hit-detection tolerance in css pixels. Pixels + * inside the radius around the given position will be checked for features. + * @property {boolean} [checkWrapped=true] Check-Wrapped Will check for for wrapped geometries inside the range of + * +/- 1 world width. Works only if a projection is used that can be wrapped. + */ + +/** + * @typedef {Object} MapOptionsInternal + * @property {Collection} [controls] Controls. + * @property {Collection} [interactions] Interactions. + * @property {HTMLElement|Document} keyboardEventTarget KeyboardEventTarget. + * @property {Collection} overlays Overlays. + * @property {Object} values Values. + */ + +/** + * @typedef {import("./ObjectEventType").Types|'change:layergroup'|'change:size'|'change:target'|'change:view'} MapObjectEventTypes + */ + +/*** + * @template Return + * @typedef {import("./Observable").OnSignature & + * import("./Observable").OnSignature & + * import("./Observable").OnSignature & + * import("./Observable").OnSignature & + * import("./Observable").OnSignature & + * import("./Observable").CombinedOnSignature} MapEventHandler + */ + +/** + * Object literal with config options for the map. + * @typedef {Object} MapOptions + * @property {Collection|Array} [controls] + * Controls initially added to the map. If not specified, + * {@link module:ol/control.defaults} is used. + * @property {number} [pixelRatio=window.devicePixelRatio] The ratio between + * physical pixels and device-independent pixels (dips) on the device. + * @property {Collection|Array} [interactions] + * Interactions that are initially added to the map. If not specified, + * {@link module:ol/interaction.defaults} is used. + * @property {HTMLElement|Document|string} [keyboardEventTarget] The element to + * listen to keyboard events on. This determines when the `KeyboardPan` and + * `KeyboardZoom` interactions trigger. For example, if this option is set to + * `document` the keyboard interactions will always trigger. If this option is + * not specified, the element the library listens to keyboard events on is the + * map target (i.e. the user-provided div for the map). If this is not + * `document`, the target element needs to be focused for key events to be + * emitted, requiring that the target element has a `tabindex` attribute. + * @property {Array|Collection|LayerGroup} [layers] + * Layers. If this is not defined, a map with no layers will be rendered. Note + * that layers are rendered in the order supplied, so if you want, for example, + * a vector layer to appear on top of a tile layer, it must come after the tile + * layer. + * @property {number} [maxTilesLoading=16] Maximum number tiles to load + * simultaneously. + * @property {number} [moveTolerance=1] The minimum distance in pixels the + * cursor must move to be detected as a map move event instead of a click. + * Increasing this value can make it easier to click on the map. + * @property {Collection|Array} [overlays] + * Overlays initially added to the map. By default, no overlays are added. + * @property {HTMLElement|string} [target] The container for the map, either the + * element itself or the `id` of the element. If not specified at construction + * time, {@link module:ol/Map~Map#setTarget} must be called for the map to be + * rendered. If passed by element, the container can be in a secondary document. + * @property {View|Promise} [view] The map's view. No layer sources will be + * fetched unless this is specified at construction time or through + * {@link module:ol/Map~Map#setView}. + */ + +/** + * @param {import("./layer/Base.js").default} layer Layer. + */ +function removeLayerMapProperty(layer) { + if (layer instanceof Layer) { + layer.setMapInternal(null); + return; + } + if (layer instanceof LayerGroup) { + layer.getLayers().forEach(removeLayerMapProperty); + } +} + +/** + * @param {import("./layer/Base.js").default} layer Layer. + * @param {Map} map Map. + */ +function setLayerMapProperty(layer, map) { + if (layer instanceof Layer) { + layer.setMapInternal(map); + return; + } + if (layer instanceof LayerGroup) { + const layers = layer.getLayers().getArray(); + for (let i = 0, ii = layers.length; i < ii; ++i) { + setLayerMapProperty(layers[i], map); + } + } +} /** * @classdesc @@ -51,29 +225,1595 @@ import {defaults as defaultInteractions} from './interaction.js'; * 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 import("./render/Event.js").default#precompose + * @fires import("./render/Event.js").default#postcompose + * @fires import("./render/Event.js").default#rendercomplete * @api */ -class Map extends PluggableMap { +class Map extends BaseObject { /** - * @param {import("./PluggableMap.js").MapOptions} options Map options. + * @param {MapOptions} [opt_options] Map options. */ - constructor(options) { - options = Object.assign({}, options); - if (!options.controls) { - options.controls = defaultControls(); - } - if (!options.interactions) { - options.interactions = defaultInteractions({ + constructor(opt_options) { + super(); + + const options = opt_options || {}; + + /*** + * @type {MapEventHandler} + */ + this.on; + + /*** + * @type {MapEventHandler} + */ + this.once; + + /*** + * @type {MapEventHandler} + */ + this.un; + + const optionsInternal = createOptionsInternal(options); + + /** + * @private + * @type {boolean|undefined} + */ + this.renderComplete_; + + /** + * @private + * @type {boolean} + */ + this.loaded_ = true; + + /** @private */ + this.boundHandleBrowserEvent_ = this.handleBrowserEvent.bind(this); + + /** + * @type {number} + * @private + */ + this.maxTilesLoading_ = + options.maxTilesLoading !== undefined ? options.maxTilesLoading : 16; + + /** + * @private + * @type {number} + */ + this.pixelRatio_ = + options.pixelRatio !== undefined + ? options.pixelRatio + : DEVICE_PIXEL_RATIO; + + /** + * @private + * @type {*} + */ + this.postRenderTimeoutHandle_; + + /** + * @private + * @type {number|undefined} + */ + this.animationDelayKey_; + + /** + * @private + */ + this.animationDelay_ = this.animationDelay_.bind(this); + + /** + * @private + * @type {import("./transform.js").Transform} + */ + this.coordinateToPixelTransform_ = createTransform(); + + /** + * @private + * @type {import("./transform.js").Transform} + */ + this.pixelToCoordinateTransform_ = createTransform(); + + /** + * @private + * @type {number} + */ + this.frameIndex_ = 0; + + /** + * @private + * @type {?FrameState} + */ + this.frameState_ = null; + + /** + * The extent at the previous 'moveend' event. + * @private + * @type {import("./extent.js").Extent} + */ + this.previousExtent_ = null; + + /** + * @private + * @type {?import("./events.js").EventsKey} + */ + this.viewPropertyListenerKey_ = null; + + /** + * @private + * @type {?import("./events.js").EventsKey} + */ + this.viewChangeListenerKey_ = null; + + /** + * @private + * @type {?Array} + */ + this.layerGroupPropertyListenerKeys_ = null; + + /** + * @private + * @type {!HTMLElement} + */ + this.viewport_ = document.createElement('div'); + this.viewport_.className = + 'ol-viewport' + ('ontouchstart' in window ? ' ol-touch' : ''); + this.viewport_.style.position = 'relative'; + this.viewport_.style.overflow = 'hidden'; + this.viewport_.style.width = '100%'; + this.viewport_.style.height = '100%'; + + /** + * @private + * @type {!HTMLElement} + */ + this.overlayContainer_ = document.createElement('div'); + this.overlayContainer_.style.position = 'absolute'; + this.overlayContainer_.style.zIndex = '0'; + this.overlayContainer_.style.width = '100%'; + this.overlayContainer_.style.height = '100%'; + this.overlayContainer_.style.pointerEvents = 'none'; + this.overlayContainer_.className = 'ol-overlaycontainer'; + this.viewport_.appendChild(this.overlayContainer_); + + /** + * @private + * @type {!HTMLElement} + */ + this.overlayContainerStopEvent_ = document.createElement('div'); + this.overlayContainerStopEvent_.style.position = 'absolute'; + this.overlayContainerStopEvent_.style.zIndex = '0'; + this.overlayContainerStopEvent_.style.width = '100%'; + this.overlayContainerStopEvent_.style.height = '100%'; + this.overlayContainerStopEvent_.style.pointerEvents = 'none'; + this.overlayContainerStopEvent_.className = 'ol-overlaycontainer-stopevent'; + this.viewport_.appendChild(this.overlayContainerStopEvent_); + + /** + * @private + * @type {MapBrowserEventHandler} + */ + this.mapBrowserEventHandler_ = null; + + /** + * @private + * @type {number} + */ + this.moveTolerance_ = options.moveTolerance; + + /** + * @private + * @type {HTMLElement|Document} + */ + this.keyboardEventTarget_ = optionsInternal.keyboardEventTarget; + + /** + * @private + * @type {?Array} + */ + this.targetChangeHandlerKeys_ = null; + + /** + * @type {Collection} + * @protected + */ + this.controls = optionsInternal.controls || defaultControls(); + + /** + * @type {Collection} + * @protected + */ + this.interactions = + optionsInternal.interactions || + defaultInteractions({ onFocusOnly: true, }); + + /** + * @type {Collection} + * @private + */ + this.overlays_ = optionsInternal.overlays; + + /** + * A lookup of overlays by id. + * @private + * @type {Object} + */ + this.overlayIdIndex_ = {}; + + /** + * @type {import("./renderer/Map.js").default|null} + * @private + */ + this.renderer_ = null; + + /** + * @private + * @type {!Array} + */ + this.postRenderFunctions_ = []; + + /** + * @private + * @type {TileQueue} + */ + this.tileQueue_ = new TileQueue( + this.getTilePriority.bind(this), + this.handleTileChange_.bind(this) + ); + + this.addChangeListener( + MapProperty.LAYERGROUP, + this.handleLayerGroupChanged_ + ); + this.addChangeListener(MapProperty.VIEW, this.handleViewChanged_); + this.addChangeListener(MapProperty.SIZE, this.handleSizeChanged_); + this.addChangeListener(MapProperty.TARGET, this.handleTargetChanged_); + + // setProperties will trigger the rendering of the map if the map + // is "defined" already. + this.setProperties(optionsInternal.values); + + const map = this; + if (options.view && !(options.view instanceof View)) { + options.view.then(function (viewOptions) { + map.setView(new View(viewOptions)); + }); } - super(options); + this.controls.addEventListener( + CollectionEventType.ADD, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent + */ + function (event) { + event.element.setMap(this); + }.bind(this) + ); + + this.controls.addEventListener( + CollectionEventType.REMOVE, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. + */ + function (event) { + event.element.setMap(null); + }.bind(this) + ); + + this.interactions.addEventListener( + CollectionEventType.ADD, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. + */ + function (event) { + event.element.setMap(this); + }.bind(this) + ); + + this.interactions.addEventListener( + CollectionEventType.REMOVE, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. + */ + function (event) { + event.element.setMap(null); + }.bind(this) + ); + + this.overlays_.addEventListener( + CollectionEventType.ADD, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. + */ + function (event) { + this.addOverlayInternal_(event.element); + }.bind(this) + ); + + this.overlays_.addEventListener( + CollectionEventType.REMOVE, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. + */ + function (event) { + const id = event.element.getId(); + if (id !== undefined) { + delete this.overlayIdIndex_[id.toString()]; + } + event.element.setMap(null); + }.bind(this) + ); + + this.controls.forEach( + /** + * @param {import("./control/Control.js").default} control Control. + * @this {Map} + */ + function (control) { + control.setMap(this); + }.bind(this) + ); + + this.interactions.forEach( + /** + * @param {import("./interaction/Interaction.js").default} interaction Interaction. + * @this {Map} + */ + function (interaction) { + interaction.setMap(this); + }.bind(this) + ); + + this.overlays_.forEach(this.addOverlayInternal_.bind(this)); } - createRenderer() { - return new CompositeMapRenderer(this); + /** + * Add the given control to the map. + * @param {import("./control/Control.js").default} control Control. + * @api + */ + addControl(control) { + this.getControls().push(control); + } + + /** + * Add the given interaction to the map. If you want to add an interaction + * at another point of the collection use `getInteractions()` and the methods + * available on {@link module:ol/Collection~Collection}. This can be used to + * stop the event propagation from the handleEvent function. The interactions + * get to handle the events in the reverse order of this collection. + * @param {import("./interaction/Interaction.js").default} interaction Interaction to add. + * @api + */ + addInteraction(interaction) { + this.getInteractions().push(interaction); + } + + /** + * Adds the given layer to the top of this map. If you want to add a layer + * elsewhere in the stack, use `getLayers()` and the methods available on + * {@link module:ol/Collection~Collection}. + * @param {import("./layer/Base.js").default} layer Layer. + * @api + */ + addLayer(layer) { + const layers = this.getLayerGroup().getLayers(); + layers.push(layer); + } + + /** + * @param {import("./layer/Group.js").GroupEvent} event The layer add event. + * @private + */ + handleLayerAdd_(event) { + setLayerMapProperty(event.layer, this); + } + + /** + * Add the given overlay to the map. + * @param {import("./Overlay.js").default} overlay Overlay. + * @api + */ + addOverlay(overlay) { + this.getOverlays().push(overlay); + } + + /** + * This deals with map's overlay collection changes. + * @param {import("./Overlay.js").default} overlay Overlay. + * @private + */ + addOverlayInternal_(overlay) { + const id = overlay.getId(); + if (id !== undefined) { + this.overlayIdIndex_[id.toString()] = overlay; + } + overlay.setMap(this); + } + + /** + * + * Clean up. + */ + disposeInternal() { + this.controls.clear(); + this.interactions.clear(); + this.overlays_.clear(); + this.setTarget(null); + super.disposeInternal(); + } + + /** + * Detect features that intersect a pixel on the viewport, and execute a + * callback with each intersecting feature. Layers included in the detection can + * be configured through the `layerFilter` option in `opt_options`. + * @param {import("./pixel.js").Pixel} pixel Pixel. + * @param {function(import("./Feature.js").FeatureLike, import("./layer/Layer.js").default, import("./geom/SimpleGeometry.js").default): T} callback Feature callback. The callback will be + * called with two arguments. The first argument is one + * {@link module:ol/Feature~Feature feature} or + * {@link module:ol/render/Feature~RenderFeature render feature} at the pixel, the second is + * the {@link module:ol/layer/Layer~Layer layer} of the feature and will be null for + * unmanaged layers. To stop detection, callback functions can return a + * truthy value. + * @param {AtPixelOptions} [opt_options] Optional options. + * @return {T|undefined} Callback result, i.e. the return value of last + * callback execution, or the first truthy callback return value. + * @template T + * @api + */ + forEachFeatureAtPixel(pixel, callback, opt_options) { + if (!this.frameState_ || !this.renderer_) { + return; + } + const coordinate = this.getCoordinateFromPixelInternal(pixel); + opt_options = opt_options !== undefined ? opt_options : {}; + const hitTolerance = + opt_options.hitTolerance !== undefined ? opt_options.hitTolerance : 0; + const layerFilter = + opt_options.layerFilter !== undefined ? opt_options.layerFilter : TRUE; + const checkWrapped = opt_options.checkWrapped !== false; + return this.renderer_.forEachFeatureAtCoordinate( + coordinate, + this.frameState_, + hitTolerance, + checkWrapped, + callback, + null, + layerFilter, + null + ); + } + + /** + * Get all features that intersect a pixel on the viewport. + * @param {import("./pixel.js").Pixel} pixel Pixel. + * @param {AtPixelOptions} [opt_options] Optional options. + * @return {Array} The detected features or + * an empty array if none were found. + * @api + */ + getFeaturesAtPixel(pixel, opt_options) { + const features = []; + this.forEachFeatureAtPixel( + pixel, + function (feature) { + features.push(feature); + }, + opt_options + ); + return features; + } + + /** + * Get all layers from all layer groups. + * @return {Array} Layers. + * @api + */ + getAllLayers() { + const layers = []; + function addLayersFrom(layerGroup) { + layerGroup.forEach(function (layer) { + if (layer instanceof LayerGroup) { + addLayersFrom(layer.getLayers()); + } else { + layers.push(layer); + } + }); + } + addLayersFrom(this.getLayers()); + return layers; + } + + /** + * Detect if features intersect a pixel on the viewport. Layers included in the + * detection can be configured through `opt_layerFilter`. + * @param {import("./pixel.js").Pixel} pixel Pixel. + * @param {AtPixelOptions} [opt_options] Optional options. + * @return {boolean} Is there a feature at the given pixel? + * @api + */ + hasFeatureAtPixel(pixel, opt_options) { + if (!this.frameState_ || !this.renderer_) { + return false; + } + const coordinate = this.getCoordinateFromPixelInternal(pixel); + opt_options = opt_options !== undefined ? opt_options : {}; + const layerFilter = + opt_options.layerFilter !== undefined ? opt_options.layerFilter : TRUE; + const hitTolerance = + opt_options.hitTolerance !== undefined ? opt_options.hitTolerance : 0; + const checkWrapped = opt_options.checkWrapped !== false; + return this.renderer_.hasFeatureAtCoordinate( + coordinate, + this.frameState_, + hitTolerance, + checkWrapped, + layerFilter, + null + ); + } + + /** + * Returns the coordinate in user projection for a browser event. + * @param {MouseEvent} event Event. + * @return {import("./coordinate.js").Coordinate} Coordinate. + * @api + */ + getEventCoordinate(event) { + return this.getCoordinateFromPixel(this.getEventPixel(event)); + } + + /** + * Returns the coordinate in view projection for a browser event. + * @param {MouseEvent} event Event. + * @return {import("./coordinate.js").Coordinate} Coordinate. + */ + getEventCoordinateInternal(event) { + return this.getCoordinateFromPixelInternal(this.getEventPixel(event)); + } + + /** + * Returns the map pixel position for a browser event relative to the viewport. + * @param {UIEvent} event Event. + * @return {import("./pixel.js").Pixel} Pixel. + * @api + */ + getEventPixel(event) { + const viewportPosition = this.viewport_.getBoundingClientRect(); + const eventPosition = + //FIXME Are we really calling this with a TouchEvent anywhere? + 'changedTouches' in event + ? /** @type {TouchEvent} */ (event).changedTouches[0] + : /** @type {MouseEvent} */ (event); + + return [ + eventPosition.clientX - viewportPosition.left, + eventPosition.clientY - viewportPosition.top, + ]; + } + + /** + * Get the target in which this map is rendered. + * Note that this returns what is entered as an option or in setTarget: + * if that was an element, it returns an element; if a string, it returns that. + * @return {HTMLElement|string|undefined} The Element or id of the Element that the + * map is rendered in. + * @observable + * @api + */ + getTarget() { + return /** @type {HTMLElement|string|undefined} */ ( + this.get(MapProperty.TARGET) + ); + } + + /** + * Get the DOM element into which this map is rendered. In contrast to + * `getTarget` this method always return an `Element`, or `null` if the + * map has no target. + * @return {HTMLElement} The element that the map is rendered in. + * @api + */ + getTargetElement() { + const target = this.getTarget(); + if (target !== undefined) { + return typeof target === 'string' + ? document.getElementById(target) + : target; + } else { + return null; + } + } + + /** + * Get the coordinate for a given pixel. This returns a coordinate in the + * user projection. + * @param {import("./pixel.js").Pixel} pixel Pixel position in the map viewport. + * @return {import("./coordinate.js").Coordinate} The coordinate for the pixel position. + * @api + */ + getCoordinateFromPixel(pixel) { + return toUserCoordinate( + this.getCoordinateFromPixelInternal(pixel), + this.getView().getProjection() + ); + } + + /** + * Get the coordinate for a given pixel. This returns a coordinate in the + * map view projection. + * @param {import("./pixel.js").Pixel} pixel Pixel position in the map viewport. + * @return {import("./coordinate.js").Coordinate} The coordinate for the pixel position. + */ + getCoordinateFromPixelInternal(pixel) { + const frameState = this.frameState_; + if (!frameState) { + return null; + } else { + return applyTransform( + frameState.pixelToCoordinateTransform, + pixel.slice() + ); + } + } + + /** + * Get the map controls. Modifying this collection changes the controls + * associated with the map. + * @return {Collection} Controls. + * @api + */ + getControls() { + return this.controls; + } + + /** + * Get the map overlays. Modifying this collection changes the overlays + * associated with the map. + * @return {Collection} Overlays. + * @api + */ + getOverlays() { + return this.overlays_; + } + + /** + * Get an overlay by its identifier (the value returned by overlay.getId()). + * Note that the index treats string and numeric identifiers as the same. So + * `map.getOverlayById(2)` will return an overlay with id `'2'` or `2`. + * @param {string|number} id Overlay identifier. + * @return {import("./Overlay.js").default} Overlay. + * @api + */ + getOverlayById(id) { + const overlay = this.overlayIdIndex_[id.toString()]; + return overlay !== undefined ? overlay : null; + } + + /** + * Get the map interactions. Modifying this collection changes the interactions + * associated with the map. + * + * Interactions are used for e.g. pan, zoom and rotate. + * @return {Collection} Interactions. + * @api + */ + getInteractions() { + return this.interactions; + } + + /** + * Get the layergroup associated with this map. + * @return {LayerGroup} A layer group containing the layers in this map. + * @observable + * @api + */ + getLayerGroup() { + return /** @type {LayerGroup} */ (this.get(MapProperty.LAYERGROUP)); + } + + /** + * Clear any existing layers and add layers to the map. + * @param {Array|Collection} layers The layers to be added to the map. + * @api + */ + setLayers(layers) { + const group = this.getLayerGroup(); + if (layers instanceof Collection) { + group.setLayers(layers); + return; + } + + const collection = group.getLayers(); + collection.clear(); + collection.extend(layers); + } + + /** + * Get the collection of layers associated with this map. + * @return {!Collection} Layers. + * @api + */ + getLayers() { + const layers = this.getLayerGroup().getLayers(); + return layers; + } + + /** + * @return {boolean} Layers have sources that are still loading. + */ + getLoadingOrNotReady() { + const layerStatesArray = this.getLayerGroup().getLayerStatesArray(); + for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) { + const state = layerStatesArray[i]; + if (!state.visible) { + continue; + } + const renderer = state.layer.getRenderer(); + if (renderer && !renderer.ready) { + return true; + } + const source = state.layer.getSource(); + if (source && source.loading) { + return true; + } + } + return false; + } + + /** + * Get the pixel for a coordinate. This takes a coordinate in the user + * projection and returns the corresponding pixel. + * @param {import("./coordinate.js").Coordinate} coordinate A map coordinate. + * @return {import("./pixel.js").Pixel} A pixel position in the map viewport. + * @api + */ + getPixelFromCoordinate(coordinate) { + const viewCoordinate = fromUserCoordinate( + coordinate, + this.getView().getProjection() + ); + return this.getPixelFromCoordinateInternal(viewCoordinate); + } + + /** + * Get the pixel for a coordinate. This takes a coordinate in the map view + * projection and returns the corresponding pixel. + * @param {import("./coordinate.js").Coordinate} coordinate A map coordinate. + * @return {import("./pixel.js").Pixel} A pixel position in the map viewport. + */ + getPixelFromCoordinateInternal(coordinate) { + const frameState = this.frameState_; + if (!frameState) { + return null; + } else { + return applyTransform( + frameState.coordinateToPixelTransform, + coordinate.slice(0, 2) + ); + } + } + + /** + * Get the map renderer. + * @return {import("./renderer/Map.js").default|null} Renderer + */ + getRenderer() { + return this.renderer_; + } + + /** + * Get the size of this map. + * @return {import("./size.js").Size|undefined} The size in pixels of the map in the DOM. + * @observable + * @api + */ + getSize() { + return /** @type {import("./size.js").Size|undefined} */ ( + this.get(MapProperty.SIZE) + ); + } + + /** + * Get the view associated with this map. A view manages properties such as + * center and resolution. + * @return {View} The view that controls this map. + * @observable + * @api + */ + getView() { + return /** @type {View} */ (this.get(MapProperty.VIEW)); + } + + /** + * Get the element that serves as the map viewport. + * @return {HTMLElement} Viewport. + * @api + */ + getViewport() { + return this.viewport_; + } + + /** + * Get the element that serves as the container for overlays. Elements added to + * this container will let mousedown and touchstart events through to the map, + * so clicks and gestures on an overlay will trigger {@link module:ol/MapBrowserEvent~MapBrowserEvent} + * events. + * @return {!HTMLElement} The map's overlay container. + */ + getOverlayContainer() { + return this.overlayContainer_; + } + + /** + * Get the element that serves as a container for overlays that don't allow + * event propagation. Elements added to this container won't let mousedown and + * touchstart events through to the map, so clicks and gestures on an overlay + * don't trigger any {@link module:ol/MapBrowserEvent~MapBrowserEvent}. + * @return {!HTMLElement} The map's overlay container that stops events. + */ + getOverlayContainerStopEvent() { + return this.overlayContainerStopEvent_; + } + + /** + * @return {!Document} The document where the map is displayed. + */ + getOwnerDocument() { + const targetElement = this.getTargetElement(); + return targetElement ? targetElement.ownerDocument : document; + } + + /** + * @param {import("./Tile.js").default} tile Tile. + * @param {string} tileSourceKey Tile source key. + * @param {import("./coordinate.js").Coordinate} tileCenter Tile center. + * @param {number} tileResolution Tile resolution. + * @return {number} Tile priority. + */ + getTilePriority(tile, tileSourceKey, tileCenter, tileResolution) { + return getTilePriority( + this.frameState_, + tile, + tileSourceKey, + tileCenter, + tileResolution + ); + } + + /** + * @param {UIEvent} browserEvent Browser event. + * @param {string} [opt_type] Type. + */ + handleBrowserEvent(browserEvent, opt_type) { + const type = opt_type || browserEvent.type; + const mapBrowserEvent = new MapBrowserEvent(type, this, browserEvent); + this.handleMapBrowserEvent(mapBrowserEvent); + } + + /** + * @param {MapBrowserEvent} mapBrowserEvent The event to handle. + */ + handleMapBrowserEvent(mapBrowserEvent) { + if (!this.frameState_) { + // With no view defined, we cannot translate pixels into geographical + // coordinates so interactions cannot be used. + return; + } + const originalEvent = /** @type {PointerEvent} */ ( + mapBrowserEvent.originalEvent + ); + const eventType = originalEvent.type; + if ( + eventType === PointerEventType.POINTERDOWN || + eventType === EventType.WHEEL || + eventType === EventType.KEYDOWN + ) { + const doc = this.getOwnerDocument(); + const rootNode = this.viewport_.getRootNode + ? this.viewport_.getRootNode() + : doc; + const target = /** @type {Node} */ (originalEvent.target); + if ( + // Abort if the target is a child of the container for elements whose events are not meant + // to be handled by map interactions. + this.overlayContainerStopEvent_.contains(target) || + // Abort if the event target is a child of the container that is no longer in the page. + // It's possible for the target to no longer be in the page if it has been removed in an + // event listener, this might happen in a Control that recreates it's content based on + // user interaction either manually or via a render in something like https://reactjs.org/ + !(rootNode === doc ? doc.documentElement : rootNode).contains(target) + ) { + return; + } + } + mapBrowserEvent.frameState = this.frameState_; + if (this.dispatchEvent(mapBrowserEvent) !== false) { + const interactionsArray = this.getInteractions().getArray().slice(); + for (let i = interactionsArray.length - 1; i >= 0; i--) { + const interaction = interactionsArray[i]; + if ( + interaction.getMap() !== this || + !interaction.getActive() || + !this.getTargetElement() + ) { + continue; + } + const cont = interaction.handleEvent(mapBrowserEvent); + if (!cont || mapBrowserEvent.propagationStopped) { + break; + } + } + } + } + + /** + * @protected + */ + handlePostRender() { + const frameState = this.frameState_; + + // Manage the tile queue + // Image loads are expensive and a limited resource, so try to use them + // efficiently: + // * When the view is static we allow a large number of parallel tile loads + // to complete the frame as quickly as possible. + // * When animating or interacting, image loads can cause janks, so we reduce + // the maximum number of loads per frame and limit the number of parallel + // tile loads to remain reactive to view changes and to reduce the chance of + // loading tiles that will quickly disappear from view. + const tileQueue = this.tileQueue_; + if (!tileQueue.isEmpty()) { + let maxTotalLoading = this.maxTilesLoading_; + let maxNewLoads = maxTotalLoading; + if (frameState) { + const hints = frameState.viewHints; + if (hints[ViewHint.ANIMATING] || hints[ViewHint.INTERACTING]) { + const lowOnFrameBudget = Date.now() - frameState.time > 8; + maxTotalLoading = lowOnFrameBudget ? 0 : 8; + maxNewLoads = lowOnFrameBudget ? 0 : 2; + } + } + if (tileQueue.getTilesLoading() < maxTotalLoading) { + tileQueue.reprioritize(); // FIXME only call if view has changed + tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads); + } + } + + if (frameState && this.renderer_ && !frameState.animate) { + if (this.renderComplete_ === true) { + if (this.hasListener(RenderEventType.RENDERCOMPLETE)) { + this.renderer_.dispatchRenderEvent( + RenderEventType.RENDERCOMPLETE, + frameState + ); + } + if (this.loaded_ === false) { + this.loaded_ = true; + this.dispatchEvent( + new MapEvent(MapEventType.LOADEND, this, frameState) + ); + } + } else if (this.loaded_ === true) { + this.loaded_ = false; + this.dispatchEvent( + new MapEvent(MapEventType.LOADSTART, this, frameState) + ); + } + } + + const postRenderFunctions = this.postRenderFunctions_; + for (let i = 0, ii = postRenderFunctions.length; i < ii; ++i) { + postRenderFunctions[i](this, frameState); + } + postRenderFunctions.length = 0; + } + + /** + * @private + */ + handleSizeChanged_() { + if (this.getView() && !this.getView().getAnimating()) { + this.getView().resolveConstraints(0); + } + + this.render(); + } + + /** + * @private + */ + handleTargetChanged_() { + if (this.mapBrowserEventHandler_) { + for (let i = 0, ii = this.targetChangeHandlerKeys_.length; i < ii; ++i) { + unlistenByKey(this.targetChangeHandlerKeys_[i]); + } + this.targetChangeHandlerKeys_ = null; + this.viewport_.removeEventListener( + EventType.CONTEXTMENU, + this.boundHandleBrowserEvent_ + ); + this.viewport_.removeEventListener( + EventType.WHEEL, + this.boundHandleBrowserEvent_ + ); + this.mapBrowserEventHandler_.dispose(); + this.mapBrowserEventHandler_ = null; + removeNode(this.viewport_); + } + + // target may be undefined, null, a string or an Element. + // If it's a string we convert it to an Element before proceeding. + // If it's not now an Element we remove the viewport from the DOM. + // If it's an Element we append the viewport element to it. + + const targetElement = this.getTargetElement(); + if (!targetElement) { + if (this.renderer_) { + clearTimeout(this.postRenderTimeoutHandle_); + this.postRenderTimeoutHandle_ = undefined; + this.postRenderFunctions_.length = 0; + this.renderer_.dispose(); + this.renderer_ = null; + } + if (this.animationDelayKey_) { + cancelAnimationFrame(this.animationDelayKey_); + this.animationDelayKey_ = undefined; + } + } else { + targetElement.appendChild(this.viewport_); + if (!this.renderer_) { + this.renderer_ = new CompositeMapRenderer(this); + } + + this.mapBrowserEventHandler_ = new MapBrowserEventHandler( + this, + this.moveTolerance_ + ); + for (const key in MapBrowserEventType) { + this.mapBrowserEventHandler_.addEventListener( + MapBrowserEventType[key], + this.handleMapBrowserEvent.bind(this) + ); + } + this.viewport_.addEventListener( + EventType.CONTEXTMENU, + this.boundHandleBrowserEvent_, + false + ); + this.viewport_.addEventListener( + EventType.WHEEL, + this.boundHandleBrowserEvent_, + PASSIVE_EVENT_LISTENERS ? {passive: false} : false + ); + + const defaultView = this.getOwnerDocument().defaultView; + const keyboardEventTarget = !this.keyboardEventTarget_ + ? targetElement + : this.keyboardEventTarget_; + this.targetChangeHandlerKeys_ = [ + listen( + keyboardEventTarget, + EventType.KEYDOWN, + this.handleBrowserEvent, + this + ), + listen( + keyboardEventTarget, + EventType.KEYPRESS, + this.handleBrowserEvent, + this + ), + listen(defaultView, EventType.RESIZE, this.updateSize, this), + ]; + } + + this.updateSize(); + // updateSize calls setSize, so no need to call this.render + // ourselves here. + } + + /** + * @private + */ + handleTileChange_() { + this.render(); + } + + /** + * @private + */ + handleViewPropertyChanged_() { + this.render(); + } + + /** + * @private + */ + handleViewChanged_() { + if (this.viewPropertyListenerKey_) { + unlistenByKey(this.viewPropertyListenerKey_); + this.viewPropertyListenerKey_ = null; + } + if (this.viewChangeListenerKey_) { + unlistenByKey(this.viewChangeListenerKey_); + this.viewChangeListenerKey_ = null; + } + const view = this.getView(); + if (view) { + this.updateViewportSize_(); + + this.viewPropertyListenerKey_ = listen( + view, + ObjectEventType.PROPERTYCHANGE, + this.handleViewPropertyChanged_, + this + ); + this.viewChangeListenerKey_ = listen( + view, + EventType.CHANGE, + this.handleViewPropertyChanged_, + this + ); + + view.resolveConstraints(0); + } + this.render(); + } + + /** + * @private + */ + handleLayerGroupChanged_() { + if (this.layerGroupPropertyListenerKeys_) { + this.layerGroupPropertyListenerKeys_.forEach(unlistenByKey); + this.layerGroupPropertyListenerKeys_ = null; + } + const layerGroup = this.getLayerGroup(); + if (layerGroup) { + this.handleLayerAdd_(new GroupEvent('addlayer', layerGroup)); + this.layerGroupPropertyListenerKeys_ = [ + listen(layerGroup, ObjectEventType.PROPERTYCHANGE, this.render, this), + listen(layerGroup, EventType.CHANGE, this.render, this), + listen(layerGroup, 'addlayer', this.handleLayerAdd_, this), + listen(layerGroup, 'removelayer', this.handleLayerRemove_, this), + ]; + } + this.render(); + } + + /** + * @return {boolean} Is rendered. + */ + isRendered() { + return !!this.frameState_; + } + + /** + * @private + */ + animationDelay_() { + this.animationDelayKey_ = undefined; + this.renderFrame_(Date.now()); + } + + /** + * Requests an immediate render in a synchronous manner. + * @api + */ + renderSync() { + if (this.animationDelayKey_) { + cancelAnimationFrame(this.animationDelayKey_); + } + this.animationDelay_(); + } + + /** + * Redraws all text after new fonts have loaded + */ + redrawText() { + const layerStates = this.getLayerGroup().getLayerStatesArray(); + for (let i = 0, ii = layerStates.length; i < ii; ++i) { + const layer = layerStates[i].layer; + if (layer.hasRenderer()) { + layer.getRenderer().handleFontsChanged(); + } + } + } + + /** + * Request a map rendering (at the next animation frame). + * @api + */ + render() { + if (this.renderer_ && this.animationDelayKey_ === undefined) { + this.animationDelayKey_ = requestAnimationFrame(this.animationDelay_); + } + } + + /** + * Remove the given control from the map. + * @param {import("./control/Control.js").default} control Control. + * @return {import("./control/Control.js").default|undefined} The removed control (or undefined + * if the control was not found). + * @api + */ + removeControl(control) { + return this.getControls().remove(control); + } + + /** + * Remove the given interaction from the map. + * @param {import("./interaction/Interaction.js").default} interaction Interaction to remove. + * @return {import("./interaction/Interaction.js").default|undefined} The removed interaction (or + * undefined if the interaction was not found). + * @api + */ + removeInteraction(interaction) { + return this.getInteractions().remove(interaction); + } + + /** + * Removes the given layer from the map. + * @param {import("./layer/Base.js").default} layer Layer. + * @return {import("./layer/Base.js").default|undefined} The removed layer (or undefined if the + * layer was not found). + * @api + */ + removeLayer(layer) { + const layers = this.getLayerGroup().getLayers(); + return layers.remove(layer); + } + + /** + * @param {import("./layer/Group.js").GroupEvent} event The layer remove event. + * @private + */ + handleLayerRemove_(event) { + removeLayerMapProperty(event.layer); + } + + /** + * Remove the given overlay from the map. + * @param {import("./Overlay.js").default} overlay Overlay. + * @return {import("./Overlay.js").default|undefined} The removed overlay (or undefined + * if the overlay was not found). + * @api + */ + removeOverlay(overlay) { + return this.getOverlays().remove(overlay); + } + + /** + * @param {number} time Time. + * @private + */ + renderFrame_(time) { + const size = this.getSize(); + const view = this.getView(); + const previousFrameState = this.frameState_; + /** @type {?FrameState} */ + let frameState = null; + if (size !== undefined && hasArea(size) && view && view.isDef()) { + const viewHints = view.getHints( + this.frameState_ ? this.frameState_.viewHints : undefined + ); + const viewState = view.getState(); + frameState = { + animate: false, + coordinateToPixelTransform: this.coordinateToPixelTransform_, + declutterTree: null, + extent: getForViewAndSize( + viewState.center, + viewState.resolution, + viewState.rotation, + size + ), + index: this.frameIndex_++, + layerIndex: 0, + layerStatesArray: this.getLayerGroup().getLayerStatesArray(), + pixelRatio: this.pixelRatio_, + pixelToCoordinateTransform: this.pixelToCoordinateTransform_, + postRenderFunctions: [], + size: size, + tileQueue: this.tileQueue_, + time: time, + usedTiles: {}, + viewState: viewState, + viewHints: viewHints, + wantedTiles: {}, + mapId: getUid(this), + renderTargets: {}, + }; + if (viewState.nextCenter && viewState.nextResolution) { + const rotation = isNaN(viewState.nextRotation) + ? viewState.rotation + : viewState.nextRotation; + + frameState.nextExtent = getForViewAndSize( + viewState.nextCenter, + viewState.nextResolution, + rotation, + size + ); + } + } + + this.frameState_ = frameState; + this.renderer_.renderFrame(frameState); + + if (frameState) { + if (frameState.animate) { + this.render(); + } + Array.prototype.push.apply( + this.postRenderFunctions_, + frameState.postRenderFunctions + ); + + if (previousFrameState) { + const moveStart = + !this.previousExtent_ || + (!isEmpty(this.previousExtent_) && + !equals(frameState.extent, this.previousExtent_)); + if (moveStart) { + this.dispatchEvent( + new MapEvent(MapEventType.MOVESTART, this, previousFrameState) + ); + this.previousExtent_ = createOrUpdateEmpty(this.previousExtent_); + } + } + + const idle = + this.previousExtent_ && + !frameState.viewHints[ViewHint.ANIMATING] && + !frameState.viewHints[ViewHint.INTERACTING] && + !equals(frameState.extent, this.previousExtent_); + + if (idle) { + this.dispatchEvent( + new MapEvent(MapEventType.MOVEEND, this, frameState) + ); + clone(frameState.extent, this.previousExtent_); + } + } + + this.dispatchEvent(new MapEvent(MapEventType.POSTRENDER, this, frameState)); + + this.renderComplete_ = + this.hasListener(MapEventType.LOADSTART) || + this.hasListener(MapEventType.LOADEND) || + this.hasListener(RenderEventType.RENDERCOMPLETE) + ? !this.tileQueue_.getTilesLoading() && + !this.tileQueue_.getCount() && + !this.getLoadingOrNotReady() + : undefined; + + if (!this.postRenderTimeoutHandle_) { + this.postRenderTimeoutHandle_ = setTimeout(() => { + this.postRenderTimeoutHandle_ = undefined; + this.handlePostRender(); + }, 0); + } + } + + /** + * Sets the layergroup of this map. + * @param {LayerGroup} layerGroup A layer group containing the layers in this map. + * @observable + * @api + */ + setLayerGroup(layerGroup) { + const oldLayerGroup = this.getLayerGroup(); + if (oldLayerGroup) { + this.handleLayerRemove_(new GroupEvent('removelayer', oldLayerGroup)); + } + this.set(MapProperty.LAYERGROUP, layerGroup); + } + + /** + * Set the size of this map. + * @param {import("./size.js").Size|undefined} size The size in pixels of the map in the DOM. + * @observable + * @api + */ + setSize(size) { + this.set(MapProperty.SIZE, size); + } + + /** + * Set the target element to render this map into. + * @param {HTMLElement|string} [target] The Element or id of the Element + * that the map is rendered in. + * @observable + * @api + */ + setTarget(target) { + this.set(MapProperty.TARGET, target); + } + + /** + * Set the view for this map. + * @param {View|Promise} view The view that controls this map. + * It is also possible to pass a promise that resolves to options for constructing a view. This + * alternative allows view properties to be resolved by sources or other components that load + * view-related metadata. + * @observable + * @api + */ + setView(view) { + if (!view || view instanceof View) { + this.set(MapProperty.VIEW, view); + return; + } + this.set(MapProperty.VIEW, new View()); + + const map = this; + view.then(function (viewOptions) { + map.setView(new View(viewOptions)); + }); + } + + /** + * Force a recalculation of the map viewport size. This should be called when + * third-party code changes the size of the map viewport. + * @api + */ + updateSize() { + const targetElement = this.getTargetElement(); + + let size = undefined; + if (targetElement) { + const computedStyle = getComputedStyle(targetElement); + const width = + targetElement.offsetWidth - + parseFloat(computedStyle['borderLeftWidth']) - + parseFloat(computedStyle['paddingLeft']) - + parseFloat(computedStyle['paddingRight']) - + parseFloat(computedStyle['borderRightWidth']); + const height = + targetElement.offsetHeight - + parseFloat(computedStyle['borderTopWidth']) - + parseFloat(computedStyle['paddingTop']) - + parseFloat(computedStyle['paddingBottom']) - + parseFloat(computedStyle['borderBottomWidth']); + if (!isNaN(width) && !isNaN(height)) { + size = [width, height]; + if ( + !hasArea(size) && + !!( + targetElement.offsetWidth || + targetElement.offsetHeight || + targetElement.getClientRects().length + ) + ) { + // eslint-disable-next-line + console.warn( + "No map visible because the map container's width or height are 0." + ); + } + } + } + + this.setSize(size); + this.updateViewportSize_(); + } + + /** + * Recomputes the viewport size and save it on the view object (if any) + * @private + */ + updateViewportSize_() { + const view = this.getView(); + if (view) { + let size = undefined; + const computedStyle = getComputedStyle(this.viewport_); + if (computedStyle.width && computedStyle.height) { + size = [ + parseInt(computedStyle.width, 10), + parseInt(computedStyle.height, 10), + ]; + } + view.setViewportSize(size); + } } } +/** + * @param {MapOptions} options Map options. + * @return {MapOptionsInternal} Internal map options. + */ +function createOptionsInternal(options) { + /** + * @type {HTMLElement|Document} + */ + let keyboardEventTarget = null; + if (options.keyboardEventTarget !== undefined) { + keyboardEventTarget = + typeof options.keyboardEventTarget === 'string' + ? document.getElementById(options.keyboardEventTarget) + : options.keyboardEventTarget; + } + + /** + * @type {Object} + */ + const values = {}; + + const layerGroup = + options.layers && + typeof (/** @type {?} */ (options.layers).getLayers) === 'function' + ? /** @type {LayerGroup} */ (options.layers) + : new LayerGroup({ + layers: + /** @type {Collection|Array} */ ( + options.layers + ), + }); + values[MapProperty.LAYERGROUP] = layerGroup; + + values[MapProperty.TARGET] = options.target; + + values[MapProperty.VIEW] = + options.view instanceof View ? options.view : new View(); + + /** @type {Collection} */ + let controls; + if (options.controls !== undefined) { + if (Array.isArray(options.controls)) { + controls = new Collection(options.controls.slice()); + } else { + assert( + typeof (/** @type {?} */ (options.controls).getArray) === 'function', + 47 + ); // Expected `controls` to be an array or an `import("./Collection.js").Collection` + controls = options.controls; + } + } + + /** @type {Collection} */ + let interactions; + if (options.interactions !== undefined) { + if (Array.isArray(options.interactions)) { + interactions = new Collection(options.interactions.slice()); + } else { + assert( + typeof (/** @type {?} */ (options.interactions).getArray) === + 'function', + 48 + ); // Expected `interactions` to be an array or an `import("./Collection.js").Collection` + interactions = options.interactions; + } + } + + /** @type {Collection} */ + let overlays; + if (options.overlays !== undefined) { + if (Array.isArray(options.overlays)) { + overlays = new Collection(options.overlays.slice()); + } else { + assert( + typeof (/** @type {?} */ (options.overlays).getArray) === 'function', + 49 + ); // Expected `overlays` to be an array or an `import("./Collection.js").Collection` + overlays = options.overlays; + } + } else { + overlays = new Collection(); + } + + return { + controls: controls, + interactions: interactions, + keyboardEventTarget: keyboardEventTarget, + overlays: overlays, + values: values, + }; +} export default Map; diff --git a/src/ol/MapBrowserEvent.js b/src/ol/MapBrowserEvent.js index dab8ab991d..a4b7674244 100644 --- a/src/ol/MapBrowserEvent.js +++ b/src/ol/MapBrowserEvent.js @@ -6,16 +6,16 @@ import MapEvent from './MapEvent.js'; /** * @classdesc * Events emitted as map browser events are instances of this type. - * See {@link module:ol/PluggableMap~PluggableMap} for which events trigger a map browser event. + * See {@link module:ol/Map~Map} for which events trigger a map browser event. * @template {UIEvent} EVENT */ class MapBrowserEvent extends MapEvent { /** * @param {string} type Event type. - * @param {import("./PluggableMap.js").default} map Map. + * @param {import("./Map.js").default} map Map. * @param {EVENT} originalEvent Original event. * @param {boolean} [opt_dragging] Is the map currently being dragged? - * @param {import("./PluggableMap.js").FrameState} [opt_frameState] Frame state. + * @param {import("./Map.js").FrameState} [opt_frameState] Frame state. * @param {Array} [opt_activePointers] Active pointers. */ constructor( diff --git a/src/ol/MapBrowserEventHandler.js b/src/ol/MapBrowserEventHandler.js index f0cc0ecb69..0946e0786e 100644 --- a/src/ol/MapBrowserEventHandler.js +++ b/src/ol/MapBrowserEventHandler.js @@ -13,7 +13,7 @@ import {listen, unlistenByKey} from './events.js'; class MapBrowserEventHandler extends Target { /** - * @param {import("./PluggableMap.js").default} map The map with the viewport to listen to events on. + * @param {import("./Map.js").default} map The map with the viewport to listen to events on. * @param {number} [moveTolerance] The minimal distance the pointer must travel to trigger a move. */ constructor(map, moveTolerance) { @@ -21,7 +21,7 @@ class MapBrowserEventHandler extends Target { /** * This is the element that we will listen to the real events on. - * @type {import("./PluggableMap.js").default} + * @type {import("./Map.js").default} * @private */ this.map_ = map; diff --git a/src/ol/MapEvent.js b/src/ol/MapEvent.js index 9c0ec07041..11271dd946 100644 --- a/src/ol/MapEvent.js +++ b/src/ol/MapEvent.js @@ -6,27 +6,27 @@ import Event from './events/Event.js'; /** * @classdesc * Events emitted as map events are instances of this type. - * See {@link module:ol/PluggableMap~PluggableMap} for which events trigger a map event. + * See {@link module:ol/Map~Map} for which events trigger a map event. */ class MapEvent extends Event { /** * @param {string} type Event type. - * @param {import("./PluggableMap.js").default} map Map. - * @param {?import("./PluggableMap.js").FrameState} [opt_frameState] Frame state. + * @param {import("./Map.js").default} map Map. + * @param {?import("./Map.js").FrameState} [opt_frameState] Frame state. */ constructor(type, map, opt_frameState) { super(type); /** * The map where the event occurred. - * @type {import("./PluggableMap.js").default} + * @type {import("./Map.js").default} * @api */ this.map = map; /** * The frame state at the time of the event. - * @type {?import("./PluggableMap.js").FrameState} + * @type {?import("./Map.js").FrameState} * @api */ this.frameState = opt_frameState !== undefined ? opt_frameState : null; diff --git a/src/ol/Overlay.js b/src/ol/Overlay.js index e3abe19353..5bdbc1b780 100644 --- a/src/ol/Overlay.js +++ b/src/ol/Overlay.js @@ -229,13 +229,13 @@ class Overlay extends BaseObject { /** * Get the map associated with this overlay. - * @return {import("./PluggableMap.js").default|null} The map that the + * @return {import("./Map.js").default|null} The map that the * overlay is part of. * @observable * @api */ getMap() { - return /** @type {import("./PluggableMap.js").default|null} */ ( + return /** @type {import("./Map.js").default|null} */ ( this.get(Property.MAP) || null ); } @@ -356,7 +356,7 @@ class Overlay extends BaseObject { /** * Set the map to be associated with this overlay. - * @param {import("./PluggableMap.js").default|null} map The map that the + * @param {import("./Map.js").default|null} map The map that the * overlay is part of. Pass `null` to just remove the overlay from the current map. * @observable * @api diff --git a/src/ol/PluggableMap.js b/src/ol/PluggableMap.js deleted file mode 100644 index a159feb9ed..0000000000 --- a/src/ol/PluggableMap.js +++ /dev/null @@ -1,1773 +0,0 @@ -/** - * @module ol/PluggableMap - */ -import BaseObject from './Object.js'; -import Collection from './Collection.js'; -import CollectionEventType from './CollectionEventType.js'; -import EventType from './events/EventType.js'; -import Layer from './layer/Layer.js'; -import LayerGroup, {GroupEvent} from './layer/Group.js'; -import MapBrowserEvent from './MapBrowserEvent.js'; -import MapBrowserEventHandler from './MapBrowserEventHandler.js'; -import MapBrowserEventType from './MapBrowserEventType.js'; -import MapEvent from './MapEvent.js'; -import MapEventType from './MapEventType.js'; -import MapProperty from './MapProperty.js'; -import ObjectEventType from './ObjectEventType.js'; -import PointerEventType from './pointer/EventType.js'; -import RenderEventType from './render/EventType.js'; -import TileQueue, {getTilePriority} from './TileQueue.js'; -import View from './View.js'; -import ViewHint from './ViewHint.js'; -import {DEVICE_PIXEL_RATIO, PASSIVE_EVENT_LISTENERS} from './has.js'; -import {TRUE} from './functions.js'; -import { - apply as applyTransform, - create as createTransform, -} from './transform.js'; -import {assert} from './asserts.js'; -import { - clone, - createOrUpdateEmpty, - equals, - getForViewAndSize, - isEmpty, -} from './extent.js'; -import {fromUserCoordinate, toUserCoordinate} from './proj.js'; -import {getUid} from './util.js'; -import {hasArea} from './size.js'; -import {listen, unlistenByKey} from './events.js'; -import {removeNode} from './dom.js'; - -/** - * State of the current frame. Only `pixelRatio`, `time` and `viewState` should - * be used in applications. - * @typedef {Object} FrameState - * @property {number} pixelRatio The pixel ratio of the frame. - * @property {number} time The time when rendering of the frame was requested. - * @property {import("./View.js").State} viewState The state of the current view. - * @property {boolean} animate Animate. - * @property {import("./transform.js").Transform} coordinateToPixelTransform CoordinateToPixelTransform. - * @property {import("rbush").default} declutterTree DeclutterTree. - * @property {null|import("./extent.js").Extent} extent Extent. - * @property {import("./extent.js").Extent} [nextExtent] Next extent during an animation series. - * @property {number} index Index. - * @property {Array} layerStatesArray LayerStatesArray. - * @property {number} layerIndex LayerIndex. - * @property {import("./transform.js").Transform} pixelToCoordinateTransform PixelToCoordinateTransform. - * @property {Array} postRenderFunctions PostRenderFunctions. - * @property {import("./size.js").Size} size Size. - * @property {TileQueue} tileQueue TileQueue. - * @property {!Object>} usedTiles UsedTiles. - * @property {Array} viewHints ViewHints. - * @property {!Object>} wantedTiles WantedTiles. - * @property {string} mapId The id of the map. - * @property {Object} renderTargets Identifiers of previously rendered elements. - */ - -/** - * @typedef {function(PluggableMap, ?FrameState): any} PostRenderFunction - */ - -/** - * @typedef {Object} AtPixelOptions - * @property {undefined|function(import("./layer/Layer.js").default): boolean} [layerFilter] Layer filter - * function. The filter function will receive one argument, the - * {@link module:ol/layer/Layer~Layer layer-candidate} and it should return a boolean value. - * Only layers which are visible and for which this function returns `true` - * will be tested for features. By default, all visible layers will be tested. - * @property {number} [hitTolerance=0] Hit-detection tolerance in css pixels. Pixels - * inside the radius around the given position will be checked for features. - * @property {boolean} [checkWrapped=true] Check-Wrapped Will check for for wrapped geometries inside the range of - * +/- 1 world width. Works only if a projection is used that can be wrapped. - */ - -/** - * @typedef {Object} MapOptionsInternal - * @property {Collection} [controls] Controls. - * @property {Collection} [interactions] Interactions. - * @property {HTMLElement|Document} keyboardEventTarget KeyboardEventTarget. - * @property {Collection} overlays Overlays. - * @property {Object} values Values. - */ - -/** - * @typedef {import("./ObjectEventType").Types|'change:layergroup'|'change:size'|'change:target'|'change:view'} MapObjectEventTypes - */ - -/*** - * @template Return - * @typedef {import("./Observable").OnSignature & - * import("./Observable").OnSignature & - * import("./Observable").OnSignature & - * import("./Observable").OnSignature & - * import("./Observable").OnSignature & - * import("./Observable").CombinedOnSignature} PluggableMapOnSignature - */ - -/** - * Object literal with config options for the map. - * @typedef {Object} MapOptions - * @property {Collection|Array} [controls] - * Controls initially added to the map. If not specified, - * {@link module:ol/control.defaults} is used. - * @property {number} [pixelRatio=window.devicePixelRatio] The ratio between - * physical pixels and device-independent pixels (dips) on the device. - * @property {Collection|Array} [interactions] - * Interactions that are initially added to the map. If not specified, - * {@link module:ol/interaction.defaults} is used. - * @property {HTMLElement|Document|string} [keyboardEventTarget] The element to - * listen to keyboard events on. This determines when the `KeyboardPan` and - * `KeyboardZoom` interactions trigger. For example, if this option is set to - * `document` the keyboard interactions will always trigger. If this option is - * not specified, the element the library listens to keyboard events on is the - * map target (i.e. the user-provided div for the map). If this is not - * `document`, the target element needs to be focused for key events to be - * emitted, requiring that the target element has a `tabindex` attribute. - * @property {Array|Collection|LayerGroup} [layers] - * Layers. If this is not defined, a map with no layers will be rendered. Note - * that layers are rendered in the order supplied, so if you want, for example, - * a vector layer to appear on top of a tile layer, it must come after the tile - * layer. - * @property {number} [maxTilesLoading=16] Maximum number tiles to load - * simultaneously. - * @property {number} [moveTolerance=1] The minimum distance in pixels the - * cursor must move to be detected as a map move event instead of a click. - * Increasing this value can make it easier to click on the map. - * @property {Collection|Array} [overlays] - * Overlays initially added to the map. By default, no overlays are added. - * @property {HTMLElement|string} [target] The container for the map, either the - * element itself or the `id` of the element. If not specified at construction - * time, {@link module:ol/Map~Map#setTarget} must be called for the map to be - * rendered. If passed by element, the container can be in a secondary document. - * @property {View|Promise} [view] The map's view. No layer sources will be - * fetched unless this is specified at construction time or through - * {@link module:ol/Map~Map#setView}. - */ - -/** - * @param {import("./layer/Base.js").default} layer Layer. - */ -function removeLayerMapProperty(layer) { - if (layer instanceof Layer) { - layer.setMapInternal(null); - return; - } - if (layer instanceof LayerGroup) { - layer.getLayers().forEach(removeLayerMapProperty); - } -} - -/** - * @param {import("./layer/Base.js").default} layer Layer. - * @param {PluggableMap} map Map. - */ -function setLayerMapProperty(layer, map) { - if (layer instanceof Layer) { - layer.setMapInternal(map); - return; - } - if (layer instanceof LayerGroup) { - const layers = layer.getLayers().getArray(); - for (let i = 0, ii = layers.length; i < ii; ++i) { - setLayerMapProperty(layers[i], map); - } - } -} - -/** - * @fires import("./MapBrowserEvent.js").MapBrowserEvent - * @fires import("./MapEvent.js").MapEvent - * @fires import("./render/Event.js").default#precompose - * @fires import("./render/Event.js").default#postcompose - * @fires import("./render/Event.js").default#rendercomplete - * @api - */ -class PluggableMap extends BaseObject { - /** - * @param {MapOptions} options Map options. - */ - constructor(options) { - super(); - - /*** - * @type {PluggableMapOnSignature} - */ - this.on; - - /*** - * @type {PluggableMapOnSignature} - */ - this.once; - - /*** - * @type {PluggableMapOnSignature} - */ - this.un; - - const optionsInternal = createOptionsInternal(options); - - /** - * @private - * @type {boolean|undefined} - */ - this.renderComplete_; - - /** - * @private - * @type {boolean} - */ - this.loaded_ = true; - - /** @private */ - this.boundHandleBrowserEvent_ = this.handleBrowserEvent.bind(this); - - /** - * @type {number} - * @private - */ - this.maxTilesLoading_ = - options.maxTilesLoading !== undefined ? options.maxTilesLoading : 16; - - /** - * @private - * @type {number} - */ - this.pixelRatio_ = - options.pixelRatio !== undefined - ? options.pixelRatio - : DEVICE_PIXEL_RATIO; - - /** - * @private - * @type {*} - */ - this.postRenderTimeoutHandle_; - - /** - * @private - * @type {number|undefined} - */ - this.animationDelayKey_; - - /** - * @private - */ - this.animationDelay_ = /** @this {PluggableMap} */ function () { - this.animationDelayKey_ = undefined; - this.renderFrame_(Date.now()); - }.bind(this); - - /** - * @private - * @type {import("./transform.js").Transform} - */ - this.coordinateToPixelTransform_ = createTransform(); - - /** - * @private - * @type {import("./transform.js").Transform} - */ - this.pixelToCoordinateTransform_ = createTransform(); - - /** - * @private - * @type {number} - */ - this.frameIndex_ = 0; - - /** - * @private - * @type {?FrameState} - */ - this.frameState_ = null; - - /** - * The extent at the previous 'moveend' event. - * @private - * @type {import("./extent.js").Extent} - */ - this.previousExtent_ = null; - - /** - * @private - * @type {?import("./events.js").EventsKey} - */ - this.viewPropertyListenerKey_ = null; - - /** - * @private - * @type {?import("./events.js").EventsKey} - */ - this.viewChangeListenerKey_ = null; - - /** - * @private - * @type {?Array} - */ - this.layerGroupPropertyListenerKeys_ = null; - - /** - * @private - * @type {!HTMLElement} - */ - this.viewport_ = document.createElement('div'); - this.viewport_.className = - 'ol-viewport' + ('ontouchstart' in window ? ' ol-touch' : ''); - this.viewport_.style.position = 'relative'; - this.viewport_.style.overflow = 'hidden'; - this.viewport_.style.width = '100%'; - this.viewport_.style.height = '100%'; - - /** - * @private - * @type {!HTMLElement} - */ - this.overlayContainer_ = document.createElement('div'); - this.overlayContainer_.style.position = 'absolute'; - this.overlayContainer_.style.zIndex = '0'; - this.overlayContainer_.style.width = '100%'; - this.overlayContainer_.style.height = '100%'; - this.overlayContainer_.style.pointerEvents = 'none'; - this.overlayContainer_.className = 'ol-overlaycontainer'; - this.viewport_.appendChild(this.overlayContainer_); - - /** - * @private - * @type {!HTMLElement} - */ - this.overlayContainerStopEvent_ = document.createElement('div'); - this.overlayContainerStopEvent_.style.position = 'absolute'; - this.overlayContainerStopEvent_.style.zIndex = '0'; - this.overlayContainerStopEvent_.style.width = '100%'; - this.overlayContainerStopEvent_.style.height = '100%'; - this.overlayContainerStopEvent_.style.pointerEvents = 'none'; - this.overlayContainerStopEvent_.className = 'ol-overlaycontainer-stopevent'; - this.viewport_.appendChild(this.overlayContainerStopEvent_); - - /** - * @private - * @type {MapBrowserEventHandler} - */ - this.mapBrowserEventHandler_ = null; - - /** - * @private - * @type {number} - */ - this.moveTolerance_ = options.moveTolerance; - - /** - * @private - * @type {HTMLElement|Document} - */ - this.keyboardEventTarget_ = optionsInternal.keyboardEventTarget; - - /** - * @private - * @type {?Array} - */ - this.targetChangeHandlerKeys_ = null; - - /** - * @type {Collection} - * @protected - */ - this.controls = optionsInternal.controls || new Collection(); - - /** - * @type {Collection} - * @protected - */ - this.interactions = optionsInternal.interactions || new Collection(); - - /** - * @type {Collection} - * @private - */ - this.overlays_ = optionsInternal.overlays; - - /** - * A lookup of overlays by id. - * @private - * @type {Object} - */ - this.overlayIdIndex_ = {}; - - /** - * @type {import("./renderer/Map.js").default|null} - * @private - */ - this.renderer_ = null; - - /** - * @private - * @type {!Array} - */ - this.postRenderFunctions_ = []; - - /** - * @private - * @type {TileQueue} - */ - this.tileQueue_ = new TileQueue( - this.getTilePriority.bind(this), - this.handleTileChange_.bind(this) - ); - - this.addChangeListener( - MapProperty.LAYERGROUP, - this.handleLayerGroupChanged_ - ); - this.addChangeListener(MapProperty.VIEW, this.handleViewChanged_); - this.addChangeListener(MapProperty.SIZE, this.handleSizeChanged_); - this.addChangeListener(MapProperty.TARGET, this.handleTargetChanged_); - - // setProperties will trigger the rendering of the map if the map - // is "defined" already. - this.setProperties(optionsInternal.values); - - const map = this; - if (options.view && !(options.view instanceof View)) { - options.view.then(function (viewOptions) { - map.setView(new View(viewOptions)); - }); - } - - this.controls.addEventListener( - CollectionEventType.ADD, - /** - * @param {import("./Collection.js").CollectionEvent} event CollectionEvent - */ - function (event) { - event.element.setMap(this); - }.bind(this) - ); - - this.controls.addEventListener( - CollectionEventType.REMOVE, - /** - * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. - */ - function (event) { - event.element.setMap(null); - }.bind(this) - ); - - this.interactions.addEventListener( - CollectionEventType.ADD, - /** - * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. - */ - function (event) { - event.element.setMap(this); - }.bind(this) - ); - - this.interactions.addEventListener( - CollectionEventType.REMOVE, - /** - * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. - */ - function (event) { - event.element.setMap(null); - }.bind(this) - ); - - this.overlays_.addEventListener( - CollectionEventType.ADD, - /** - * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. - */ - function (event) { - this.addOverlayInternal_(event.element); - }.bind(this) - ); - - this.overlays_.addEventListener( - CollectionEventType.REMOVE, - /** - * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. - */ - function (event) { - const id = event.element.getId(); - if (id !== undefined) { - delete this.overlayIdIndex_[id.toString()]; - } - event.element.setMap(null); - }.bind(this) - ); - - this.controls.forEach( - /** - * @param {import("./control/Control.js").default} control Control. - * @this {PluggableMap} - */ - function (control) { - control.setMap(this); - }.bind(this) - ); - - this.interactions.forEach( - /** - * @param {import("./interaction/Interaction.js").default} interaction Interaction. - * @this {PluggableMap} - */ - function (interaction) { - interaction.setMap(this); - }.bind(this) - ); - - this.overlays_.forEach(this.addOverlayInternal_.bind(this)); - } - - /** - * @abstract - * @return {import("./renderer/Map.js").default} The map renderer - */ - createRenderer() { - throw new Error('Use a map type that has a createRenderer method'); - } - - /** - * Add the given control to the map. - * @param {import("./control/Control.js").default} control Control. - * @api - */ - addControl(control) { - this.getControls().push(control); - } - - /** - * Add the given interaction to the map. If you want to add an interaction - * at another point of the collection use `getInteractions()` and the methods - * available on {@link module:ol/Collection~Collection}. This can be used to - * stop the event propagation from the handleEvent function. The interactions - * get to handle the events in the reverse order of this collection. - * @param {import("./interaction/Interaction.js").default} interaction Interaction to add. - * @api - */ - addInteraction(interaction) { - this.getInteractions().push(interaction); - } - - /** - * Adds the given layer to the top of this map. If you want to add a layer - * elsewhere in the stack, use `getLayers()` and the methods available on - * {@link module:ol/Collection~Collection}. - * @param {import("./layer/Base.js").default} layer Layer. - * @api - */ - addLayer(layer) { - const layers = this.getLayerGroup().getLayers(); - layers.push(layer); - } - - /** - * @param {import("./layer/Group.js").GroupEvent} event The layer add event. - * @private - */ - handleLayerAdd_(event) { - setLayerMapProperty(event.layer, this); - } - - /** - * Add the given overlay to the map. - * @param {import("./Overlay.js").default} overlay Overlay. - * @api - */ - addOverlay(overlay) { - this.getOverlays().push(overlay); - } - - /** - * This deals with map's overlay collection changes. - * @param {import("./Overlay.js").default} overlay Overlay. - * @private - */ - addOverlayInternal_(overlay) { - const id = overlay.getId(); - if (id !== undefined) { - this.overlayIdIndex_[id.toString()] = overlay; - } - overlay.setMap(this); - } - - /** - * - * Clean up. - */ - disposeInternal() { - this.controls.clear(); - this.interactions.clear(); - this.overlays_.clear(); - this.setTarget(null); - super.disposeInternal(); - } - - /** - * Detect features that intersect a pixel on the viewport, and execute a - * callback with each intersecting feature. Layers included in the detection can - * be configured through the `layerFilter` option in `opt_options`. - * @param {import("./pixel.js").Pixel} pixel Pixel. - * @param {function(import("./Feature.js").FeatureLike, import("./layer/Layer.js").default, import("./geom/SimpleGeometry.js").default): T} callback Feature callback. The callback will be - * called with two arguments. The first argument is one - * {@link module:ol/Feature~Feature feature} or - * {@link module:ol/render/Feature~RenderFeature render feature} at the pixel, the second is - * the {@link module:ol/layer/Layer~Layer layer} of the feature and will be null for - * unmanaged layers. To stop detection, callback functions can return a - * truthy value. - * @param {AtPixelOptions} [opt_options] Optional options. - * @return {T|undefined} Callback result, i.e. the return value of last - * callback execution, or the first truthy callback return value. - * @template T - * @api - */ - forEachFeatureAtPixel(pixel, callback, opt_options) { - if (!this.frameState_ || !this.renderer_) { - return; - } - const coordinate = this.getCoordinateFromPixelInternal(pixel); - opt_options = opt_options !== undefined ? opt_options : {}; - const hitTolerance = - opt_options.hitTolerance !== undefined ? opt_options.hitTolerance : 0; - const layerFilter = - opt_options.layerFilter !== undefined ? opt_options.layerFilter : TRUE; - const checkWrapped = opt_options.checkWrapped !== false; - return this.renderer_.forEachFeatureAtCoordinate( - coordinate, - this.frameState_, - hitTolerance, - checkWrapped, - callback, - null, - layerFilter, - null - ); - } - - /** - * Get all features that intersect a pixel on the viewport. - * @param {import("./pixel.js").Pixel} pixel Pixel. - * @param {AtPixelOptions} [opt_options] Optional options. - * @return {Array} The detected features or - * an empty array if none were found. - * @api - */ - getFeaturesAtPixel(pixel, opt_options) { - const features = []; - this.forEachFeatureAtPixel( - pixel, - function (feature) { - features.push(feature); - }, - opt_options - ); - return features; - } - - /** - * Get all layers from all layer groups. - * @return {Array} Layers. - * @api - */ - getAllLayers() { - const layers = []; - function addLayersFrom(layerGroup) { - layerGroup.forEach(function (layer) { - if (layer instanceof LayerGroup) { - addLayersFrom(layer.getLayers()); - } else { - layers.push(layer); - } - }); - } - addLayersFrom(this.getLayers()); - return layers; - } - - /** - * Detect if features intersect a pixel on the viewport. Layers included in the - * detection can be configured through `opt_layerFilter`. - * @param {import("./pixel.js").Pixel} pixel Pixel. - * @param {AtPixelOptions} [opt_options] Optional options. - * @return {boolean} Is there a feature at the given pixel? - * @api - */ - hasFeatureAtPixel(pixel, opt_options) { - if (!this.frameState_ || !this.renderer_) { - return false; - } - const coordinate = this.getCoordinateFromPixelInternal(pixel); - opt_options = opt_options !== undefined ? opt_options : {}; - const layerFilter = - opt_options.layerFilter !== undefined ? opt_options.layerFilter : TRUE; - const hitTolerance = - opt_options.hitTolerance !== undefined ? opt_options.hitTolerance : 0; - const checkWrapped = opt_options.checkWrapped !== false; - return this.renderer_.hasFeatureAtCoordinate( - coordinate, - this.frameState_, - hitTolerance, - checkWrapped, - layerFilter, - null - ); - } - - /** - * Returns the coordinate in user projection for a browser event. - * @param {MouseEvent} event Event. - * @return {import("./coordinate.js").Coordinate} Coordinate. - * @api - */ - getEventCoordinate(event) { - return this.getCoordinateFromPixel(this.getEventPixel(event)); - } - - /** - * Returns the coordinate in view projection for a browser event. - * @param {MouseEvent} event Event. - * @return {import("./coordinate.js").Coordinate} Coordinate. - */ - getEventCoordinateInternal(event) { - return this.getCoordinateFromPixelInternal(this.getEventPixel(event)); - } - - /** - * Returns the map pixel position for a browser event relative to the viewport. - * @param {UIEvent} event Event. - * @return {import("./pixel.js").Pixel} Pixel. - * @api - */ - getEventPixel(event) { - const viewportPosition = this.viewport_.getBoundingClientRect(); - const eventPosition = - //FIXME Are we really calling this with a TouchEvent anywhere? - 'changedTouches' in event - ? /** @type {TouchEvent} */ (event).changedTouches[0] - : /** @type {MouseEvent} */ (event); - - return [ - eventPosition.clientX - viewportPosition.left, - eventPosition.clientY - viewportPosition.top, - ]; - } - - /** - * Get the target in which this map is rendered. - * Note that this returns what is entered as an option or in setTarget: - * if that was an element, it returns an element; if a string, it returns that. - * @return {HTMLElement|string|undefined} The Element or id of the Element that the - * map is rendered in. - * @observable - * @api - */ - getTarget() { - return /** @type {HTMLElement|string|undefined} */ ( - this.get(MapProperty.TARGET) - ); - } - - /** - * Get the DOM element into which this map is rendered. In contrast to - * `getTarget` this method always return an `Element`, or `null` if the - * map has no target. - * @return {HTMLElement} The element that the map is rendered in. - * @api - */ - getTargetElement() { - const target = this.getTarget(); - if (target !== undefined) { - return typeof target === 'string' - ? document.getElementById(target) - : target; - } else { - return null; - } - } - - /** - * Get the coordinate for a given pixel. This returns a coordinate in the - * user projection. - * @param {import("./pixel.js").Pixel} pixel Pixel position in the map viewport. - * @return {import("./coordinate.js").Coordinate} The coordinate for the pixel position. - * @api - */ - getCoordinateFromPixel(pixel) { - return toUserCoordinate( - this.getCoordinateFromPixelInternal(pixel), - this.getView().getProjection() - ); - } - - /** - * Get the coordinate for a given pixel. This returns a coordinate in the - * map view projection. - * @param {import("./pixel.js").Pixel} pixel Pixel position in the map viewport. - * @return {import("./coordinate.js").Coordinate} The coordinate for the pixel position. - */ - getCoordinateFromPixelInternal(pixel) { - const frameState = this.frameState_; - if (!frameState) { - return null; - } else { - return applyTransform( - frameState.pixelToCoordinateTransform, - pixel.slice() - ); - } - } - - /** - * Get the map controls. Modifying this collection changes the controls - * associated with the map. - * @return {Collection} Controls. - * @api - */ - getControls() { - return this.controls; - } - - /** - * Get the map overlays. Modifying this collection changes the overlays - * associated with the map. - * @return {Collection} Overlays. - * @api - */ - getOverlays() { - return this.overlays_; - } - - /** - * Get an overlay by its identifier (the value returned by overlay.getId()). - * Note that the index treats string and numeric identifiers as the same. So - * `map.getOverlayById(2)` will return an overlay with id `'2'` or `2`. - * @param {string|number} id Overlay identifier. - * @return {import("./Overlay.js").default} Overlay. - * @api - */ - getOverlayById(id) { - const overlay = this.overlayIdIndex_[id.toString()]; - return overlay !== undefined ? overlay : null; - } - - /** - * Get the map interactions. Modifying this collection changes the interactions - * associated with the map. - * - * Interactions are used for e.g. pan, zoom and rotate. - * @return {Collection} Interactions. - * @api - */ - getInteractions() { - return this.interactions; - } - - /** - * Get the layergroup associated with this map. - * @return {LayerGroup} A layer group containing the layers in this map. - * @observable - * @api - */ - getLayerGroup() { - return /** @type {LayerGroup} */ (this.get(MapProperty.LAYERGROUP)); - } - - /** - * Clear any existing layers and add layers to the map. - * @param {Array|Collection} layers The layers to be added to the map. - * @api - */ - setLayers(layers) { - const group = this.getLayerGroup(); - if (layers instanceof Collection) { - group.setLayers(layers); - return; - } - - const collection = group.getLayers(); - collection.clear(); - collection.extend(layers); - } - - /** - * Get the collection of layers associated with this map. - * @return {!Collection} Layers. - * @api - */ - getLayers() { - const layers = this.getLayerGroup().getLayers(); - return layers; - } - - /** - * @return {boolean} Layers have sources that are still loading. - */ - getLoadingOrNotReady() { - const layerStatesArray = this.getLayerGroup().getLayerStatesArray(); - for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) { - const state = layerStatesArray[i]; - if (!state.visible) { - continue; - } - const renderer = state.layer.getRenderer(); - if (renderer && !renderer.ready) { - return true; - } - const source = /** @type {import("./layer/Layer.js").default} */ ( - state.layer - ).getSource(); - if (source && source.loading) { - return true; - } - } - return false; - } - - /** - * Get the pixel for a coordinate. This takes a coordinate in the user - * projection and returns the corresponding pixel. - * @param {import("./coordinate.js").Coordinate} coordinate A map coordinate. - * @return {import("./pixel.js").Pixel} A pixel position in the map viewport. - * @api - */ - getPixelFromCoordinate(coordinate) { - const viewCoordinate = fromUserCoordinate( - coordinate, - this.getView().getProjection() - ); - return this.getPixelFromCoordinateInternal(viewCoordinate); - } - - /** - * Get the pixel for a coordinate. This takes a coordinate in the map view - * projection and returns the corresponding pixel. - * @param {import("./coordinate.js").Coordinate} coordinate A map coordinate. - * @return {import("./pixel.js").Pixel} A pixel position in the map viewport. - */ - getPixelFromCoordinateInternal(coordinate) { - const frameState = this.frameState_; - if (!frameState) { - return null; - } else { - return applyTransform( - frameState.coordinateToPixelTransform, - coordinate.slice(0, 2) - ); - } - } - - /** - * Get the map renderer. - * @return {import("./renderer/Map.js").default|null} Renderer - */ - getRenderer() { - return this.renderer_; - } - - /** - * Get the size of this map. - * @return {import("./size.js").Size|undefined} The size in pixels of the map in the DOM. - * @observable - * @api - */ - getSize() { - return /** @type {import("./size.js").Size|undefined} */ ( - this.get(MapProperty.SIZE) - ); - } - - /** - * Get the view associated with this map. A view manages properties such as - * center and resolution. - * @return {View} The view that controls this map. - * @observable - * @api - */ - getView() { - return /** @type {View} */ (this.get(MapProperty.VIEW)); - } - - /** - * Get the element that serves as the map viewport. - * @return {HTMLElement} Viewport. - * @api - */ - getViewport() { - return this.viewport_; - } - - /** - * Get the element that serves as the container for overlays. Elements added to - * this container will let mousedown and touchstart events through to the map, - * so clicks and gestures on an overlay will trigger {@link module:ol/MapBrowserEvent~MapBrowserEvent} - * events. - * @return {!HTMLElement} The map's overlay container. - */ - getOverlayContainer() { - return this.overlayContainer_; - } - - /** - * Get the element that serves as a container for overlays that don't allow - * event propagation. Elements added to this container won't let mousedown and - * touchstart events through to the map, so clicks and gestures on an overlay - * don't trigger any {@link module:ol/MapBrowserEvent~MapBrowserEvent}. - * @return {!HTMLElement} The map's overlay container that stops events. - */ - getOverlayContainerStopEvent() { - return this.overlayContainerStopEvent_; - } - - /** - * @return {!Document} The document where the map is displayed. - */ - getOwnerDocument() { - const targetElement = this.getTargetElement(); - return targetElement ? targetElement.ownerDocument : document; - } - - /** - * @param {import("./Tile.js").default} tile Tile. - * @param {string} tileSourceKey Tile source key. - * @param {import("./coordinate.js").Coordinate} tileCenter Tile center. - * @param {number} tileResolution Tile resolution. - * @return {number} Tile priority. - */ - getTilePriority(tile, tileSourceKey, tileCenter, tileResolution) { - return getTilePriority( - this.frameState_, - tile, - tileSourceKey, - tileCenter, - tileResolution - ); - } - - /** - * @param {UIEvent} browserEvent Browser event. - * @param {string} [opt_type] Type. - */ - handleBrowserEvent(browserEvent, opt_type) { - const type = opt_type || browserEvent.type; - const mapBrowserEvent = new MapBrowserEvent(type, this, browserEvent); - this.handleMapBrowserEvent(mapBrowserEvent); - } - - /** - * @param {MapBrowserEvent} mapBrowserEvent The event to handle. - */ - handleMapBrowserEvent(mapBrowserEvent) { - if (!this.frameState_) { - // With no view defined, we cannot translate pixels into geographical - // coordinates so interactions cannot be used. - return; - } - const originalEvent = /** @type {PointerEvent} */ ( - mapBrowserEvent.originalEvent - ); - const eventType = originalEvent.type; - if ( - eventType === PointerEventType.POINTERDOWN || - eventType === EventType.WHEEL || - eventType === EventType.KEYDOWN - ) { - const doc = this.getOwnerDocument(); - const rootNode = this.viewport_.getRootNode - ? this.viewport_.getRootNode() - : doc; - const target = /** @type {Node} */ (originalEvent.target); - if ( - // Abort if the target is a child of the container for elements whose events are not meant - // to be handled by map interactions. - this.overlayContainerStopEvent_.contains(target) || - // Abort if the event target is a child of the container that is no longer in the page. - // It's possible for the target to no longer be in the page if it has been removed in an - // event listener, this might happen in a Control that recreates it's content based on - // user interaction either manually or via a render in something like https://reactjs.org/ - !(rootNode === doc ? doc.documentElement : rootNode).contains(target) - ) { - return; - } - } - mapBrowserEvent.frameState = this.frameState_; - if (this.dispatchEvent(mapBrowserEvent) !== false) { - const interactionsArray = this.getInteractions().getArray().slice(); - for (let i = interactionsArray.length - 1; i >= 0; i--) { - const interaction = interactionsArray[i]; - if ( - interaction.getMap() !== this || - !interaction.getActive() || - !this.getTargetElement() - ) { - continue; - } - const cont = interaction.handleEvent(mapBrowserEvent); - if (!cont || mapBrowserEvent.propagationStopped) { - break; - } - } - } - } - - /** - * @protected - */ - handlePostRender() { - const frameState = this.frameState_; - - // Manage the tile queue - // Image loads are expensive and a limited resource, so try to use them - // efficiently: - // * When the view is static we allow a large number of parallel tile loads - // to complete the frame as quickly as possible. - // * When animating or interacting, image loads can cause janks, so we reduce - // the maximum number of loads per frame and limit the number of parallel - // tile loads to remain reactive to view changes and to reduce the chance of - // loading tiles that will quickly disappear from view. - const tileQueue = this.tileQueue_; - if (!tileQueue.isEmpty()) { - let maxTotalLoading = this.maxTilesLoading_; - let maxNewLoads = maxTotalLoading; - if (frameState) { - const hints = frameState.viewHints; - if (hints[ViewHint.ANIMATING] || hints[ViewHint.INTERACTING]) { - const lowOnFrameBudget = Date.now() - frameState.time > 8; - maxTotalLoading = lowOnFrameBudget ? 0 : 8; - maxNewLoads = lowOnFrameBudget ? 0 : 2; - } - } - if (tileQueue.getTilesLoading() < maxTotalLoading) { - tileQueue.reprioritize(); // FIXME only call if view has changed - tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads); - } - } - - if (frameState && this.renderer_ && !frameState.animate) { - if (this.renderComplete_ === true) { - if (this.hasListener(RenderEventType.RENDERCOMPLETE)) { - this.renderer_.dispatchRenderEvent( - RenderEventType.RENDERCOMPLETE, - frameState - ); - } - if (this.loaded_ === false) { - this.loaded_ = true; - this.dispatchEvent( - new MapEvent(MapEventType.LOADEND, this, frameState) - ); - } - } else if (this.loaded_ === true) { - this.loaded_ = false; - this.dispatchEvent( - new MapEvent(MapEventType.LOADSTART, this, frameState) - ); - } - } - - const postRenderFunctions = this.postRenderFunctions_; - for (let i = 0, ii = postRenderFunctions.length; i < ii; ++i) { - postRenderFunctions[i](this, frameState); - } - postRenderFunctions.length = 0; - } - - /** - * @private - */ - handleSizeChanged_() { - if (this.getView() && !this.getView().getAnimating()) { - this.getView().resolveConstraints(0); - } - - this.render(); - } - - /** - * @private - */ - handleTargetChanged_() { - if (this.mapBrowserEventHandler_) { - for (let i = 0, ii = this.targetChangeHandlerKeys_.length; i < ii; ++i) { - unlistenByKey(this.targetChangeHandlerKeys_[i]); - } - this.targetChangeHandlerKeys_ = null; - this.viewport_.removeEventListener( - EventType.CONTEXTMENU, - this.boundHandleBrowserEvent_ - ); - this.viewport_.removeEventListener( - EventType.WHEEL, - this.boundHandleBrowserEvent_ - ); - this.mapBrowserEventHandler_.dispose(); - this.mapBrowserEventHandler_ = null; - removeNode(this.viewport_); - } - - // target may be undefined, null, a string or an Element. - // If it's a string we convert it to an Element before proceeding. - // If it's not now an Element we remove the viewport from the DOM. - // If it's an Element we append the viewport element to it. - - const targetElement = this.getTargetElement(); - if (!targetElement) { - if (this.renderer_) { - clearTimeout(this.postRenderTimeoutHandle_); - this.postRenderTimeoutHandle_ = undefined; - this.postRenderFunctions_.length = 0; - this.renderer_.dispose(); - this.renderer_ = null; - } - if (this.animationDelayKey_) { - cancelAnimationFrame(this.animationDelayKey_); - this.animationDelayKey_ = undefined; - } - } else { - targetElement.appendChild(this.viewport_); - if (!this.renderer_) { - this.renderer_ = this.createRenderer(); - } - - this.mapBrowserEventHandler_ = new MapBrowserEventHandler( - this, - this.moveTolerance_ - ); - for (const key in MapBrowserEventType) { - this.mapBrowserEventHandler_.addEventListener( - MapBrowserEventType[key], - this.handleMapBrowserEvent.bind(this) - ); - } - this.viewport_.addEventListener( - EventType.CONTEXTMENU, - this.boundHandleBrowserEvent_, - false - ); - this.viewport_.addEventListener( - EventType.WHEEL, - this.boundHandleBrowserEvent_, - PASSIVE_EVENT_LISTENERS ? {passive: false} : false - ); - - const defaultView = this.getOwnerDocument().defaultView; - const keyboardEventTarget = !this.keyboardEventTarget_ - ? targetElement - : this.keyboardEventTarget_; - this.targetChangeHandlerKeys_ = [ - listen( - keyboardEventTarget, - EventType.KEYDOWN, - this.handleBrowserEvent, - this - ), - listen( - keyboardEventTarget, - EventType.KEYPRESS, - this.handleBrowserEvent, - this - ), - listen(defaultView, EventType.RESIZE, this.updateSize, this), - ]; - } - - this.updateSize(); - // updateSize calls setSize, so no need to call this.render - // ourselves here. - } - - /** - * @private - */ - handleTileChange_() { - this.render(); - } - - /** - * @private - */ - handleViewPropertyChanged_() { - this.render(); - } - - /** - * @private - */ - handleViewChanged_() { - if (this.viewPropertyListenerKey_) { - unlistenByKey(this.viewPropertyListenerKey_); - this.viewPropertyListenerKey_ = null; - } - if (this.viewChangeListenerKey_) { - unlistenByKey(this.viewChangeListenerKey_); - this.viewChangeListenerKey_ = null; - } - const view = this.getView(); - if (view) { - this.updateViewportSize_(); - - this.viewPropertyListenerKey_ = listen( - view, - ObjectEventType.PROPERTYCHANGE, - this.handleViewPropertyChanged_, - this - ); - this.viewChangeListenerKey_ = listen( - view, - EventType.CHANGE, - this.handleViewPropertyChanged_, - this - ); - - view.resolveConstraints(0); - } - this.render(); - } - - /** - * @private - */ - handleLayerGroupChanged_() { - if (this.layerGroupPropertyListenerKeys_) { - this.layerGroupPropertyListenerKeys_.forEach(unlistenByKey); - this.layerGroupPropertyListenerKeys_ = null; - } - const layerGroup = this.getLayerGroup(); - if (layerGroup) { - this.handleLayerAdd_(new GroupEvent('addlayer', layerGroup)); - this.layerGroupPropertyListenerKeys_ = [ - listen(layerGroup, ObjectEventType.PROPERTYCHANGE, this.render, this), - listen(layerGroup, EventType.CHANGE, this.render, this), - listen(layerGroup, 'addlayer', this.handleLayerAdd_, this), - listen(layerGroup, 'removelayer', this.handleLayerRemove_, this), - ]; - } - this.render(); - } - - /** - * @return {boolean} Is rendered. - */ - isRendered() { - return !!this.frameState_; - } - - /** - * Requests an immediate render in a synchronous manner. - * @api - */ - renderSync() { - if (this.animationDelayKey_) { - cancelAnimationFrame(this.animationDelayKey_); - } - this.animationDelay_(); - } - - /** - * Redraws all text after new fonts have loaded - */ - redrawText() { - const layerStates = this.getLayerGroup().getLayerStatesArray(); - for (let i = 0, ii = layerStates.length; i < ii; ++i) { - const layer = layerStates[i].layer; - if (layer.hasRenderer()) { - layer.getRenderer().handleFontsChanged(); - } - } - } - - /** - * Request a map rendering (at the next animation frame). - * @api - */ - render() { - if (this.renderer_ && this.animationDelayKey_ === undefined) { - this.animationDelayKey_ = requestAnimationFrame(this.animationDelay_); - } - } - - /** - * Remove the given control from the map. - * @param {import("./control/Control.js").default} control Control. - * @return {import("./control/Control.js").default|undefined} The removed control (or undefined - * if the control was not found). - * @api - */ - removeControl(control) { - return this.getControls().remove(control); - } - - /** - * Remove the given interaction from the map. - * @param {import("./interaction/Interaction.js").default} interaction Interaction to remove. - * @return {import("./interaction/Interaction.js").default|undefined} The removed interaction (or - * undefined if the interaction was not found). - * @api - */ - removeInteraction(interaction) { - return this.getInteractions().remove(interaction); - } - - /** - * Removes the given layer from the map. - * @param {import("./layer/Base.js").default} layer Layer. - * @return {import("./layer/Base.js").default|undefined} The removed layer (or undefined if the - * layer was not found). - * @api - */ - removeLayer(layer) { - const layers = this.getLayerGroup().getLayers(); - return layers.remove(layer); - } - - /** - * @param {import("./layer/Group.js").GroupEvent} event The layer remove event. - * @private - */ - handleLayerRemove_(event) { - removeLayerMapProperty(event.layer); - } - - /** - * Remove the given overlay from the map. - * @param {import("./Overlay.js").default} overlay Overlay. - * @return {import("./Overlay.js").default|undefined} The removed overlay (or undefined - * if the overlay was not found). - * @api - */ - removeOverlay(overlay) { - return this.getOverlays().remove(overlay); - } - - /** - * @param {number} time Time. - * @private - */ - renderFrame_(time) { - const size = this.getSize(); - const view = this.getView(); - const previousFrameState = this.frameState_; - /** @type {?FrameState} */ - let frameState = null; - if (size !== undefined && hasArea(size) && view && view.isDef()) { - const viewHints = view.getHints( - this.frameState_ ? this.frameState_.viewHints : undefined - ); - const viewState = view.getState(); - frameState = { - animate: false, - coordinateToPixelTransform: this.coordinateToPixelTransform_, - declutterTree: null, - extent: getForViewAndSize( - viewState.center, - viewState.resolution, - viewState.rotation, - size - ), - index: this.frameIndex_++, - layerIndex: 0, - layerStatesArray: this.getLayerGroup().getLayerStatesArray(), - pixelRatio: this.pixelRatio_, - pixelToCoordinateTransform: this.pixelToCoordinateTransform_, - postRenderFunctions: [], - size: size, - tileQueue: this.tileQueue_, - time: time, - usedTiles: {}, - viewState: viewState, - viewHints: viewHints, - wantedTiles: {}, - mapId: getUid(this), - renderTargets: {}, - }; - if (viewState.nextCenter && viewState.nextResolution) { - const rotation = isNaN(viewState.nextRotation) - ? viewState.rotation - : viewState.nextRotation; - - frameState.nextExtent = getForViewAndSize( - viewState.nextCenter, - viewState.nextResolution, - rotation, - size - ); - } - } - - this.frameState_ = frameState; - /** @type {import("./renderer/Map.js").default} */ ( - this.renderer_ - ).renderFrame(frameState); - - if (frameState) { - if (frameState.animate) { - this.render(); - } - Array.prototype.push.apply( - this.postRenderFunctions_, - frameState.postRenderFunctions - ); - - if (previousFrameState) { - const moveStart = - !this.previousExtent_ || - (!isEmpty(this.previousExtent_) && - !equals(frameState.extent, this.previousExtent_)); - if (moveStart) { - this.dispatchEvent( - new MapEvent(MapEventType.MOVESTART, this, previousFrameState) - ); - this.previousExtent_ = createOrUpdateEmpty(this.previousExtent_); - } - } - - const idle = - this.previousExtent_ && - !frameState.viewHints[ViewHint.ANIMATING] && - !frameState.viewHints[ViewHint.INTERACTING] && - !equals(frameState.extent, this.previousExtent_); - - if (idle) { - this.dispatchEvent( - new MapEvent(MapEventType.MOVEEND, this, frameState) - ); - clone(frameState.extent, this.previousExtent_); - } - } - - this.dispatchEvent(new MapEvent(MapEventType.POSTRENDER, this, frameState)); - - this.renderComplete_ = - this.hasListener(MapEventType.LOADSTART) || - this.hasListener(MapEventType.LOADEND) || - this.hasListener(RenderEventType.RENDERCOMPLETE) - ? !this.tileQueue_.getTilesLoading() && - !this.tileQueue_.getCount() && - !this.getLoadingOrNotReady() - : undefined; - - if (!this.postRenderTimeoutHandle_) { - this.postRenderTimeoutHandle_ = setTimeout(() => { - this.postRenderTimeoutHandle_ = undefined; - this.handlePostRender(); - }, 0); - } - } - - /** - * Sets the layergroup of this map. - * @param {LayerGroup} layerGroup A layer group containing the layers in this map. - * @observable - * @api - */ - setLayerGroup(layerGroup) { - const oldLayerGroup = this.getLayerGroup(); - if (oldLayerGroup) { - this.handleLayerRemove_(new GroupEvent('removelayer', oldLayerGroup)); - } - this.set(MapProperty.LAYERGROUP, layerGroup); - } - - /** - * Set the size of this map. - * @param {import("./size.js").Size|undefined} size The size in pixels of the map in the DOM. - * @observable - * @api - */ - setSize(size) { - this.set(MapProperty.SIZE, size); - } - - /** - * Set the target element to render this map into. - * @param {HTMLElement|string} [target] The Element or id of the Element - * that the map is rendered in. - * @observable - * @api - */ - setTarget(target) { - this.set(MapProperty.TARGET, target); - } - - /** - * Set the view for this map. - * @param {View|Promise} view The view that controls this map. - * It is also possible to pass a promise that resolves to options for constructing a view. This - * alternative allows view properties to be resolved by sources or other components that load - * view-related metadata. - * @observable - * @api - */ - setView(view) { - if (!view || view instanceof View) { - this.set(MapProperty.VIEW, view); - return; - } - this.set(MapProperty.VIEW, new View()); - - const map = this; - view.then(function (viewOptions) { - map.setView(new View(viewOptions)); - }); - } - - /** - * Force a recalculation of the map viewport size. This should be called when - * third-party code changes the size of the map viewport. - * @api - */ - updateSize() { - const targetElement = this.getTargetElement(); - - let size = undefined; - if (targetElement) { - const computedStyle = getComputedStyle(targetElement); - const width = - targetElement.offsetWidth - - parseFloat(computedStyle['borderLeftWidth']) - - parseFloat(computedStyle['paddingLeft']) - - parseFloat(computedStyle['paddingRight']) - - parseFloat(computedStyle['borderRightWidth']); - const height = - targetElement.offsetHeight - - parseFloat(computedStyle['borderTopWidth']) - - parseFloat(computedStyle['paddingTop']) - - parseFloat(computedStyle['paddingBottom']) - - parseFloat(computedStyle['borderBottomWidth']); - if (!isNaN(width) && !isNaN(height)) { - size = [width, height]; - if ( - !hasArea(size) && - !!( - targetElement.offsetWidth || - targetElement.offsetHeight || - targetElement.getClientRects().length - ) - ) { - // eslint-disable-next-line - console.warn( - "No map visible because the map container's width or height are 0." - ); - } - } - } - - this.setSize(size); - this.updateViewportSize_(); - } - - /** - * Recomputes the viewport size and save it on the view object (if any) - * @private - */ - updateViewportSize_() { - const view = this.getView(); - if (view) { - let size = undefined; - const computedStyle = getComputedStyle(this.viewport_); - if (computedStyle.width && computedStyle.height) { - size = [ - parseInt(computedStyle.width, 10), - parseInt(computedStyle.height, 10), - ]; - } - view.setViewportSize(size); - } - } -} - -/** - * @param {MapOptions} options Map options. - * @return {MapOptionsInternal} Internal map options. - */ -function createOptionsInternal(options) { - /** - * @type {HTMLElement|Document} - */ - let keyboardEventTarget = null; - if (options.keyboardEventTarget !== undefined) { - keyboardEventTarget = - typeof options.keyboardEventTarget === 'string' - ? document.getElementById(options.keyboardEventTarget) - : options.keyboardEventTarget; - } - - /** - * @type {Object} - */ - const values = {}; - - const layerGroup = - options.layers && - typeof (/** @type {?} */ (options.layers).getLayers) === 'function' - ? /** @type {LayerGroup} */ (options.layers) - : new LayerGroup({ - layers: - /** @type {Collection|Array} */ ( - options.layers - ), - }); - values[MapProperty.LAYERGROUP] = layerGroup; - - values[MapProperty.TARGET] = options.target; - - values[MapProperty.VIEW] = - options.view instanceof View ? options.view : new View(); - - /** @type {Collection} */ - let controls; - if (options.controls !== undefined) { - if (Array.isArray(options.controls)) { - controls = new Collection(options.controls.slice()); - } else { - assert( - typeof (/** @type {?} */ (options.controls).getArray) === 'function', - 47 - ); // Expected `controls` to be an array or an `import("./Collection.js").Collection` - controls = options.controls; - } - } - - /** @type {Collection} */ - let interactions; - if (options.interactions !== undefined) { - if (Array.isArray(options.interactions)) { - interactions = new Collection(options.interactions.slice()); - } else { - assert( - typeof (/** @type {?} */ (options.interactions).getArray) === - 'function', - 48 - ); // Expected `interactions` to be an array or an `import("./Collection.js").Collection` - interactions = options.interactions; - } - } - - /** @type {Collection} */ - let overlays; - if (options.overlays !== undefined) { - if (Array.isArray(options.overlays)) { - overlays = new Collection(options.overlays.slice()); - } else { - assert( - typeof (/** @type {?} */ (options.overlays).getArray) === 'function', - 49 - ); // Expected `overlays` to be an array or an `import("./Collection.js").Collection` - overlays = options.overlays; - } - } else { - overlays = new Collection(); - } - - return { - controls: controls, - interactions: interactions, - keyboardEventTarget: keyboardEventTarget, - overlays: overlays, - values: values, - }; -} -export default PluggableMap; diff --git a/src/ol/TileQueue.js b/src/ol/TileQueue.js index 523c63e58e..e50d3d5f14 100644 --- a/src/ol/TileQueue.js +++ b/src/ol/TileQueue.js @@ -126,7 +126,7 @@ class TileQueue extends PriorityQueue { export default TileQueue; /** - * @param {import('./PluggableMap.js').FrameState} frameState Frame state. + * @param {import('./Map.js').FrameState} frameState Frame state. * @param {import("./Tile.js").default} tile Tile. * @param {string} tileSourceKey Tile source key. * @param {import("./coordinate.js").Coordinate} tileCenter Tile center. diff --git a/src/ol/control/Attribution.js b/src/ol/control/Attribution.js index 03de9d15f6..01ac8d3bed 100644 --- a/src/ol/control/Attribution.js +++ b/src/ol/control/Attribution.js @@ -186,7 +186,7 @@ class Attribution extends Control { /** * Collect a list of visible attributions and set the collapsible state. - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. * @return {Array} Attributions. * @private */ @@ -253,7 +253,7 @@ class Attribution extends Control { /** * @private - * @param {?import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {?import("../Map.js").FrameState} frameState Frame state. */ updateElement_(frameState) { if (!frameState) { diff --git a/src/ol/control/Control.js b/src/ol/control/Control.js index 2dde885ae8..a0208a72ae 100644 --- a/src/ol/control/Control.js +++ b/src/ol/control/Control.js @@ -69,7 +69,7 @@ class Control extends BaseObject { /** * @private - * @type {import("../PluggableMap.js").default|null} + * @type {import("../Map.js").default|null} */ this.map_ = null; @@ -98,7 +98,7 @@ class Control extends BaseObject { /** * Get the map associated with this control. - * @return {import("../PluggableMap.js").default|null} Map. + * @return {import("../Map.js").default|null} Map. * @api */ getMap() { @@ -110,7 +110,7 @@ class Control extends BaseObject { * Pass `null` to just remove the control from the current map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default|null} map Map. + * @param {import("../Map.js").default|null} map Map. * @api */ setMap(map) { diff --git a/src/ol/control/FullScreen.js b/src/ol/control/FullScreen.js index 5d86589964..1cc47c83f3 100644 --- a/src/ol/control/FullScreen.js +++ b/src/ol/control/FullScreen.js @@ -285,7 +285,7 @@ class FullScreen extends Control { * Pass `null` to just remove the control from the current map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default|null} map Map. + * @param {import("../Map.js").default|null} map Map. * @api */ setMap(map) { diff --git a/src/ol/control/MousePosition.js b/src/ol/control/MousePosition.js index 9bd6a95355..a799a306ae 100644 --- a/src/ol/control/MousePosition.js +++ b/src/ol/control/MousePosition.js @@ -188,7 +188,7 @@ class MousePosition extends Control { * Pass `null` to just remove the control from the current map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default|null} map Map. + * @param {import("../Map.js").default|null} map Map. * @api */ setMap(map) { diff --git a/src/ol/control/OverviewMap.js b/src/ol/control/OverviewMap.js index 767dbdd8a1..2f5523eaab 100644 --- a/src/ol/control/OverviewMap.js +++ b/src/ol/control/OverviewMap.js @@ -1,14 +1,14 @@ /** * @module ol/control/OverviewMap */ -import CompositeMapRenderer from '../renderer/Composite.js'; +import Collection from '../Collection.js'; import Control from './Control.js'; import EventType from '../events/EventType.js'; +import Map from '../Map.js'; import MapEventType from '../MapEventType.js'; import MapProperty from '../MapProperty.js'; import ObjectEventType from '../ObjectEventType.js'; import Overlay from '../Overlay.js'; -import PluggableMap from '../PluggableMap.js'; import View from '../View.js'; import ViewProperty from '../ViewProperty.js'; import {CLASS_COLLAPSED, CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js'; @@ -37,12 +37,6 @@ const MAX_RATIO = 0.75; */ const MIN_RATIO = 0.1; -class ControlledMap extends PluggableMap { - createRenderer() { - return new CompositeMapRenderer(this); - } -} - /** * @typedef {Object} Options * @property {string} [className='ol-overviewmap'] CSS class name. @@ -179,14 +173,17 @@ class OverviewMap extends Control { */ this.view_ = options.view; + const ovmap = new Map({ + view: options.view, + controls: new Collection(), + interactions: new Collection(), + }); + /** - * @type {ControlledMap} + * @type {Map} * @private */ - this.ovmap_ = new ControlledMap({ - view: options.view, - }); - const ovmap = this.ovmap_; + this.ovmap_ = ovmap; if (options.layers) { options.layers.forEach(function (layer) { @@ -269,7 +266,7 @@ class OverviewMap extends Control { * Pass `null` to just remove the control from the current map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default|null} map Map. + * @param {import("../Map.js").default|null} map Map. * @api */ setMap(map) { @@ -661,7 +658,7 @@ class OverviewMap extends Control { /** * Return the overview map. - * @return {import("../PluggableMap.js").default} Overview map. + * @return {import("../Map.js").default} Overview map. * @api */ getOverviewMap() { diff --git a/src/ol/control/ZoomSlider.js b/src/ol/control/ZoomSlider.js index c86a58f9b5..282462152c 100644 --- a/src/ol/control/ZoomSlider.js +++ b/src/ol/control/ZoomSlider.js @@ -164,7 +164,7 @@ class ZoomSlider extends Control { * Pass `null` to just remove the control from the current map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default|null} map Map. + * @param {import("../Map.js").default|null} map Map. * @api */ setMap(map) { diff --git a/src/ol/index.js b/src/ol/index.js index f23e730334..a9f256299a 100644 --- a/src/ol/index.js +++ b/src/ol/index.js @@ -20,7 +20,6 @@ export {default as MapEvent} from './MapEvent.js'; export {default as Object} from './Object.js'; export {default as Observable} from './Observable.js'; export {default as Overlay} from './Overlay.js'; -export {default as PluggableMap} from './PluggableMap.js'; export {default as Tile} from './Tile.js'; export {default as TileCache} from './TileCache.js'; export {default as TileQueue} from './TileQueue.js'; diff --git a/src/ol/interaction/DragAndDrop.js b/src/ol/interaction/DragAndDrop.js index 1d47ba448c..2c6a4d964f 100644 --- a/src/ol/interaction/DragAndDrop.js +++ b/src/ol/interaction/DragAndDrop.js @@ -254,7 +254,7 @@ class DragAndDrop extends Interaction { * Remove the interaction from its current map and attach it to the new map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. */ setMap(map) { this.unregisterListeners_(); diff --git a/src/ol/interaction/Draw.js b/src/ol/interaction/Draw.js index 5edd39a0a5..4ce2946522 100644 --- a/src/ol/interaction/Draw.js +++ b/src/ol/interaction/Draw.js @@ -521,7 +521,7 @@ class Draw extends PointerInteraction { * Remove the interaction from its current map and attach it to the new map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. */ setMap(map) { super.setMap(map); diff --git a/src/ol/interaction/Extent.js b/src/ol/interaction/Extent.js index 4670d72a4d..03429a65ed 100644 --- a/src/ol/interaction/Extent.js +++ b/src/ol/interaction/Extent.js @@ -211,7 +211,7 @@ class Extent extends PointerInteraction { /** * @param {import("../pixel.js").Pixel} pixel cursor location - * @param {import("../PluggableMap.js").default} map map + * @param {import("../Map.js").default} map map * @return {import("../coordinate.js").Coordinate|null} snapped vertex on extent * @private */ @@ -424,7 +424,7 @@ class Extent extends PointerInteraction { * Remove the interaction from its current map and attach it to the new map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. */ setMap(map) { this.extentOverlay_.setMap(map); diff --git a/src/ol/interaction/Interaction.js b/src/ol/interaction/Interaction.js index be6f4e41e0..e54fcb6ca7 100644 --- a/src/ol/interaction/Interaction.js +++ b/src/ol/interaction/Interaction.js @@ -66,7 +66,7 @@ class Interaction extends BaseObject { /** * @private - * @type {import("../PluggableMap.js").default|null} + * @type {import("../Map.js").default|null} */ this.map_ = null; @@ -85,7 +85,7 @@ class Interaction extends BaseObject { /** * Get the map associated with this interaction. - * @return {import("../PluggableMap.js").default|null} Map. + * @return {import("../Map.js").default|null} Map. * @api */ getMap() { @@ -116,7 +116,7 @@ class Interaction extends BaseObject { * Remove the interaction from its current map and attach it to the new map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default|null} map Map. + * @param {import("../Map.js").default|null} map Map. */ setMap(map) { this.map_ = map; diff --git a/src/ol/interaction/Link.js b/src/ol/interaction/Link.js index 0395f66f96..95bea6a106 100644 --- a/src/ol/interaction/Link.js +++ b/src/ol/interaction/Link.js @@ -164,7 +164,7 @@ class Link extends Interaction { } /** - * @param {import("../PluggableMap.js").default|null} map Map. + * @param {import("../Map.js").default|null} map Map. */ setMap(map) { const oldMap = this.getMap(); @@ -183,7 +183,7 @@ class Link extends Interaction { } /** - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. * @private */ registerListeners_(map) { @@ -199,7 +199,7 @@ class Link extends Interaction { } /** - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. * @private */ unregisterListeners_(map) { diff --git a/src/ol/interaction/Modify.js b/src/ol/interaction/Modify.js index 4fccb73ab3..f53913914b 100644 --- a/src/ol/interaction/Modify.js +++ b/src/ol/interaction/Modify.js @@ -538,7 +538,7 @@ class Modify extends PointerInteraction { * Remove the interaction from its current map and attach it to the new map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. */ setMap(map) { this.overlay_.setMap(map); @@ -1158,7 +1158,7 @@ class Modify extends PointerInteraction { /** * @param {import("../pixel.js").Pixel} pixel Pixel - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. * @param {import("../coordinate.js").Coordinate} [opt_coordinate] The pixel Coordinate. * @private */ diff --git a/src/ol/interaction/MouseWheelZoom.js b/src/ol/interaction/MouseWheelZoom.js index 81c638dca9..a3fc89fb87 100644 --- a/src/ol/interaction/MouseWheelZoom.js +++ b/src/ol/interaction/MouseWheelZoom.js @@ -254,7 +254,7 @@ class MouseWheelZoom extends Interaction { /** * @private - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. */ handleWheelZoom_(map) { const view = map.getView(); diff --git a/src/ol/interaction/Select.js b/src/ol/interaction/Select.js index 6efee1180f..5c53cf7e50 100644 --- a/src/ol/interaction/Select.js +++ b/src/ol/interaction/Select.js @@ -332,7 +332,7 @@ class Select extends Interaction { /** * Remove the interaction from its current map, if any, and attach it to a new * map, if any. Pass `null` to just remove the interaction from the current map. - * @param {import("../PluggableMap.js").default|null} map Map. + * @param {import("../Map.js").default|null} map Map. * @api */ setMap(map) { diff --git a/src/ol/interaction/Snap.js b/src/ol/interaction/Snap.js index 794a9ce6fa..e7129628d1 100644 --- a/src/ol/interaction/Snap.js +++ b/src/ol/interaction/Snap.js @@ -368,7 +368,7 @@ class Snap extends PointerInteraction { * Remove the interaction from its current map and attach it to the new map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. */ setMap(map) { const currentMap = this.getMap(); @@ -423,7 +423,7 @@ class Snap extends PointerInteraction { /** * @param {import("../pixel.js").Pixel} pixel Pixel * @param {import("../coordinate.js").Coordinate} pixelCoordinate Coordinate - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. * @return {Result|null} Snap result */ snapTo(pixel, pixelCoordinate, map) { diff --git a/src/ol/interaction/Translate.js b/src/ol/interaction/Translate.js index 4cb7a43d4b..c60ce44307 100644 --- a/src/ol/interaction/Translate.js +++ b/src/ol/interaction/Translate.js @@ -336,7 +336,7 @@ class Translate extends PointerInteraction { * Tests to see if the given coordinates intersects any of our selected * features. * @param {import("../pixel.js").Pixel} pixel Pixel coordinate to test for intersection. - * @param {import("../PluggableMap.js").default} map Map to test the intersection on. + * @param {import("../Map.js").default} map Map to test the intersection on. * @return {import("../Feature.js").default} Returns the feature found at the specified pixel * coordinates. * @private @@ -381,7 +381,7 @@ class Translate extends PointerInteraction { * Remove the interaction from its current map and attach it to the new map. * Subclasses may set up event handlers to get notified about changes to * the map here. - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. */ setMap(map) { const oldMap = this.getMap(); @@ -397,7 +397,7 @@ class Translate extends PointerInteraction { } /** - * @param {import("../PluggableMap.js").default} oldMap Old map. + * @param {import("../Map.js").default} oldMap Old map. * @private */ updateState_(oldMap) { diff --git a/src/ol/layer/BaseImage.js b/src/ol/layer/BaseImage.js index e2eeec1682..9b9b3a836d 100644 --- a/src/ol/layer/BaseImage.js +++ b/src/ol/layer/BaseImage.js @@ -23,10 +23,10 @@ import Layer from './Layer.js'; * visible. * @property {number} [maxZoom] The maximum view zoom level (inclusive) at 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 + * @property {import("../Map.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 import("../PluggableMap.js").default#addLayer map.addLayer()}. + * use {@link import("../Map.js").default#addLayer map.addLayer()}. * @property {ImageSourceType} [source] Source for this layer. * @property {Object} [properties] Arbitrary observable properties. Can be accessed with `#get()` and `#set()`. */ diff --git a/src/ol/layer/BaseTile.js b/src/ol/layer/BaseTile.js index b8f872b99c..41fbd27e10 100644 --- a/src/ol/layer/BaseTile.js +++ b/src/ol/layer/BaseTile.js @@ -37,10 +37,10 @@ import TileProperty from './TileProperty.js'; * @property {number} [preload=0] Preload. Load low-resolution tiles up to `preload` levels. `0` * means no preloading. * @property {TileSourceType} [source] Source for this layer. - * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage + * @property {import("../Map.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 import("../PluggableMap.js").default#addLayer map.addLayer()}. + * use {@link import("../Map.js").default#addLayer map.addLayer()}. * @property {boolean} [useInterimTilesOnError=true] Use interim tiles on error. * @property {Object} [properties] Arbitrary observable properties. Can be accessed with `#get()` and `#set()`. */ diff --git a/src/ol/layer/BaseVector.js b/src/ol/layer/BaseVector.js index c104cdb518..320b8b2f4c 100644 --- a/src/ol/layer/BaseVector.js +++ b/src/ol/layer/BaseVector.js @@ -36,10 +36,10 @@ import {toStyle} from '../style/flat.js'; * 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 {VectorSourceType} [source] Source. - * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage + * @property {import("../Map.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 import("../PluggableMap.js").default#addLayer map.addLayer()}. + * use [map.addLayer()]{@link import("../Map.js").default#addLayer}. * @property {boolean} [declutter=false] Declutter images and text. Decluttering is applied to all * image and text styles of all Vector and VectorTile layers that have set this to `true`. The priority * is defined by the z-index of the layer, the `zIndex` of the style and the render order of features. @@ -161,8 +161,8 @@ class BaseVectorLayer extends Layer { * when a hit was detected, or it will be empty. * * The hit detection algorithm used for this method is optimized for performance, but is less - * accurate than the one used in {@link import("../PluggableMap.js").default#getFeaturesAtPixel}: Text - * is not considered, and icons are only represented by their bounding box instead of the exact + * accurate than the one used in [map.getFeaturesAtPixel()]{@link import("../Map.js").default#getFeaturesAtPixel}. + * Text is not considered, and icons are only represented by their bounding box instead of the exact * image. * * @param {import("../pixel.js").Pixel} pixel Pixel. @@ -227,7 +227,7 @@ class BaseVectorLayer extends Layer { /** * Render declutter items for this layer - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. */ renderDeclutter(frameState) { if (!frameState.declutterTree) { diff --git a/src/ol/layer/Layer.js b/src/ol/layer/Layer.js index d77041cf5a..2f2b2d70af 100644 --- a/src/ol/layer/Layer.js +++ b/src/ol/layer/Layer.js @@ -9,7 +9,7 @@ import {assert} from '../asserts.js'; import {listen, unlistenByKey} from '../events.js'; /** - * @typedef {function(import("../PluggableMap.js").FrameState):HTMLElement} RenderFunction + * @typedef {function(import("../Map.js").FrameState):HTMLElement} RenderFunction */ /*** @@ -45,7 +45,7 @@ import {listen, unlistenByKey} from '../events.js'; * @property {SourceType} [source] Source for this layer. If not provided to the constructor, * the source can be set by calling {@link module:ol/layer/Layer~Layer#setSource layer.setSource(source)} after * construction. - * @property {import("../PluggableMap.js").default|null} [map] Map. + * @property {import("../Map.js").default|null} [map] Map. * @property {RenderFunction} [render] Render function. Takes the frame state as input and is expected to return an * HTML element. Will overwrite the default rendering for the layer. * @property {Object} [properties] Arbitrary observable properties. Can be accessed with `#get()` and `#set()`. @@ -75,10 +75,10 @@ import {listen, unlistenByKey} from '../events.js'; * Layers group together those properties that pertain to how the data is to be * displayed, irrespective of the source of that data. * - * Layers are usually added to a map with {@link import("../PluggableMap.js").default#addLayer map.addLayer()}. Components - * like {@link module:ol/interaction/Draw~Draw} use unmanaged layers + * Layers are usually added to a map with [map.addLayer()]{@link import("../Map.js").default#addLayer}. + * Components like {@link module:ol/interaction/Draw~Draw} use unmanaged layers * internally. These unmanaged layers are associated with the map using - * {@link module:ol/layer/Layer~Layer#setMap} instead. + * [layer.setMap()]{@link module:ol/layer/Layer~Layer#setMap} instead. * * A generic `change` event is fired when the state of the source changes. * @@ -262,7 +262,7 @@ class Layer extends BaseLayer { /** * In charge to manage the rendering of the layer. One layer type is * bounded with one layer renderer. - * @param {?import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {?import("../Map.js").FrameState} frameState Frame state. * @param {HTMLElement} target Target which the renderer may (but need not) use * for rendering its content. * @return {HTMLElement} The rendered element. @@ -285,7 +285,7 @@ class Layer extends BaseLayer { /** * For use inside the library only. - * @param {import("../PluggableMap.js").default|null} map Map. + * @param {import("../Map.js").default|null} map Map. */ setMapInternal(map) { if (!map) { @@ -296,7 +296,7 @@ class Layer extends BaseLayer { /** * For use inside the library only. - * @return {import("../PluggableMap.js").default|null} Map. + * @return {import("../Map.js").default|null} Map. */ getMapInternal() { return this.get(LayerProperty.MAP); @@ -310,7 +310,7 @@ class Layer extends BaseLayer { * * To add the layer to a map and have it managed by the map, use * {@link module:ol/Map~Map#addLayer} instead. - * @param {import("../PluggableMap.js").default|null} map Map. + * @param {import("../Map.js").default|null} map Map. * @api */ setMap(map) { diff --git a/src/ol/layer/MapboxVector.js b/src/ol/layer/MapboxVector.js index 9c151f7d5a..a7dc60233c 100644 --- a/src/ol/layer/MapboxVector.js +++ b/src/ol/layer/MapboxVector.js @@ -88,10 +88,10 @@ class ErrorEvent extends BaseEvent { * * `'vector'`: Everything is rendered as vectors. Use this mode for improved performance on vector * tile layers with only a few rendered features (e.g. for highlighting a subset of features of * another layer with the same source). - * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage + * @property {import("../Map.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 import("../PluggableMap.js").default#addLayer map.addLayer()}. + * use [map.addLayer()]{@link import("../Map.js").default#addLayer}. * @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 diff --git a/src/ol/layer/VectorImage.js b/src/ol/layer/VectorImage.js index fe30cf6200..7dfe83aa59 100644 --- a/src/ol/layer/VectorImage.js +++ b/src/ol/layer/VectorImage.js @@ -31,10 +31,10 @@ import CanvasVectorImageLayerRenderer from '../renderer/canvas/VectorImageLayer. * 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 {VectorSourceType} [source] Source. - * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage + * @property {import("../Map.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 import("../PluggableMap.js").default#addLayer map.addLayer()}. + * use [map.addLayer()]{@link import("../Map.js").default#addLayer}. * @property {boolean} [declutter=false] Declutter images and text on this layer. The priority is defined * by the `zIndex` of the style and the render order of features. Higher z-index means higher priority. * Within the same z-index, a feature rendered before another has higher priority. diff --git a/src/ol/layer/VectorTile.js b/src/ol/layer/VectorTile.js index eed3e67d3a..44103f94c5 100644 --- a/src/ol/layer/VectorTile.js +++ b/src/ol/layer/VectorTile.js @@ -55,10 +55,10 @@ import {assert} from '../asserts.js'; * tile layers with only a few rendered features (e.g. for highlighting a subset of features of * another layer with the same source). * @property {import("../source/VectorTile.js").default} [source] Source. - * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage + * @property {import("../Map.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 import("../PluggableMap.js").default#addLayer map.addLayer()}. + * use [map.addLayer()]{@link import("../Map.js").default#addLayer}. * @property {boolean} [declutter=false] Declutter images and text. Decluttering is applied to all * image and text styles of all Vector and VectorTile layers that have set this to `true`. The priority * is defined by the z-index of the layer, the `zIndex` of the style and the render order of features. @@ -171,8 +171,8 @@ class VectorTileLayer extends BaseVectorLayer { * when a hit was detected, or it will be empty. * * The hit detection algorithm used for this method is optimized for performance, but is less - * accurate than the one used in {@link import("../PluggableMap.js").default#getFeaturesAtPixel map.getFeaturesAtPixel()}: Text - * is not considered, and icons are only represented by their bounding box instead of the exact + * accurate than the one used in [map.getFeaturesAtPixel()]{@link import("../Map.js").default#getFeaturesAtPixel}. + * Text is not considered, and icons are only represented by their bounding box instead of the exact * image. * * @param {import("../pixel.js").Pixel} pixel Pixel. diff --git a/src/ol/layer/WebGLTile.js b/src/ol/layer/WebGLTile.js index a35d518bb1..8fbee47399 100644 --- a/src/ol/layer/WebGLTile.js +++ b/src/ol/layer/WebGLTile.js @@ -68,7 +68,7 @@ import { * expects an extent and a resolution (in view projection units per pixel) and returns an array of sources. See * {@link module:ol/source.sourcesFromTileGrid} for a helper function to generate sources that are organized in a * pyramid following the same pattern as a tile grid. **Note:** All sources must have the same band count and content. - * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage + * @property {import("../Map.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~Map#addLayer}. @@ -422,7 +422,7 @@ class WebGLTileLayer extends BaseTileLayer { } /** - * @param {import("../PluggableMap").FrameState} frameState Frame state. + * @param {import("../Map").FrameState} frameState Frame state. * @param {Array} sources Sources. * @return {HTMLElement} Canvas. */ @@ -439,7 +439,7 @@ class WebGLTileLayer extends BaseTileLayer { } /** - * @param {?import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {?import("../Map.js").FrameState} frameState Frame state. * @param {HTMLElement} target Target which the renderer may (but need not) use * for rendering its content. * @return {HTMLElement} The rendered element. diff --git a/src/ol/render/Box.js b/src/ol/render/Box.js index d09fb0b99f..f2fc4d94a2 100644 --- a/src/ol/render/Box.js +++ b/src/ol/render/Box.js @@ -29,7 +29,7 @@ class RenderBox extends Disposable { /** * @private - * @type {import("../PluggableMap.js").default|null} + * @type {import("../Map.js").default|null} */ this.map_ = null; @@ -68,7 +68,7 @@ class RenderBox extends Disposable { } /** - * @param {import("../PluggableMap.js").default|null} map Map. + * @param {import("../Map.js").default|null} map Map. */ setMap(map) { if (this.map_) { diff --git a/src/ol/render/Event.js b/src/ol/render/Event.js index ddccd6adac..a1e24aefe3 100644 --- a/src/ol/render/Event.js +++ b/src/ol/render/Event.js @@ -9,7 +9,7 @@ class RenderEvent extends Event { * @param {import("./EventType.js").default} type Type. * @param {import("../transform.js").Transform} [opt_inversePixelTransform] Transform for * CSS pixels to rendered pixels. - * @param {import("../PluggableMap.js").FrameState} [opt_frameState] Frame state. + * @param {import("../Map.js").FrameState} [opt_frameState] Frame state. * @param {?(CanvasRenderingContext2D|WebGLRenderingContext)} [opt_context] Context. */ constructor(type, opt_inversePixelTransform, opt_frameState, opt_context) { @@ -25,7 +25,7 @@ class RenderEvent extends Event { /** * An object representing the current render frame state. - * @type {import("../PluggableMap.js").FrameState|undefined} + * @type {import("../Map.js").FrameState|undefined} * @api */ this.frameState = opt_frameState; diff --git a/src/ol/render/webgl/BatchRenderer.js b/src/ol/render/webgl/BatchRenderer.js index aae3e73733..31b43dcb17 100644 --- a/src/ol/render/webgl/BatchRenderer.js +++ b/src/ol/render/webgl/BatchRenderer.js @@ -70,7 +70,7 @@ class AbstractBatchRenderer { * Rebuild rendering instructions and webgl buffers based on the provided frame state * Note: this is a costly operation. * @param {import("./MixedGeometryBatch.js").GeometryBatch} batch Geometry batch - * @param {import("../../PluggableMap").FrameState} frameState Frame state. + * @param {import("../../Map").FrameState} frameState Frame state. * @param {import("../../geom/Geometry.js").Type} geometryType Geometry type * @param {function(): void} callback Function called once the render buffers are updated */ @@ -89,7 +89,7 @@ class AbstractBatchRenderer { * the invert transform of the webgl buffers * @param {import("./MixedGeometryBatch.js").GeometryBatch} batch Geometry batch * @param {import("../../transform.js").Transform} currentTransform Transform - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {number} offsetX X offset */ render(batch, currentTransform, frameState, offsetX) { diff --git a/src/ol/renderer/Composite.js b/src/ol/renderer/Composite.js index b4c5ed7284..8947c3655d 100644 --- a/src/ol/renderer/Composite.js +++ b/src/ol/renderer/Composite.js @@ -18,7 +18,7 @@ import {replaceChildren} from '../dom.js'; */ class CompositeMapRenderer extends MapRenderer { /** - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. */ constructor(map) { super(map); @@ -63,7 +63,7 @@ class CompositeMapRenderer extends MapRenderer { /** * @param {import("../render/EventType.js").default} type Event type. - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. */ dispatchRenderEvent(type, frameState) { const map = this.getMap(); @@ -81,7 +81,7 @@ class CompositeMapRenderer extends MapRenderer { /** * Render. - * @param {?import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {?import("../Map.js").FrameState} frameState Frame state. */ renderFrame(frameState) { if (!frameState) { diff --git a/src/ol/renderer/Layer.js b/src/ol/renderer/Layer.js index fbce025e07..da20e0b8e7 100644 --- a/src/ol/renderer/Layer.js +++ b/src/ol/renderer/Layer.js @@ -58,7 +58,7 @@ class LayerRenderer extends Observable { /** * Determine whether render should be called. * @abstract - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. */ prepareFrame(frameState) { @@ -68,7 +68,7 @@ class LayerRenderer extends Observable { /** * Render the layer. * @abstract - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. * @param {HTMLElement} target Target that may be used to render content to. * @return {HTMLElement} The rendered element. */ @@ -116,7 +116,7 @@ class LayerRenderer extends Observable { /** * @abstract * @param {import("../coordinate.js").Coordinate} coordinate Coordinate. - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. * @param {number} hitTolerance Hit tolerance in pixels. * @param {import("./vector.js").FeatureCallback} callback Feature callback. * @param {Array>} matches The hit detected matches with tolerance. diff --git a/src/ol/renderer/Map.js b/src/ol/renderer/Map.js index cff20012ab..4f4ce462d2 100644 --- a/src/ol/renderer/Map.js +++ b/src/ol/renderer/Map.js @@ -25,14 +25,14 @@ import {wrapX} from '../coordinate.js'; */ class MapRenderer extends Disposable { /** - * @param {import("../PluggableMap.js").default} map Map. + * @param {import("../Map.js").default} map Map. */ constructor(map) { super(); /** * @private - * @type {import("../PluggableMap.js").default} + * @type {import("../Map.js").default} */ this.map_ = map; } @@ -40,14 +40,14 @@ class MapRenderer extends Disposable { /** * @abstract * @param {import("../render/EventType.js").default} type Event type. - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. */ dispatchRenderEvent(type, frameState) { abstract(); } /** - * @param {import("../PluggableMap.js").FrameState} frameState FrameState. + * @param {import("../Map.js").FrameState} frameState FrameState. * @protected */ calculateMatrices2D(frameState) { @@ -71,7 +71,7 @@ class MapRenderer extends Disposable { /** * @param {import("../coordinate.js").Coordinate} coordinate Coordinate. - * @param {import("../PluggableMap.js").FrameState} frameState FrameState. + * @param {import("../Map.js").FrameState} frameState FrameState. * @param {number} hitTolerance Hit tolerance in pixels. * @param {boolean} checkWrapped Check for wrapped geometries. * @param {import("./vector.js").FeatureCallback} callback Feature callback. @@ -172,7 +172,7 @@ class MapRenderer extends Disposable { /** * @param {import("../coordinate.js").Coordinate} coordinate Coordinate. - * @param {import("../PluggableMap.js").FrameState} frameState FrameState. + * @param {import("../Map.js").FrameState} frameState FrameState. * @param {number} hitTolerance Hit tolerance in pixels. * @param {boolean} checkWrapped Check for wrapped geometries. * @param {function(this: U, import("../layer/Layer.js").default): boolean} layerFilter Layer filter @@ -206,7 +206,7 @@ class MapRenderer extends Disposable { } /** - * @return {import("../PluggableMap.js").default} Map. + * @return {import("../Map.js").default} Map. */ getMap() { return this.map_; @@ -215,14 +215,14 @@ class MapRenderer extends Disposable { /** * Render. * @abstract - * @param {?import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {?import("../Map.js").FrameState} frameState Frame state. */ renderFrame(frameState) { abstract(); } /** - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. * @protected */ scheduleExpireIconCache(frameState) { @@ -233,8 +233,8 @@ class MapRenderer extends Disposable { } /** - * @param {import("../PluggableMap.js").default} map Map. - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").default} map Map. + * @param {import("../Map.js").FrameState} frameState Frame state. */ function expireIconCache(map, frameState) { iconImageCache.expire(); diff --git a/src/ol/renderer/canvas/ImageLayer.js b/src/ol/renderer/canvas/ImageLayer.js index 9e9fb57aeb..5f53cb0cd2 100644 --- a/src/ol/renderer/canvas/ImageLayer.js +++ b/src/ol/renderer/canvas/ImageLayer.js @@ -50,7 +50,7 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer { /** * Determine whether render should be called. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. */ prepareFrame(frameState) { @@ -152,7 +152,7 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer { /** * Render the layer. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {HTMLElement} target Target that may be used to render content to. * @return {HTMLElement} The rendered element. */ diff --git a/src/ol/renderer/canvas/Layer.js b/src/ol/renderer/canvas/Layer.js index c472196adc..fcbd43a6ea 100644 --- a/src/ol/renderer/canvas/Layer.js +++ b/src/ol/renderer/canvas/Layer.js @@ -102,7 +102,7 @@ class CanvasLayerRenderer extends LayerRenderer { /** * @protected - * @type {import("../../PluggableMap.js").FrameState|null} + * @type {import("../../Map.js").FrameState|null} */ this.frameState = null; } @@ -131,7 +131,7 @@ class CanvasLayerRenderer extends LayerRenderer { } /** - * @param {import('../../PluggableMap.js').FrameState} frameState Frame state. + * @param {import('../../Map.js').FrameState} frameState Frame state. * @return {string} Background color. */ getBackground(frameState) { @@ -207,7 +207,7 @@ class CanvasLayerRenderer extends LayerRenderer { /** * @param {CanvasRenderingContext2D} context Context. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {import("../../extent.js").Extent} extent Clip extent. * @protected */ @@ -240,7 +240,7 @@ class CanvasLayerRenderer extends LayerRenderer { /** * @param {import("../../render/EventType.js").default} type Event type. * @param {CanvasRenderingContext2D} context Context. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @private */ dispatchRenderEvent_(type, context, frameState) { @@ -258,7 +258,7 @@ class CanvasLayerRenderer extends LayerRenderer { /** * @param {CanvasRenderingContext2D} context Context. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @protected */ preRender(context, frameState) { @@ -268,7 +268,7 @@ class CanvasLayerRenderer extends LayerRenderer { /** * @param {CanvasRenderingContext2D} context Context. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @protected */ postRender(context, frameState) { diff --git a/src/ol/renderer/canvas/TileLayer.js b/src/ol/renderer/canvas/TileLayer.js index 4778966b7d..dfdb48d01c 100644 --- a/src/ol/renderer/canvas/TileLayer.js +++ b/src/ol/renderer/canvas/TileLayer.js @@ -117,7 +117,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer { * @param {number} z Tile coordinate z. * @param {number} x Tile coordinate x. * @param {number} y Tile coordinate y. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {!import("../../Tile.js").default} Tile. */ getTile(z, x, y, frameState) { @@ -230,7 +230,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer { /** * Determine whether render should be called. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. */ prepareFrame(frameState) { @@ -239,7 +239,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer { /** * Render the layer. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {HTMLElement} target Target that may be used to render content to. * @return {HTMLElement} The rendered element. */ @@ -571,7 +571,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer { /** * @param {import("../../ImageTile.js").default} tile Tile. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {number} x Left of the tile. * @param {number} y Top of the tile. * @param {number} w Width of the tile. @@ -635,7 +635,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer { } /** - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {import("../../source/Tile.js").default} tileSource Tile source. * @protected */ @@ -643,8 +643,8 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer { if (tileSource.canExpireCache()) { /** * @param {import("../../source/Tile.js").default} tileSource Tile source. - * @param {import("../../PluggableMap.js").default} map Map. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").default} map Map. + * @param {import("../../Map.js").FrameState} frameState Frame state. */ const postRenderFunction = function (tileSource, map, frameState) { const tileSourceKey = getUid(tileSource); @@ -657,7 +657,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer { }.bind(null, tileSource); frameState.postRenderFunctions.push( - /** @type {import("../../PluggableMap.js").PostRenderFunction} */ ( + /** @type {import("../../Map.js").PostRenderFunction} */ ( postRenderFunction ) ); @@ -686,7 +686,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer { * - registers idle tiles in frameState.wantedTiles so that they are not * discarded by the tile queue * - enqueues missing tiles - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {import("../../source/Tile.js").default} tileSource Tile source. * @param {import("../../tilegrid/TileGrid.js").default} tileGrid Tile grid. * @param {number} pixelRatio Pixel ratio. diff --git a/src/ol/renderer/canvas/VectorImageLayer.js b/src/ol/renderer/canvas/VectorImageLayer.js index c643faf58a..2da759918a 100644 --- a/src/ol/renderer/canvas/VectorImageLayer.js +++ b/src/ol/renderer/canvas/VectorImageLayer.js @@ -81,7 +81,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer { /** * Determine whether render should be called. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. */ prepareFrame(frameState) { @@ -109,21 +109,20 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer { const layerState = frameState.layerStatesArray[frameState.layerIndex]; context.globalAlpha = layerState.opacity; const imageLayerState = Object.assign({}, layerState, {opacity: 1}); - const imageFrameState = - /** @type {import("../../PluggableMap.js").FrameState} */ ( - Object.assign({}, frameState, { - declutterTree: new RBush(9), - extent: renderedExtent, - size: [width, height], - viewState: /** @type {import("../../View.js").State} */ ( - Object.assign({}, frameState.viewState, { - rotation: 0, - }) - ), - layerStatesArray: [imageLayerState], - layerIndex: 0, - }) - ); + const imageFrameState = /** @type {import("../../Map.js").FrameState} */ ( + Object.assign({}, frameState, { + declutterTree: new RBush(9), + extent: renderedExtent, + size: [width, height], + viewState: /** @type {import("../../View.js").State} */ ( + Object.assign({}, frameState.viewState, { + rotation: 0, + }) + ), + layerStatesArray: [imageLayerState], + layerIndex: 0, + }) + ); let emptyImage = true; const image = new ImageCanvas( renderedExtent, @@ -194,7 +193,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer { /** * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {number} hitTolerance Hit tolerance in pixels. * @param {import("../vector.js").FeatureCallback} callback Feature callback. * @param {Array>} matches The hit detected matches with tolerance. diff --git a/src/ol/renderer/canvas/VectorLayer.js b/src/ol/renderer/canvas/VectorLayer.js index da5e41e56f..99e460a4ae 100644 --- a/src/ol/renderer/canvas/VectorLayer.js +++ b/src/ol/renderer/canvas/VectorLayer.js @@ -158,7 +158,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { /** * @param {ExecutorGroup} executorGroup Executor group. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {import("rbush").default} [opt_declutterTree] Declutter tree. */ renderWorlds(executorGroup, frameState, opt_declutterTree) { @@ -236,7 +236,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { /** * Render declutter items for this layer - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. */ renderDeclutter(frameState) { if (this.declutterExecutorGroup) { @@ -252,7 +252,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { /** * Render the layer. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {HTMLElement} target Target that may be used to render content to. * @return {HTMLElement} The rendered element. */ @@ -432,7 +432,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { /** * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {number} hitTolerance Hit tolerance in pixels. * @param {import("../vector.js").FeatureCallback} callback Feature callback. * @param {Array>} matches The hit detected matches with tolerance. @@ -534,7 +534,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { /** * Determine whether render should be called. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. */ prepareFrame(frameState) { diff --git a/src/ol/renderer/canvas/VectorTileLayer.js b/src/ol/renderer/canvas/VectorTileLayer.js index 660454212d..c65bcfa2d5 100644 --- a/src/ol/renderer/canvas/VectorTileLayer.js +++ b/src/ol/renderer/canvas/VectorTileLayer.js @@ -117,7 +117,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { * @param {number} z Tile coordinate z. * @param {number} x Tile coordinate x. * @param {number} y Tile coordinate y. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {!import("../../Tile.js").default} Tile. */ getTile(z, x, y, frameState) { @@ -168,7 +168,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { /** * Determine whether render should be called. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. */ prepareFrame(frameState) { @@ -321,7 +321,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { /** * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {number} hitTolerance Hit tolerance in pixels. * @param {import("../vector.js").FeatureCallback} callback Feature callback. * @param {Array>} matches The hit detected matches with tolerance. @@ -548,7 +548,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { /** * Render declutter items for this layer - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. */ renderDeclutter(frameState) { const context = this.context; @@ -618,7 +618,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { /** * Render the layer. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {HTMLElement} target Target that may be used to render content to. * @return {HTMLElement} The rendered element. */ @@ -797,7 +797,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { /** * @param {import("../../VectorRenderTile.js").default} tile Tile. - * @param {import("../../PluggableMap").FrameState} frameState Frame state. + * @param {import("../../Map").FrameState} frameState Frame state. * @private */ renderTileImage_(tile, frameState) { diff --git a/src/ol/renderer/webgl/Layer.js b/src/ol/renderer/webgl/Layer.js index 8ce020d53d..ec67f16981 100644 --- a/src/ol/renderer/webgl/Layer.js +++ b/src/ol/renderer/webgl/Layer.js @@ -81,7 +81,7 @@ class WebGLLayerRenderer extends LayerRenderer { /** * @param {WebGLRenderingContext} context The WebGL rendering context. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @protected */ dispatchPreComposeEvent(context, frameState) { @@ -99,7 +99,7 @@ class WebGLLayerRenderer extends LayerRenderer { /** * @param {WebGLRenderingContext} context The WebGL rendering context. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @protected */ dispatchPostComposeEvent(context, frameState) { @@ -138,7 +138,7 @@ class WebGLLayerRenderer extends LayerRenderer { /** * Determine whether renderFrame should be called. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. */ prepareFrame(frameState) { @@ -194,7 +194,7 @@ class WebGLLayerRenderer extends LayerRenderer { /** * Determine whether renderFrame should be called. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. * @protected */ @@ -213,7 +213,7 @@ class WebGLLayerRenderer extends LayerRenderer { /** * @param {import("../../render/EventType.js").default} type Event type. * @param {WebGLRenderingContext} context The rendering context. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @private */ dispatchRenderEvent_(type, context, frameState) { @@ -242,7 +242,7 @@ class WebGLLayerRenderer extends LayerRenderer { /** * @param {WebGLRenderingContext} context The rendering context. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @protected */ preRender(context, frameState) { @@ -251,7 +251,7 @@ class WebGLLayerRenderer extends LayerRenderer { /** * @param {WebGLRenderingContext} context The rendering context. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @protected */ postRender(context, frameState) { diff --git a/src/ol/renderer/webgl/PointsLayer.js b/src/ol/renderer/webgl/PointsLayer.js index c7eca3db00..0a1ab8f20f 100644 --- a/src/ol/renderer/webgl/PointsLayer.js +++ b/src/ol/renderer/webgl/PointsLayer.js @@ -456,7 +456,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { /** * Render the layer. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {HTMLElement} The rendered element. */ renderFrame(frameState) { @@ -512,7 +512,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { /** * Determine whether renderFrame should be called. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. */ prepareFrameInternal(frameState) { @@ -555,7 +555,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { /** * Rebuild internal webgl buffers based on current view extent; costly, should not be called too much - * @param {import("../../PluggableMap").FrameState} frameState Frame state. + * @param {import("../../Map").FrameState} frameState Frame state. * @private */ rebuildBuffers_(frameState) { @@ -672,7 +672,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { /** * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {number} hitTolerance Hit tolerance in pixels. * @param {import("../vector.js").FeatureCallback} callback Feature callback. * @param {Array>} matches The hit detected matches with tolerance. @@ -712,7 +712,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { /** * Render the hit detection data to the corresponding render target - * @param {import("../../PluggableMap.js").FrameState} frameState current frame state + * @param {import("../../Map.js").FrameState} frameState current frame state * @param {number} startWorld the world to render in the first iteration * @param {number} endWorld the last world to render * @param {number} worldWidth the width of the worlds being rendered diff --git a/src/ol/renderer/webgl/TileLayer.js b/src/ol/renderer/webgl/TileLayer.js index 836d6580de..4833fba2e6 100644 --- a/src/ol/renderer/webgl/TileLayer.js +++ b/src/ol/renderer/webgl/TileLayer.js @@ -95,7 +95,7 @@ function addTileTextureToLookup(tileTexturesByZ, tileTexture, z) { } /** - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {import("../../extent.js").Extent} extent The frame extent. * @return {import("../../extent.js").Extent} Frame extent intersected with layer extents. */ @@ -244,7 +244,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer { /** * @private - * @type {import("../../PluggableMap.js").FrameState|null} + * @type {import("../../Map.js").FrameState|null} */ this.frameState_ = null; } @@ -295,7 +295,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer { /** * Determine whether renderFrame should be called. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. */ prepareFrameInternal(frameState) { @@ -312,7 +312,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer { } /** - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {import("../../extent.js").Extent} extent The extent to be rendered. * @param {number} initialZ The zoom level. * @param {Object>} tileTexturesByZ The zoom level. @@ -412,7 +412,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer { /** * Render the layer. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {HTMLElement} The rendered element. */ renderFrame(frameState) { @@ -670,8 +670,8 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer { /** * Here we unconditionally expire the source cache since the renderer maintains * its own cache. - * @param {import("../../PluggableMap.js").default} map Map. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").default} map Map. + * @param {import("../../Map.js").FrameState} frameState Frame state. */ const postRenderFunction = function (map, frameState) { tileSource.expireCache(frameState.viewState.projection, empty); diff --git a/src/ol/renderer/webgl/VectorLayer.js b/src/ol/renderer/webgl/VectorLayer.js index bb15ce2ccd..0375f4d6a5 100644 --- a/src/ol/renderer/webgl/VectorLayer.js +++ b/src/ol/renderer/webgl/VectorLayer.js @@ -255,7 +255,7 @@ class WebGLVectorLayerRenderer extends WebGLLayerRenderer { /** * Render the layer. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {HTMLElement} The rendered element. */ renderFrame(frameState) { @@ -312,7 +312,7 @@ class WebGLVectorLayerRenderer extends WebGLLayerRenderer { /** * Determine whether renderFrame should be called. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. */ prepareFrameInternal(frameState) { @@ -375,7 +375,7 @@ class WebGLVectorLayerRenderer extends WebGLLayerRenderer { /** * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {number} hitTolerance Hit tolerance in pixels. * @param {import("../vector.js").FeatureCallback} callback Feature callback. * @param {Array>} matches The hit detected matches with tolerance. diff --git a/src/ol/source/Raster.js b/src/ol/source/Raster.js index 2a9953b387..41ad44d933 100644 --- a/src/ol/source/Raster.js +++ b/src/ol/source/Raster.js @@ -466,7 +466,7 @@ const RasterEventType = { export class RasterSourceEvent extends Event { /** * @param {string} type Type. - * @param {import("../PluggableMap.js").FrameState} frameState The frame state. + * @param {import("../Map.js").FrameState} frameState The frame state. * @param {Object|Array} data An object made available to operations. For "afteroperations" evenets * this will be an array of objects if more than one thread is used. */ @@ -600,7 +600,7 @@ class RasterSource extends ImageSource { /** * The most recently requested frame state. - * @type {import("../PluggableMap.js").FrameState} + * @type {import("../Map.js").FrameState} * @private */ this.requestedFrameState_; @@ -620,7 +620,7 @@ class RasterSource extends ImageSource { /** * @private - * @type {import("../PluggableMap.js").FrameState} + * @type {import("../Map.js").FrameState} */ this.frameState_ = { animate: false, @@ -699,11 +699,11 @@ class RasterSource extends ImageSource { * @param {import("../extent.js").Extent} extent The view extent (in map units). * @param {number} resolution The view resolution. * @param {import("../proj/Projection.js").default} projection The view projection. - * @return {import("../PluggableMap.js").FrameState} The updated frame state. + * @return {import("../Map.js").FrameState} The updated frame state. * @private */ updateFrameState_(extent, resolution, projection) { - const frameState = /** @type {import("../PluggableMap.js").FrameState} */ ( + const frameState = /** @type {import("../Map.js").FrameState} */ ( Object.assign({}, this.frameState_) ); @@ -817,7 +817,7 @@ class RasterSource extends ImageSource { /** * Called when pixel processing is complete. - * @param {import("../PluggableMap.js").FrameState} frameState The frame state. + * @param {import("../Map.js").FrameState} frameState The frame state. * @param {Error} err Any error during processing. * @param {ImageData} output The output image data. * @param {Object|Array} data The user data (or an array if more than one thread). @@ -890,7 +890,7 @@ let sharedContext = null; /** * Get image data from a layer. * @param {import("../layer/Layer.js").default} layer Layer to render. - * @param {import("../PluggableMap.js").FrameState} frameState The frame state. + * @param {import("../Map.js").FrameState} frameState The frame state. * @return {ImageData} The image data. */ function getImageData(layer, frameState) { diff --git a/src/ol/source/Source.js b/src/ol/source/Source.js index 907887145f..119682eed8 100644 --- a/src/ol/source/Source.js +++ b/src/ol/source/Source.js @@ -11,10 +11,10 @@ import {get as getProjection} from '../proj.js'; */ /** - * A function that takes a {@link module:ol/PluggableMap~FrameState} and returns a string or + * A function that takes a {@link module:ol/Map~FrameState} and returns a string or * an array of strings representing source attributions. * - * @typedef {function(import("../PluggableMap.js").FrameState): (string|Array)} Attribution + * @typedef {function(import("../Map.js").FrameState): (string|Array)} Attribution */ /** diff --git a/src/ol/webgl/Helper.js b/src/ol/webgl/Helper.js index b3c39e3a74..45a3ba79c4 100644 --- a/src/ol/webgl/Helper.js +++ b/src/ol/webgl/Helper.js @@ -82,7 +82,7 @@ export const AttributeType = { /** * Uniform value can be a number, array of numbers (2 to 4), canvas element or a callback returning * one of the previous types. - * @typedef {UniformLiteralValue|function(import("../PluggableMap.js").FrameState):UniformLiteralValue} UniformValue + * @typedef {UniformLiteralValue|function(import("../Map.js").FrameState):UniformLiteralValue} UniformValue */ /** @@ -548,7 +548,7 @@ class WebGLHelper extends Disposable { * Clear the buffer & set the viewport to draw. * Post process passes will be initialized here, the first one being bound as a render target for * subsequent draw calls. - * @param {import("../PluggableMap.js").FrameState} frameState current frame state + * @param {import("../Map.js").FrameState} frameState current frame state * @param {boolean} [opt_disableAlphaBlend] If true, no alpha blending will happen. */ prepareDraw(frameState, opt_disableAlphaBlend) { @@ -583,7 +583,7 @@ class WebGLHelper extends Disposable { * Clear the render target & bind it for future draw operations. * This is similar to `prepareDraw`, only post processes will not be applied. * Note: the whole viewport will be drawn to the render target, regardless of its size. - * @param {import("../PluggableMap.js").FrameState} frameState current frame state + * @param {import("../Map.js").FrameState} frameState current frame state * @param {import("./RenderTarget.js").default} renderTarget Render target to draw to * @param {boolean} [opt_disableAlphaBlend] If true, no alpha blending will happen. */ @@ -622,9 +622,9 @@ class WebGLHelper extends Disposable { /** * Apply the successive post process passes which will eventually render to the actual canvas. - * @param {import("../PluggableMap.js").FrameState} frameState current frame state - * @param {function(WebGLRenderingContext, import("../PluggableMap.js").FrameState):void} [preCompose] Called before composing. - * @param {function(WebGLRenderingContext, import("../PluggableMap.js").FrameState):void} [postCompose] Called before composing. + * @param {import("../Map.js").FrameState} frameState current frame state + * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [preCompose] Called before composing. + * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [postCompose] Called before composing. */ finalizeDraw(frameState, preCompose, postCompose) { // apply post processes using the next one as target @@ -662,7 +662,7 @@ class WebGLHelper extends Disposable { /** * Sets the default matrix uniforms for a given frame state. This is called internally in `prepareDraw`. - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. */ applyFrameState(frameState) { const size = frameState.size; @@ -701,7 +701,7 @@ class WebGLHelper extends Disposable { /** * Sets the custom uniforms based on what was given in the constructor. This is called internally in `prepareDraw`. - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. */ applyUniforms(frameState) { const gl = this.getGL(); @@ -794,7 +794,7 @@ class WebGLHelper extends Disposable { * Set up a program for use. The program will be set as the current one. Then, the uniforms used * in the program will be set based on the current frame state and the helper configuration. * @param {WebGLProgram} program Program. - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. */ useProgram(program, frameState) { const gl = this.getGL(); @@ -906,7 +906,7 @@ class WebGLHelper extends Disposable { /** * Modifies the given transform to apply the rotation/translation/scaling of the given frame state. * The resulting transform can be used to convert world space coordinates to view coordinates. - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. * @param {import("../transform").Transform} transform Transform to update. * @return {import("../transform").Transform} The updated transform object. */ diff --git a/src/ol/webgl/PostProcessingPass.js b/src/ol/webgl/PostProcessingPass.js index 9168ddd2ed..fba6684427 100644 --- a/src/ol/webgl/PostProcessingPass.js +++ b/src/ol/webgl/PostProcessingPass.js @@ -191,7 +191,7 @@ class WebGLPostProcessingPass { * Initialize the render target texture of the post process, make sure it is at the * right size and bind it as a render target for the next draw calls. * The last step to be initialized will be the one where the primitives are rendered. - * @param {import("../PluggableMap.js").FrameState} frameState current frame state + * @param {import("../Map.js").FrameState} frameState current frame state * @api */ init(frameState) { @@ -250,10 +250,10 @@ class WebGLPostProcessingPass { /** * Render to the next postprocessing pass (or to the canvas if final pass). - * @param {import("../PluggableMap.js").FrameState} frameState current frame state + * @param {import("../Map.js").FrameState} frameState current frame state * @param {WebGLPostProcessingPass} [nextPass] Next pass, optional - * @param {function(WebGLRenderingContext, import("../PluggableMap.js").FrameState):void} [preCompose] Called before composing. - * @param {function(WebGLRenderingContext, import("../PluggableMap.js").FrameState):void} [postCompose] Called before composing. + * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [preCompose] Called before composing. + * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [postCompose] Called before composing. * @api */ apply(frameState, nextPass, preCompose, postCompose) { @@ -325,7 +325,7 @@ class WebGLPostProcessingPass { /** * Sets the custom uniforms based on what was given in the constructor. - * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../Map.js").FrameState} frameState Frame state. * @private */ applyUniforms(frameState) { diff --git a/test/browser/spec/ol/interaction/pointer.test.js b/test/browser/spec/ol/interaction/Pointer.test.js similarity index 99% rename from test/browser/spec/ol/interaction/pointer.test.js rename to test/browser/spec/ol/interaction/Pointer.test.js index 72cc22e05c..84b1c189ef 100644 --- a/test/browser/spec/ol/interaction/pointer.test.js +++ b/test/browser/spec/ol/interaction/Pointer.test.js @@ -6,7 +6,7 @@ import OlEvent from '../../../../../src/ol/events/Event.js'; import PointerInteraction from '../../../../../src/ol/interaction/Pointer.js'; import View from '../../../../../src/ol/View.js'; -describe('ol.interaction.Pointer', function () { +describe('ol/interaction/Pointer', function () { describe('#handleEvent', function () { let event; let defaultPrevented; diff --git a/test/browser/spec/ol/layer/vectortile.test.js b/test/browser/spec/ol/layer/vectortile.test.js index c4da7dd372..4962d6e795 100644 --- a/test/browser/spec/ol/layer/vectortile.test.js +++ b/test/browser/spec/ol/layer/vectortile.test.js @@ -194,7 +194,7 @@ describe('ol.layer.VectorTile', function () { }); const renderer = layer.getRenderer(); const frameState = - /** @type {import("../../../../../src/ol/PluggableMap.js").FrameState} */ ({ + /** @type {import("../../../../../src/ol/Map.js").FrameState} */ ({ pixelRatio: 1, viewState: { zoom: zoom, diff --git a/test/browser/spec/ol/renderer/canvas/VectorLayer.test.js b/test/browser/spec/ol/renderer/canvas/VectorLayer.test.js index 1ef16454dd..8fddfe70a0 100644 --- a/test/browser/spec/ol/renderer/canvas/VectorLayer.test.js +++ b/test/browser/spec/ol/renderer/canvas/VectorLayer.test.js @@ -248,12 +248,12 @@ describe('ol/renderer/canvas/VectorLayer', function () { }); describe('#prepareFrame and #compose', function () { - /** @type {import("../../../../../../src/ol/PluggableMap").FrameState*/ let frameState; - /** @type {import("../../../../../../src/ol/extent").Extent*/ let projExtent; + /** @type {import("../../../../../../src/ol/Map").FrameState} */ let frameState; + /** @type {import("../../../../../../src/ol/extent").Extent} */ let projExtent; /** @type {CanvasVectorLayerRenderer} */ let renderer; /** @type {number} */ let worldWidth; /** @type {number} */ let buffer; - /** @type {Array*/ let loadExtents; + /** @type {Array} */ let loadExtents; function loader(extent) { loadExtents.push(extent); @@ -661,7 +661,7 @@ describe('ol/renderer/canvas/VectorLayer', function () { const projection = getProjection('EPSG:3857'); const projExtent = projection.getExtent(); const worldWidth = getWidth(projExtent); - /** @type {import("../../../../../../src/ol/PluggableMap").FrameState*/ + /** @type {import("../../../../../../src/ol/Map").FrameState} */ const frameState = { viewHints: [], pixelRatio: 1, diff --git a/test/browser/spec/ol/renderer/webgl/TileLayer.test.js b/test/browser/spec/ol/renderer/webgl/TileLayer.test.js index fc7da75410..4d8af2618b 100644 --- a/test/browser/spec/ol/renderer/webgl/TileLayer.test.js +++ b/test/browser/spec/ol/renderer/webgl/TileLayer.test.js @@ -13,7 +13,7 @@ describe('ol/renderer/webgl/TileLayer', function () { let renderer; /** @type {WebGLTileLayer} */ let tileLayer; - /** @type {import('../../../../../../src/ol/PluggableMap.js').FrameState} */ + /** @type {import('../../../../../../src/ol/Map.js').FrameState} */ let frameState; beforeEach(function () { const size = 256;