@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
264 lines (260 loc) • 12.4 kB
TypeScript
import type Point from "../../../geometry/Point.js";
import type Layer from "../../../layers/Layer.js";
import type MapView from "../../MapView.js";
import type ViewState from "../ViewState.js";
import type LayerView from "../../layers/LayerView.js";
import type { ScreenPoint } from "../../../core/types.js";
import type { ViewHit } from "../../types.js";
import type { LayerViewProperties } from "../../layers/LayerView.js";
export interface BaseLayerView2DProperties extends LayerViewProperties, Partial<Pick<BaseLayerView2D, "tiles">> {}
export interface RenderParameters {
/** The [canvas 2D context](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D) in which to draw content. */
context: CanvasRenderingContext2D;
/** The pixel ratio. */
pixelRatio: number;
/** The object that describes view state. */
state: ViewState;
/** The stationary state of the `MapView`. */
stationary: boolean;
}
/** Represents a tile reference. */
export interface Tile {
/** The tile string identifier in the format `level/row/col/world` */
id: string;
/** The level identifier of the [LOD](https://developers.arcgis.com/javascript/latest/references/core/layers/support/LOD/) to which the tile belongs */
level: number;
/** The row identifier. */
row: number;
/** The column identifier. */
col: number;
/** When the projection allows world wrapping (e.g. Web Mercator), identifies the instance of the world this tile's `level`/`row`/`col`. */
world: number;
/** The number of map units per pixel in the tile. */
resolution: number;
/** The map scale at the tile's level. */
scale: number;
/** The coordinates of the top-left corner of the tile as an array of two numbers. The coordinates are in un-normalized map units. */
coords: [
number,
number
];
/** The bounds of the tile as an array of four numbers that be readily converted to an [Extent](https://developers.arcgis.com/javascript/latest/references/core/geometry/Extent/) object. */
bounds: [
number,
number,
number,
number
];
}
/**
* Represents the [LayerView](https://developers.arcgis.com/javascript/latest/references/core/views/layers/LayerView/) of a [Layer](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/)
* after it has been added to a [Map](https://developers.arcgis.com/javascript/latest/references/core/Map/) with a [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/).
*
* This class may be extended to create a custom [LayerView](https://developers.arcgis.com/javascript/latest/references/core/views/layers/LayerView/) for a Layer.
* A [LayerView](https://developers.arcgis.com/javascript/latest/references/core/views/layers/LayerView/) is created on demand by the [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/) when a layer is
* added the to list of layers of its map.
*
* The subclass can implement multiple functions of the LayerView lifecycle. First, the [attach()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerView2D/#attach) method
* is called when the LayerView is about to start drawing the layer's content. Then during the life of the LayerView,
* the [render()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerView2D/#render) method is called during the MapView rendering phase. The `render()` method has access to a canvas 2d context
* in which it can render the content available for display. Finally the [detach()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerView2D/#detach) method is called after the layer
* is removed from the map. It releases all allocated resources and stops on-going requests.
*
* @since 4.8
* @example
* let TileBorderLayerView2D = BaseLayerView2D.createSubclass({
* // Example of a render implementation that draws tile boundaries
* render(renderParameters) {
* let tileSize = this.layer.tileInfo.size[0];
* let state = renderParameters.state;
* let pixelRatio = state.pixelRatio;
* let width = state.size[0];
* let height = state.size[1];
* let context = renderParameters.context;
* let coords = [0, 0];
*
* context.fillStyle = "rgba(0,0,0,0.25)";
* context.fillRect(0, 0, width * pixelRatio, height * pixelRatio);
*
* // apply rotation for everything that will be applied to the canvas
* if (state.rotation !== 0) {
* context.translate(width * pixelRatio * 0.5, height * pixelRatio * 0.5);
* context.rotate((state.rotation * Math.PI) / 180);
* context.translate(- width * pixelRatio * 0.5, -height * pixelRatio * 0.5);
* }
*
* // Set the style for all the text.
* context.font = "24px monospace";
* context.fillStyle = "black";
* context.shadowBlur = 1;
*
* for (const tile of this.tiles) {
* let screenScale = tile.resolution / state.resolution * pixelRatio;
*
* state.toScreenNoRotation(coords, tile.coords);
*
* // Draw the tile boundaries
* context.strokeRect(coords[0], coords[1], tileSize * screenScale, tileSize * screenScale);
*
* // Draw the tile information
* context.shadowColor = "white";
* context.fillText(
* tile.level + "/" + tile.row + "/" + tile.col + "/" + tile.world,
* coords[0] + 12,
* coords[1] + 24,
* tileSize * screenScale
* );
* context.shadowColor = "transparent";
* }
* }
* });
*
* let CustomTileLayer = Layer.createSubclass({
* tileInfo: TileInfo.create({ spatialReference: { wkid: 3857 }}),
*
* createLayerView(view) {
* if (view.type === "2d") {
* return new TileBorderLayerView2D({
* view: view,
* layer: this
* });
* }
* }
* });
*/
export default abstract class BaseLayerView2D extends LayerView {
constructor(properties?: BaseLayerView2DProperties);
/** References the layer this [LayerView](https://developers.arcgis.com/javascript/latest/references/core/views/layers/LayerView/) represents. */
get layer(): Layer;
/**
* The array of [Tile](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerView2D/#Tile) objects computed to cover the MapView's visible area.
* This array is updated when the view is animating or the user is interacting with it. Then if tiles have been added or removed,
* [tilesChanged()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerView2D/#tilesChanged) is called.
*
* @see [tilesChanged()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerView2D/#tilesChanged)
*/
tiles: Tile[];
/**
* References the [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/) this [LayerView](https://developers.arcgis.com/javascript/latest/references/core/views/layers/LayerView/) belongs to.
*
* @since 4.28
* @example
* // Check for the first time layerView.updating becomes false. Then query for
* // features that are visible within the view associated with the layer view.
* await reactiveUtils.whenOnce(() => !layerView.updating);
* const query = layerView.createQuery();
* query.geometry = layerView.view.extent;
* const result = layerView.queryFeatures(query);
*/
get view(): MapView;
/**
* Method called when after the [LayerView](https://developers.arcgis.com/javascript/latest/references/core/views/layers/LayerView/) is created and right before it's asked to draw the layer's content.
* Typically this method is implemented to start watching property changes on the layer for example.
*
* @see [detach()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerView2D/#detach)
* @example
* attach() {
* this._propertyHandle = reactiveUtils.watch(
* () => this.layer.opacity,
* () => this.requestRender()
* );
* }
*/
attach(): void;
/**
* Method called after the layer is removed and the [LayerView](https://developers.arcgis.com/javascript/latest/references/core/views/layers/LayerView/) is about to be removed.
* Typically, this method is implemented to free resources like watchers.
*
* @see [attach()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerView2D/#attach)
* @example
* // remove the watchers on the layer that are added in attach()
* detach() {
* this._propertyHandle.remove();
* this._propertyHandle = null;
* }
*/
detach(): void;
/**
* Method to implement that is responsible for providing objects hit at the specified screen coordinates.
* This method is called internally by the [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/) each time
* its [MapView.hitTest()](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/#hitTest) method is called.
*
* @param mapPoint - The point in map units.
* @param screenPoint - The point in screen coordinates.
* @returns A Promise that resolves to an array of hits.
*/
hitTest(mapPoint: Point, screenPoint: ScreenPoint): Promise<ViewHit[] | null | undefined>;
/**
* The method to implement that is responsible of drawing the content of the layer.
* This method is called every time the MapView's state changes, or if [requestRender()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerView2D/#requestRender) has been called.
*
* @param renderParameters
* @example
* // Example of a render implementation that draws tile boundaries
* render(renderParameters) {
* let tileSize = this.layer.tileInfo.size[0];
* let state = renderParameters.state;
* let pixelRatio = state.pixelRatio;
* let width = state.size[0];
* let height = state.size[1];
* let context = renderParameters.context;
* let coords = [0, 0];
*
* context.fillStyle = "rgba(0,0,0,0.25)";
* context.fillRect(0, 0, width * pixelRatio, height * pixelRatio);
*
* // apply rotation for everything that will be applied to the canvas
* if (state.rotation !== 0) {
* context.translate(width * pixelRatio * 0.5, height * pixelRatio * 0.5);
* context.rotate((state.rotation * Math.PI) / 180);
* context.translate(- width * pixelRatio * 0.5, -height * pixelRatio * 0.5);
* }
*
* // Set the style for all the text.
* context.font = "24px monospace";
* context.fillStyle = "black";
* context.shadowBlur = 1;
*
* for (const tile of this.tiles) {
* let screenScale = tile.resolution / state.resolution * pixelRatio;
*
* state.toScreenNoRotation(coords, tile.coords);
*
* // Draw the tile boundaries
* context.strokeRect(coords[0], coords[1], tileSize * screenScale, tileSize * screenScale);
*
* // Draw the tile information
* context.shadowColor = "white";
* context.fillText(
* tile.level + "/" + tile.row + "/" + tile.col + "/" + tile.world,
* coords[0] + 12,
* coords[1] + 24,
* tileSize * screenScale
* );
* context.shadowColor = "transparent";
* }
* }
*/
abstract render(renderParameters: RenderParameters): void;
/**
* The [LayerView](https://developers.arcgis.com/javascript/latest/references/core/views/layers/LayerView/) can call this method to ask the MapView to schedule a new rendering frame.
*
* @example
* // Call requestRender whenever the layer opacity has changed.
* attach() {
* this._propertyHandle = reactiveUtils.watch(
* () => this.layer.opacity,
* () => this.requestRender()
* );
* }
*/
requestRender(): void;
/**
* Method to implement, which notifies of tiles being added or removed for the current view state.
* This function can be implemented to start and stop fetching new data, or allocate and dispose resources.
*
* @param added - The tile objects added for the current view viewport.
* @param removed - The tile objects removed from the view viewport.
*/
tilesChanged(added: Tile[], removed: Tile[]): void;
}