@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
436 lines (430 loc) • 23.8 kB
TypeScript
import type Extent from "../../../geometry/Extent.js";
import type Multipoint from "../../../geometry/Multipoint.js";
import type Point from "../../../geometry/Point.js";
import type Polygon from "../../../geometry/Polygon.js";
import type Polyline from "../../../geometry/Polyline.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 { TessellatedMesh } from "../types.js";
import type { LayerViewProperties } from "../../layers/LayerView.js";
export interface BaseLayerViewGL2DProperties extends LayerViewProperties, Partial<Pick<BaseLayerViewGL2D, "tiles">> {}
/**
* A rectangle in screen-space.
*
* An instance of `Rect` is used to specify the screen-space geometry of the resulting marker when calling
* [tessellatePoint()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#tessellatePoint) or [tessellateMultipoint()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#tessellateMultipoint).
* The exact interpretation of _"screen-space"_ is ultimately implemented through a custom vertex shader;
* a common convention is to interpret the values in the rect as being expressed in pixels or points.
* See [TessellatedMesh](https://developers.arcgis.com/javascript/latest/references/core/views/2d/types/#TessellatedMesh) for more details.
*
* 
*/
export interface Rect {
/** The `x`-coordinate of the upper-left corner of the rectangle, relative to the anchor of the marker. */
x: number;
/** The `y`-coordinate of the upper-left corner of the rectangle, relative to the anchor of the marker. */
y: number;
/** Width of the rectangle. */
width: number;
/** Height of the rectangle. */
height: number;
}
/**
* The destination to which [render()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#render) should direct its output.
*
* Rendering output is saved into a [framebuffer](https://developer.mozilla.org/en-US/docs/Web/API/WebGLFramebuffer),
* possibly but not necessarily the default one, at a location
* defined by the [viewport](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/viewport).
*
* An instance of this class is mantained internally by `BaseLayerViewGL2D` and can be accessed by a call to
* [getRenderTarget()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#getRenderTarget). It is the same instance that is restored to the WebGL context by
* calling [bindRenderTarget()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#bindRenderTarget).
*
* When control is handed over to [render()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#render), the WebGL context is guaranteed to be in a default state
* except for the currently bound framebuffer and the configured viewport. Implementations of [render()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#render)
* are free to change these parameters using `gl.bindFramebuffer()` and `gl.viewport()`, but they must send the
* output of the rendering process to the render target.
*/
export interface RenderTarget {
/** The framebuffer where the [render()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#render) method should direct its output. */
framebuffer: WebGLFramebuffer | null;
/** A viewport that fully covers `framebuffer`. */
viewport: [
number,
number,
number,
number
];
}
export interface RenderParameters {
/**
* The
* WebGL or WebGL 2 context. Its concrete type depends on system configuration.
* Every time that `render()` is called, the API automatically resets WebGL to a conventional
* state which is _almost_ the default one; the only two things that may be non-default are
* the bound framebuffer and the viewport, which is set to match the entire framebuffer.
* _The body of `render()` **must not** change these settings_.
*/
context: WebGL2RenderingContext;
/** 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/). In contrast to the
* related class [BaseLayerView2D](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerView2D/), this one exposes [WebGL](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext)
* rendering capabilities.
*
* > [!WARNING]
* >
* > ### Important notes
* >
* > **This interface is experimental**. Please read the following information carefully before using it in a product.
* >
* > Due to the nature of WebGL it is not possible to fully sandbox user-supplied code, and its malfunctions can affect the
* > performance, visual quality and even stability of the entire [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/). For this reason, Esri
* > does not provide any support for issues related to WebGL rendering in custom rendering code, or for issues that arise in
* > [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/) rendering while using custom rendering code.
*
* 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/BaseLayerViewGL2D/#attach) method is called when the LayerView is about to start drawing the layer's content; it
* is usually responsible for resource allocation.
* * Then during the life of the LayerView the [render()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#render) method is called once per frame; it must complete
* drawing before returning.
* * Finally the [detach()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#detach) method is called after the layer is removed from the map; it releases all allocated
* resources and stops on-going requests.
*
* Each of these functions has access to the [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/)'s WebGL context through the instance property
* [this.context](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#context). The developer must provide own shaders, meshes
* and textures, and is responsible for setting the required GL states on the context.
*
* As a convenience for the developer, starting with version 4.14 of the API, `BaseLayerViewGL2D` includes tessellation
* helper methods; the developer can supply [Point](https://developers.arcgis.com/javascript/latest/references/core/geometry/Point/), [Multipoint](https://developers.arcgis.com/javascript/latest/references/core/geometry/Multipoint/),
* [Polyline](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polyline/), [Extent](https://developers.arcgis.com/javascript/latest/references/core/geometry/Extent/), or [Polygon](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polygon/)
* geometries and have them converted to abstract descriptions of triangle meshes that can be easily fed to the GPU as
* vertex and index buffers. The [SDK sample](https://developers.arcgis.com/javascript/latest/sample-code/custom-gl-tessellation-helpers/)
* explains in detail how to use the tessellation helpers and how to write compatible shaders.
*
* @since 4.11
* @see [Sample - Tutorial: animated markers](https://developers.arcgis.com/javascript/latest/sample-code/custom-gl-visuals/)
* @see [Sample - Tessellation helpers](https://developers.arcgis.com/javascript/latest/sample-code/custom-gl-tessellation-helpers/)
* @see [Sample - Animated lines](https://developers.arcgis.com/javascript/latest/sample-code/custom-gl-animated-lines/)
* @see [Sample - Tiling support](https://developers.arcgis.com/javascript/latest/sample-code/custom-gl-tiles/)
* @see [Sample - Using deck.gl](https://developers.arcgis.com/javascript/latest/sample-code/custom-lv-deckgl/)
* @example
* let CustomLayerView2D = BaseLayerViewGL2D.createSubclass({
* render(renderParameters) {
* const gl = this.context;
*
* ...
* }
*
* attach() {
* const gl = this.context;
*
* ...
* }
*
* detach() {
* const gl = this.context;
*
* ...
* }
* });
*
* let CustomTileLayer = Layer.createSubclass({
* tileInfo: TileInfo.create({ spatialReference: { wkid: 3857 }}),
*
* createLayerView(view) {
* if (view.type === "2d") {
* return new CustomLayerView2D({
* view: view,
* layer: this
* });
* }
* }
* });
*/
export default abstract class BaseLayerViewGL2D extends LayerView {
constructor(properties?: BaseLayerViewGL2DProperties);
/** The WebGL rendering context associated to this layer view. */
get context(): WebGL2RenderingContext;
/** 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/BaseLayerViewGL2D/#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/BaseLayerViewGL2D/#tilesChanged) is called.
*
* @see [tilesChanged()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#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 after the [LayerView](https://developers.arcgis.com/javascript/latest/references/core/views/layers/LayerView/) is created and right before it starts drawing the layer's content.
* Typically this method is implemented to start watching property changes on the layer and to initialize WebGL objects such as
* shaders.
*
* @see [detach()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#detach)
* @example
* // Create a shader program and a property watcher
* attach() {
* let gl = this.context;
*
* this._shaderProgram = gl.createProgram();
* ...
*
* this._propertyHandle = reactiveUtils.watch(
* () => this.layer.opacity,
* () => this.requestRender()
* );
* }
*/
attach(): void;
/**
* Bind the designated rendering output surface and restore the correct viewport.
*
* This method can be used after the WebGL state has been altered by a call to
* `gl.bindFramebuffer()` to restore the framebuffer that contains the final,
* composited frame, i.e. the one that is guaranteed to be bound right before
* control is handed over to [render()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#render). Note that this *may or may not be the default framebuffer*;
* [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/) can use various surfaces for frame compositing and there is no
* guarantee that when [render()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#render) is called, the bound framebuffer is
* the default one.
*
* Together with the framebuffer, also a matching full-size viewport is restored.
*
* @example
* render() {
* let gl = this.context;
*
* ...
*
* // Bind a temporary offscreen surface
* gl.bindFramebuffer(gl.FRAMEBUFFER, this.myOffscreenSurface);
*
* ...
*
* // Render to the offscreen surface
*
* ...
*
* // Bind the original render surface so that the image stored
* // into the temporary one can be blitted/composited with the
* // actual frame data
* this.bindRenderTarget();
*
* ...
*
* // Your own frame composition logic
*
* ...
* }
*/
bindRenderTarget(): 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 and destroy WebGL objects such as shader programs.
*
* @see [attach()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#attach)
* @example
* // Remove the watchers and destroy the shader program created in attach()
* detach() {
* this._propertyHandle.remove();
* this._propertyHandle = null;
*
* const gl = this.context;
*
* gl.deleteProgram(this._shaderProgram);
* this._shaderProgram = null;
* }
*/
detach(): void;
/**
* Get the designated rendering output surface and corresponding viewport configuration.
*
* The returned object is the same render target that is restored by a call to [bindRenderTarget()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#bindRenderTarget).
*/
getRenderTarget(): RenderTarget;
/**
* 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 graphics.
*/
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/BaseLayerViewGL2D/#requestRender) has been called.
*
* @param renderParameters
* @example
* // Example of a render implementation that draws using a custom shader program
* render(renderParameters) {
* const gl = this.context;
* gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
* gl.vertexAttribPointer(0, 2, gl.SHORT, false, 10, 0);
* gl.vertexAttribPointer(1, 3, gl.SHORT, true, 10, 4);
* gl.bindBuffer(gl.ARRAY_BUFFER, null);
* gl.enableVertexAttribArray(0);
* gl.enableVertexAttribArray(1);
* ...
* // Update uniforms as needed by calling gl.uniform...
* ...
* gl.useProgram(this._shaderProgram);
* gl.drawArrays(gl.TRIANGLES, 0, this._vertexCount);
* gl.disableVertexAttribArray(0);
* gl.disableVertexAttribArray(1);
* gl.useProgram(null);
* }
*/
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;
/**
* Tessellate an [Extent](https://developers.arcgis.com/javascript/latest/references/core/geometry/Extent/) into a rectangle.
*
* @param extent - The input geometry.
* @returns A promise to a [TessellatedMesh](https://developers.arcgis.com/javascript/latest/references/core/views/2d/types/#TessellatedMesh). The output mesh is composed of two triangles.
* @since 4.14
* @example
* this.tessellateExtent(g.geometry).then(function (mesh) {
* // do something with mesh
* });
*/
tessellateExtent(extent: Extent): Promise<TessellatedMesh>;
/**
* Tessellate a [Multipoint](https://developers.arcgis.com/javascript/latest/references/core/geometry/Multipoint/) into quads (markers).
*
* @param multipoint - The input geometry. These are the geographic points where each marker will me anchored.
* @param footprint - The rectangle that describes the geometry of each marker. Coordinates x and y
* can be thought as being in screen-space, relative to the screen-space projection of the geographic point.
* @returns A promise to a [TessellatedMesh](https://developers.arcgis.com/javascript/latest/references/core/views/2d/types/#TessellatedMesh). Each marker is represented by two triangles.
* @since 4.14
* @example
* this.tessellateMultipoint(g.geometry, {x: 0, : -12, width: 34, height: 10}).then(function (mesh) {
* // do something with mesh
* });
*/
tessellateMultipoint(multipoint: Multipoint, footprint: Rect): Promise<TessellatedMesh>;
/**
* Tessellate a [Point](https://developers.arcgis.com/javascript/latest/references/core/geometry/Point/) into a quad (marker).
*
* @param point - The input geometry. This is the geographic point where the marker will me anchored.
* @param footprint - The rectangle that describes the geometry of the marker.
* Coordinates `x` and `y` are the
* position of the upper-left corner of the marker, and can be thought as being in screen-space, relative to the screen-space
* projection of the geographic point; `width` and `height` are in pixels. See [Rect](https://developers.arcgis.com/javascript/latest/references/core/views/2d/layers/BaseLayerViewGL2D/#Rect)
* for a visual explanation of marker geometry.
* @returns A promise to a [TessellatedMesh](https://developers.arcgis.com/javascript/latest/references/core/views/2d/types/#TessellatedMesh). The output mesh is composed of two triangles.
* @since 4.14
* @example
* this.tessellatePoint(g.geometry, {x: 0, : -12, width: 34, height: 10}).then(function (mesh) {
* // do something with mesh
* });
*/
tessellatePoint(point: Point, footprint: Rect): Promise<TessellatedMesh>;
/**
* Tessellate a [Polygon](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polygon/) into triangles.
*
* @param polygon - The input geometry. *The geometry must be simple*;
* if the input geometry is not simple, you must first create a simplified version of it using
* [simplifyOperator](https://developers.arcgis.com/javascript/latest/references/core/geometry/operators/simplifyOperator/), and pass the simplified geometry to `tessellatePolygon`.
* @returns A promise to a [TessellatedMesh](https://developers.arcgis.com/javascript/latest/references/core/views/2d/types/#TessellatedMesh).
* @since 4.14
* @example
* this.tessellatePolygon(g.geometry).then(function (mesh) {
* // do something with mesh
* });
*/
tessellatePolygon(polygon: Polygon): Promise<TessellatedMesh>;
/**
* Tessellate a [Polyline](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polyline/) into triangles.
*
* @param polyline - The input geometry. *The geometry must be simple*;
* if the input geometry is not simple, you must first create a simplified version of it using
* [simplifyOperator](https://developers.arcgis.com/javascript/latest/references/core/geometry/operators/simplifyOperator/), and pass the simplified geometry to `tessellatePolyline`.
* @param width - The width of the line; this will be used to scale xOffset and yOffset.
* @returns A promise to a [TessellatedMesh](https://developers.arcgis.com/javascript/latest/references/core/views/2d/types/#TessellatedMesh).
* @since 4.14
* @example
* this.tessellatePolyline(g.geometry, 10).then(function (mesh) {
* // do something with mesh
* });
*/
tessellatePolyline(polyline: Polyline, width: number): Promise<TessellatedMesh>;
/**
* 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;
}