[Maps] convert TileLayer and VectorTileLayer to TS (#117745)
* [Maps] convert TileLayer and VectorTileLayer to TS * commit using @elastic.co Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
7e4ae48efa
commit
7d90bad960
|
@ -466,7 +466,7 @@ export class AbstractLayer implements ILayer {
|
|||
return null;
|
||||
}
|
||||
|
||||
isBasemap(): boolean {
|
||||
isBasemap(order: number): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { AbstractLayer } from '../layer';
|
||||
import { ITMSSource } from '../../sources/tms_source';
|
||||
import { LayerDescriptor } from '../../../../common/descriptor_types';
|
||||
|
||||
interface ITileLayerArguments {
|
||||
source: ITMSSource;
|
||||
layerDescriptor: LayerDescriptor;
|
||||
}
|
||||
|
||||
export class TileLayer extends AbstractLayer {
|
||||
static type: string;
|
||||
|
||||
constructor(args: ITileLayerArguments);
|
||||
}
|
|
@ -5,25 +5,41 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { AbstractLayer } from '../layer';
|
||||
import type { Map as MbMap } from '@kbn/mapbox-gl';
|
||||
import _ from 'lodash';
|
||||
import { AbstractLayer } from '../layer';
|
||||
import { SOURCE_DATA_REQUEST_ID, LAYER_TYPE, LAYER_STYLE_TYPE } from '../../../../common/constants';
|
||||
import { LayerDescriptor } from '../../../../common/descriptor_types';
|
||||
import { TileStyle } from '../../styles/tile/tile_style';
|
||||
import { ITMSSource } from '../../sources/tms_source';
|
||||
import { DataRequestContext } from '../../../actions';
|
||||
|
||||
export interface ITileLayerArguments {
|
||||
source: ITMSSource;
|
||||
layerDescriptor: LayerDescriptor;
|
||||
}
|
||||
|
||||
// TODO - rename to RasterTileLayer
|
||||
export class TileLayer extends AbstractLayer {
|
||||
static createDescriptor(options, mapColors) {
|
||||
const tileLayerDescriptor = super.createDescriptor(options, mapColors);
|
||||
static createDescriptor(options: Partial<LayerDescriptor>) {
|
||||
const tileLayerDescriptor = super.createDescriptor(options);
|
||||
tileLayerDescriptor.type = LAYER_TYPE.TILE;
|
||||
tileLayerDescriptor.alpha = _.get(options, 'alpha', 1);
|
||||
tileLayerDescriptor.style = { type: LAYER_STYLE_TYPE.TILE };
|
||||
return tileLayerDescriptor;
|
||||
}
|
||||
|
||||
constructor({ source, layerDescriptor }) {
|
||||
private readonly _style: TileStyle;
|
||||
|
||||
constructor({ source, layerDescriptor }: ITileLayerArguments) {
|
||||
super({ source, layerDescriptor });
|
||||
this._style = new TileStyle();
|
||||
}
|
||||
|
||||
getSource(): ITMSSource {
|
||||
return super.getSource() as ITMSSource;
|
||||
}
|
||||
|
||||
getStyleForEditing() {
|
||||
return this._style;
|
||||
}
|
||||
|
@ -36,10 +52,10 @@ export class TileLayer extends AbstractLayer {
|
|||
return this._style;
|
||||
}
|
||||
|
||||
async syncData({ startLoading, stopLoading, onLoadError, dataFilters }) {
|
||||
async syncData({ startLoading, stopLoading, onLoadError, dataFilters }: DataRequestContext) {
|
||||
const sourceDataRequest = this.getSourceDataRequest();
|
||||
if (sourceDataRequest) {
|
||||
//data is immmutable
|
||||
// data is immmutable
|
||||
return;
|
||||
}
|
||||
const requestToken = Symbol(`layer-source-refresh:${this.getId()} - source`);
|
||||
|
@ -60,28 +76,28 @@ export class TileLayer extends AbstractLayer {
|
|||
return [this._getMbLayerId()];
|
||||
}
|
||||
|
||||
ownsMbLayerId(mbLayerId) {
|
||||
ownsMbLayerId(mbLayerId: string) {
|
||||
return this._getMbLayerId() === mbLayerId;
|
||||
}
|
||||
|
||||
ownsMbSourceId(mbSourceId) {
|
||||
ownsMbSourceId(mbSourceId: string) {
|
||||
return this.getId() === mbSourceId;
|
||||
}
|
||||
|
||||
syncLayerWithMB(mbMap) {
|
||||
syncLayerWithMB(mbMap: MbMap) {
|
||||
const source = mbMap.getSource(this.getId());
|
||||
const mbLayerId = this._getMbLayerId();
|
||||
|
||||
if (!source) {
|
||||
const sourceDataRequest = this.getSourceDataRequest();
|
||||
if (!sourceDataRequest) {
|
||||
//this is possible if the layer was invisible at startup.
|
||||
//the actions will not perform any data=syncing as an optimization when a layer is invisible
|
||||
//when turning the layer back into visible, it's possible the url has not been resovled yet.
|
||||
// this is possible if the layer was invisible at startup.
|
||||
// the actions will not perform any data=syncing as an optimization when a layer is invisible
|
||||
// when turning the layer back into visible, it's possible the url has not been resovled yet.
|
||||
return;
|
||||
}
|
||||
|
||||
const tmsSourceData = sourceDataRequest.getData();
|
||||
const tmsSourceData = sourceDataRequest.getData() as { url?: string };
|
||||
if (!tmsSourceData || !tmsSourceData.url) {
|
||||
return;
|
||||
}
|
||||
|
@ -106,9 +122,9 @@ export class TileLayer extends AbstractLayer {
|
|||
this._setTileLayerProperties(mbMap, mbLayerId);
|
||||
}
|
||||
|
||||
_setTileLayerProperties(mbMap, mbLayerId) {
|
||||
_setTileLayerProperties(mbMap: MbMap, mbLayerId: string) {
|
||||
this.syncVisibilityWithMb(mbMap, mbLayerId);
|
||||
mbMap.setLayerZoomRange(mbLayerId, this._descriptor.minZoom, this._descriptor.maxZoom);
|
||||
mbMap.setLayerZoomRange(mbLayerId, this.getMinZoom(), this.getMaxZoom());
|
||||
mbMap.setPaintProperty(mbLayerId, 'raster-opacity', this.getAlpha());
|
||||
}
|
||||
|
||||
|
@ -116,7 +132,7 @@ export class TileLayer extends AbstractLayer {
|
|||
return 'grid';
|
||||
}
|
||||
|
||||
isBasemap(order) {
|
||||
isBasemap(order: number) {
|
||||
return order === 0;
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ITileLayerArguments, TileLayer } from '../tile_layer/tile_layer';
|
||||
|
||||
export class VectorTileLayer extends TileLayer {
|
||||
static type: string;
|
||||
constructor(args: ITileLayerArguments);
|
||||
}
|
|
@ -5,27 +5,52 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { TileLayer } from '../tile_layer/tile_layer';
|
||||
import type { Map as MbMap, Layer as MbLayer, Style as MbStyle } from '@kbn/mapbox-gl';
|
||||
import _ from 'lodash';
|
||||
import { TileLayer } from '../tile_layer/tile_layer';
|
||||
import { SOURCE_DATA_REQUEST_ID, LAYER_TYPE, LAYER_STYLE_TYPE } from '../../../../common/constants';
|
||||
import { LayerDescriptor } from '../../../../common/descriptor_types';
|
||||
import { DataRequest } from '../../util/data_request';
|
||||
import { isRetina } from '../../../util';
|
||||
import {
|
||||
addSpriteSheetToMapFromImageData,
|
||||
loadSpriteSheetImageData,
|
||||
// @ts-expect-error
|
||||
} from '../../../connected_components/mb_map/utils';
|
||||
import { DataRequestContext } from '../../../actions';
|
||||
import { EMSTMSSource } from '../../sources/ems_tms_source';
|
||||
|
||||
const MB_STYLE_TYPE_TO_OPACITY = {
|
||||
fill: ['fill-opacity'],
|
||||
line: ['line-opacity'],
|
||||
circle: ['circle-opacity'],
|
||||
background: ['background-opacity'],
|
||||
symbol: ['icon-opacity', 'text-opacity'],
|
||||
};
|
||||
interface SourceRequestMeta {
|
||||
tileLayerId: string;
|
||||
}
|
||||
|
||||
// TODO remove once ems_client exports EmsSpriteSheet and EmsSprite type
|
||||
interface EmsSprite {
|
||||
height: number;
|
||||
pixelRatio: number;
|
||||
width: number;
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
interface EmsSpriteSheet {
|
||||
[spriteName: string]: EmsSprite;
|
||||
}
|
||||
|
||||
interface SourceRequestData {
|
||||
spriteSheetImageData?: ImageData;
|
||||
vectorStyleSheet?: MbStyle;
|
||||
spriteMeta?: {
|
||||
png: string;
|
||||
json: EmsSpriteSheet;
|
||||
};
|
||||
}
|
||||
|
||||
// TODO - rename to EmsVectorTileLayer
|
||||
export class VectorTileLayer extends TileLayer {
|
||||
static type = LAYER_TYPE.VECTOR_TILE;
|
||||
|
||||
static createDescriptor(options) {
|
||||
static createDescriptor(options: Partial<LayerDescriptor>) {
|
||||
const tileLayerDescriptor = super.createDescriptor(options);
|
||||
tileLayerDescriptor.type = VectorTileLayer.type;
|
||||
tileLayerDescriptor.alpha = _.get(options, 'alpha', 1);
|
||||
|
@ -33,11 +58,21 @@ export class VectorTileLayer extends TileLayer {
|
|||
return tileLayerDescriptor;
|
||||
}
|
||||
|
||||
_canSkipSync({ prevDataRequest, nextMeta }) {
|
||||
getSource(): EMSTMSSource {
|
||||
return super.getSource() as EMSTMSSource;
|
||||
}
|
||||
|
||||
_canSkipSync({
|
||||
prevDataRequest,
|
||||
nextMeta,
|
||||
}: {
|
||||
prevDataRequest?: DataRequest;
|
||||
nextMeta: SourceRequestMeta;
|
||||
}) {
|
||||
if (!prevDataRequest) {
|
||||
return false;
|
||||
}
|
||||
const prevMeta = prevDataRequest.getMeta();
|
||||
const prevMeta = prevDataRequest.getMeta() as SourceRequestMeta;
|
||||
if (!prevMeta) {
|
||||
return false;
|
||||
}
|
||||
|
@ -45,7 +80,7 @@ export class VectorTileLayer extends TileLayer {
|
|||
return prevMeta.tileLayerId === nextMeta.tileLayerId;
|
||||
}
|
||||
|
||||
async syncData({ startLoading, stopLoading, onLoadError }) {
|
||||
async syncData({ startLoading, stopLoading, onLoadError }: DataRequestContext) {
|
||||
const nextMeta = { tileLayerId: this.getSource().getTileLayerId() };
|
||||
const canSkipSync = this._canSkipSync({
|
||||
prevDataRequest: this.getSourceDataRequest(),
|
||||
|
@ -59,7 +94,9 @@ export class VectorTileLayer extends TileLayer {
|
|||
try {
|
||||
startLoading(SOURCE_DATA_REQUEST_ID, requestToken, nextMeta);
|
||||
const styleAndSprites = await this.getSource().getVectorStyleSheetAndSpriteMeta(isRetina());
|
||||
const spriteSheetImageData = await loadSpriteSheetImageData(styleAndSprites.spriteMeta.png);
|
||||
const spriteSheetImageData = styleAndSprites.spriteMeta
|
||||
? await loadSpriteSheetImageData(styleAndSprites.spriteMeta.png)
|
||||
: undefined;
|
||||
const data = {
|
||||
...styleAndSprites,
|
||||
spriteSheetImageData,
|
||||
|
@ -70,7 +107,7 @@ export class VectorTileLayer extends TileLayer {
|
|||
}
|
||||
}
|
||||
|
||||
_generateMbId(name) {
|
||||
_generateMbId(name: string) {
|
||||
return `${this.getId()}_${name}`;
|
||||
}
|
||||
|
||||
|
@ -79,7 +116,7 @@ export class VectorTileLayer extends TileLayer {
|
|||
return `${this.getId()}${DELIMITTER}${this.getSource().getTileLayerId()}${DELIMITTER}`;
|
||||
}
|
||||
|
||||
_generateMbSourceId(name) {
|
||||
_generateMbSourceId(name: string) {
|
||||
return `${this._generateMbSourceIdPrefix()}${name}`;
|
||||
}
|
||||
|
||||
|
@ -88,11 +125,7 @@ export class VectorTileLayer extends TileLayer {
|
|||
if (!sourceDataRequest) {
|
||||
return null;
|
||||
}
|
||||
const vectorStyleAndSprites = sourceDataRequest.getData();
|
||||
if (!vectorStyleAndSprites) {
|
||||
return null;
|
||||
}
|
||||
return vectorStyleAndSprites.vectorStyleSheet;
|
||||
return (sourceDataRequest.getData() as SourceRequestData)?.vectorStyleSheet;
|
||||
}
|
||||
|
||||
_getSpriteMeta() {
|
||||
|
@ -100,8 +133,7 @@ export class VectorTileLayer extends TileLayer {
|
|||
if (!sourceDataRequest) {
|
||||
return null;
|
||||
}
|
||||
const vectorStyleAndSprites = sourceDataRequest.getData();
|
||||
return vectorStyleAndSprites.spriteMeta;
|
||||
return (sourceDataRequest.getData() as SourceRequestData)?.spriteMeta;
|
||||
}
|
||||
|
||||
_getSpriteImageData() {
|
||||
|
@ -109,13 +141,12 @@ export class VectorTileLayer extends TileLayer {
|
|||
if (!sourceDataRequest) {
|
||||
return null;
|
||||
}
|
||||
const vectorStyleAndSprites = sourceDataRequest.getData();
|
||||
return vectorStyleAndSprites.spriteSheetImageData;
|
||||
return (sourceDataRequest.getData() as SourceRequestData)?.spriteSheetImageData;
|
||||
}
|
||||
|
||||
getMbLayerIds() {
|
||||
const vectorStyle = this._getVectorStyle();
|
||||
if (!vectorStyle) {
|
||||
if (!vectorStyle || !vectorStyle.layers) {
|
||||
return [];
|
||||
}
|
||||
return vectorStyle.layers.map((layer) => this._generateMbId(layer.id));
|
||||
|
@ -123,29 +154,32 @@ export class VectorTileLayer extends TileLayer {
|
|||
|
||||
getMbSourceIds() {
|
||||
const vectorStyle = this._getVectorStyle();
|
||||
if (!vectorStyle) {
|
||||
if (!vectorStyle || !vectorStyle.sources) {
|
||||
return [];
|
||||
}
|
||||
const sourceIds = Object.keys(vectorStyle.sources);
|
||||
return sourceIds.map((sourceId) => this._generateMbSourceId(sourceId));
|
||||
}
|
||||
|
||||
ownsMbLayerId(mbLayerId) {
|
||||
ownsMbLayerId(mbLayerId: string) {
|
||||
return mbLayerId.startsWith(this.getId());
|
||||
}
|
||||
|
||||
ownsMbSourceId(mbSourceId) {
|
||||
ownsMbSourceId(mbSourceId: string) {
|
||||
return mbSourceId.startsWith(this.getId());
|
||||
}
|
||||
|
||||
_makeNamespacedImageId(imageId) {
|
||||
_makeNamespacedImageId(imageId: string) {
|
||||
const prefix = this.getSource().getSpriteNamespacePrefix() + '/';
|
||||
return prefix + imageId;
|
||||
}
|
||||
|
||||
_requiresPrevSourceCleanup(mbMap) {
|
||||
_requiresPrevSourceCleanup(mbMap: MbMap) {
|
||||
const sourceIdPrefix = this._generateMbSourceIdPrefix();
|
||||
const mbStyle = mbMap.getStyle();
|
||||
if (!mbStyle.sources) {
|
||||
return false;
|
||||
}
|
||||
return Object.keys(mbStyle.sources).some((mbSourceId) => {
|
||||
const doesMbSourceBelongToLayer = this.ownsMbSourceId(mbSourceId);
|
||||
const doesMbSourceBelongToSource = mbSourceId.startsWith(sourceIdPrefix);
|
||||
|
@ -153,7 +187,7 @@ export class VectorTileLayer extends TileLayer {
|
|||
});
|
||||
}
|
||||
|
||||
syncLayerWithMB(mbMap) {
|
||||
syncLayerWithMB(mbMap: MbMap) {
|
||||
const vectorStyle = this._getVectorStyle();
|
||||
if (!vectorStyle) {
|
||||
return;
|
||||
|
@ -162,7 +196,7 @@ export class VectorTileLayer extends TileLayer {
|
|||
this._removeStaleMbSourcesAndLayers(mbMap);
|
||||
|
||||
let initialBootstrapCompleted = false;
|
||||
const sourceIds = Object.keys(vectorStyle.sources);
|
||||
const sourceIds = vectorStyle.sources ? Object.keys(vectorStyle.sources) : [];
|
||||
sourceIds.forEach((sourceId) => {
|
||||
if (initialBootstrapCompleted) {
|
||||
return;
|
||||
|
@ -170,20 +204,20 @@ export class VectorTileLayer extends TileLayer {
|
|||
const mbSourceId = this._generateMbSourceId(sourceId);
|
||||
const mbSource = mbMap.getSource(mbSourceId);
|
||||
if (mbSource) {
|
||||
//if a single source is present, the layer already has bootstrapped with the mbMap
|
||||
// if a single source is present, the layer already has bootstrapped with the mbMap
|
||||
initialBootstrapCompleted = true;
|
||||
return;
|
||||
}
|
||||
mbMap.addSource(mbSourceId, vectorStyle.sources[sourceId]);
|
||||
mbMap.addSource(mbSourceId, vectorStyle.sources![sourceId]);
|
||||
});
|
||||
|
||||
if (!initialBootstrapCompleted) {
|
||||
//sync spritesheet
|
||||
// sync spritesheet
|
||||
const spriteMeta = this._getSpriteMeta();
|
||||
if (!spriteMeta) {
|
||||
return;
|
||||
}
|
||||
const newJson = {};
|
||||
const newJson: EmsSpriteSheet = {};
|
||||
for (const imageId in spriteMeta.json) {
|
||||
if (spriteMeta.json.hasOwnProperty(imageId)) {
|
||||
const namespacedImageId = this._makeNamespacedImageId(imageId);
|
||||
|
@ -197,8 +231,9 @@ export class VectorTileLayer extends TileLayer {
|
|||
}
|
||||
addSpriteSheetToMapFromImageData(newJson, imageData, mbMap);
|
||||
|
||||
//sync layers
|
||||
vectorStyle.layers.forEach((layer) => {
|
||||
// sync layers
|
||||
const layers = vectorStyle.layers ? vectorStyle.layers : [];
|
||||
layers.forEach((layer) => {
|
||||
const mbLayerId = this._generateMbId(layer.id);
|
||||
const mbLayer = mbMap.getLayer(mbLayerId);
|
||||
if (mbLayer) {
|
||||
|
@ -206,7 +241,10 @@ export class VectorTileLayer extends TileLayer {
|
|||
}
|
||||
const newLayerObject = {
|
||||
...layer,
|
||||
source: this._generateMbSourceId(layer.source),
|
||||
source:
|
||||
typeof (layer as MbLayer).source === 'string'
|
||||
? this._generateMbSourceId((layer as MbLayer).source as string)
|
||||
: undefined,
|
||||
id: mbLayerId,
|
||||
};
|
||||
|
||||
|
@ -237,15 +275,35 @@ export class VectorTileLayer extends TileLayer {
|
|||
this._setTileLayerProperties(mbMap);
|
||||
}
|
||||
|
||||
_setOpacityForType(mbMap, mbLayer, mbLayerId) {
|
||||
const opacityProps = MB_STYLE_TYPE_TO_OPACITY[mbLayer.type];
|
||||
if (!opacityProps) {
|
||||
return;
|
||||
_getOpacityProps(layerType: string): string[] {
|
||||
if (layerType === 'fill') {
|
||||
return ['fill-opacity'];
|
||||
}
|
||||
|
||||
opacityProps.forEach((opacityProp) => {
|
||||
if (mbLayer.paint && typeof mbLayer.paint[opacityProp] === 'number') {
|
||||
const newOpacity = mbLayer.paint[opacityProp] * this.getAlpha();
|
||||
if (layerType === 'line') {
|
||||
return ['line-opacity'];
|
||||
}
|
||||
|
||||
if (layerType === 'circle') {
|
||||
return ['circle-opacity'];
|
||||
}
|
||||
|
||||
if (layerType === 'background') {
|
||||
return ['background-opacity'];
|
||||
}
|
||||
|
||||
if (layerType === 'symbol') {
|
||||
return ['icon-opacity', 'text-opacity'];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
_setOpacityForType(mbMap: MbMap, mbLayer: MbLayer, mbLayerId: string) {
|
||||
this._getOpacityProps(mbLayer.type).forEach((opacityProp) => {
|
||||
const mbPaint = mbLayer.paint as { [key: string]: unknown } | undefined;
|
||||
if (mbPaint && typeof mbPaint[opacityProp] === 'number') {
|
||||
const newOpacity = (mbPaint[opacityProp] as number) * this.getAlpha();
|
||||
mbMap.setPaintProperty(mbLayerId, opacityProp, newOpacity);
|
||||
} else {
|
||||
mbMap.setPaintProperty(mbLayerId, opacityProp, this.getAlpha());
|
||||
|
@ -253,21 +311,21 @@ export class VectorTileLayer extends TileLayer {
|
|||
});
|
||||
}
|
||||
|
||||
_setLayerZoomRange(mbMap, mbLayer, mbLayerId) {
|
||||
let minZoom = this._descriptor.minZoom;
|
||||
_setLayerZoomRange(mbMap: MbMap, mbLayer: MbLayer, mbLayerId: string) {
|
||||
let minZoom = this.getMinZoom();
|
||||
if (typeof mbLayer.minzoom === 'number') {
|
||||
minZoom = Math.max(minZoom, mbLayer.minzoom);
|
||||
}
|
||||
let maxZoom = this._descriptor.maxZoom;
|
||||
let maxZoom = this.getMaxZoom();
|
||||
if (typeof mbLayer.maxzoom === 'number') {
|
||||
maxZoom = Math.min(maxZoom, mbLayer.maxzoom);
|
||||
}
|
||||
mbMap.setLayerZoomRange(mbLayerId, minZoom, maxZoom);
|
||||
}
|
||||
|
||||
_setTileLayerProperties(mbMap) {
|
||||
_setTileLayerProperties(mbMap: MbMap) {
|
||||
const vectorStyle = this._getVectorStyle();
|
||||
if (!vectorStyle) {
|
||||
if (!vectorStyle || !vectorStyle.layers) {
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in a new issue