chore: 瓦片代码重构 (#1390)

* feat: 瓦片代码改造

* chore: 瓦片代码重构

* feat: 瓦片代码完善

* chore: 瓦片代码重构

Co-authored-by: shihui <yiqianyao.yqy@alibaba-inc.com>
This commit is contained in:
YiQianYao 2022-10-13 21:12:35 +08:00 committed by GitHub
parent 8a98f79b16
commit 3b2bdc3999
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 1237 additions and 1205 deletions

View File

@ -0,0 +1,141 @@
import { RasterLayer, Scene, Source } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps';
import React, { useEffect } from 'react';
import * as GeoTIFF from 'geotiff';
const colorList = [
'#419bdf', // Water
'#419bdf',
'#397d49', // Tree
'#397d49',
'#88b053', // Grass
'#88b053',
'#7a87c6', // vegetation
'#7a87c6',
'#e49635', // Crops
'#e49635',
'#dfc35a', // shrub
'#dfc35a',
'#c4281b', // Built Area
'#c4281b',
'#a59b8f', // Bare ground
'#a59b8f',
'#a8ebff', // Snow
'#a8ebff',
'#616161', // Clouds
'#616161'
];
const positions = [
0.0,
0.1,
0.1,
0.2,
0.2,
0.3,
0.3,
0.4,
0.4,
0.5,
0.5,
0.6,
0.6,
0.7,
0.7,
0.8,
0.8,
0.9,
0.9,
1.0
];
export default () => {
useEffect(() => {
const scene = new Scene({
id: 'map',
stencil: true,
map: new GaodeMap({
center: [ 116, 27 ],
zoom: 6,
style: 'dark'
})
});
scene.on('loaded', () => {
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/fccd80c0-2611-49f9-9a9f-e2a4dd12226f.json'
)
.then(res => res.json())
.then(maskData => {
const layer = new RasterLayer({
mask: true,
maskfence: maskData
});
const tileSource = new Source('https://ganos.oss-cn-hangzhou.aliyuncs.com/m2/l7/tiff_jx/{z}/{x}/{y}.tiff',
{
parser: {
type: 'rasterTile',
dataType: 'arraybuffer',
tileSize: 256,
maxZoom: 13.1,
format: async data => {
const tiff = await GeoTIFF.fromArrayBuffer(data);
const image = await tiff.getImage();
const width = image.getWidth();
const height = image.getHeight();
const values = await image.readRasters();
return { rasterData: values[0], width, height };
}
}
});
layer.source(tileSource)
.style({
domain: [ 0.001, 11.001 ],
clampLow: false,
rampColors: {
colors: colorList,
positions
}
});
scene.addLayer(layer);
setTimeout(() => {
layer.style({
rampColors: {
colors: ['#f00', '#ff0'],
positions: [0, 1]
}
});
scene.render()
}, 2000)
});
});
return () => {
scene.destroy();
};
}, []);
return (
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
);
};

View File

@ -0,0 +1,4 @@
### Raster - RasterData - Update
数据栅格 update
#### 加载 tiff
<code src="./rasterData/update.tsx"></code>

View File

@ -1,13 +1,13 @@
### Vector
<!--
#### vector point
<code src="./vector/point.tsx"></code>
<code src="./vector/point.tsx"></code> -->
#### vector line
<code src="./vector/line.tsx"></code>
#### geojson-vt
<code src="./vector/geojson-vt.tsx"></code>
<!-- #### geojson-vt
<code src="./vector/geojson-vt.tsx"></code> -->
#### debugLayer
<code src="./vector/debugLayer.tsx"></code>
<!-- #### debugLayer
<code src="./vector/debugLayer.tsx"></code> -->

View File

@ -46,7 +46,8 @@ export default () => {
})
.source(source)
.color('COLOR')
.active(true)
// .active(true)
.select(true)
.style({
opacity: 0.6,
});

View File

@ -1,7 +1,7 @@
// @ts-ignore
import { Scene, LineLayer } from '@antv/l7';
// @ts-ignore
import { Mapbox } from '@antv/l7-maps';
import { Map } from '@antv/l7-maps';
import React, { useEffect } from 'react';
export default () => {
@ -9,10 +9,8 @@ export default () => {
const scene = new Scene({
id: 'line',
stencil: true,
map: new Mapbox({
map: new Map({
center: [121.268, 30.3628],
pitch: 0,
style: 'blank',
zoom: 4,
}),
});

View File

@ -172,17 +172,6 @@ export interface ISubLayerInitOptions {
workerEnabled?: boolean;
}
export interface ITilePickManager {
isLastPicked: boolean;
on(type: string, cb: (option: any) => void): void;
normalRender(layers: ILayer[]): void;
beforeHighlight(pickedColors: any): void;
beforeSelect(pickedColors: any): void;
clearPick(): void;
pickRender(layers: ILayer[], target: IInteractionTarget): boolean;
destroy(): void;
}
export interface IBaseTileLayerManager {
sourceLayer: string;
parent: ILayer;
@ -191,24 +180,39 @@ export interface IBaseTileLayerManager {
createTile(tile: Tile): { layers: ILayer[]; layerIDList: string[] };
addChild(layer: ILayer): void;
addChilds(layers: ILayer[]): void;
getChilds(layerIDList: string[]): ILayer[];
addChildren(layers: ILayer[]): void;
getChildren(layerIDList: string[]): ILayer[];
removeChild(layer: ILayer): void;
removeChilds(layerIDList: string[], refresh?: boolean): void;
removeChildren(layerIDList: string[], refresh?: boolean): void;
clearChild(): void;
hasChild(layer: ILayer): boolean;
render(isPicking?: boolean): void;
destroy(): void;
}
export interface ITileRenderService {
render(layers: ILayer[]): void;
renderMask(layers: ILayer): void;
}
export interface ITilePickService {
isLastPicked: boolean;
on(type: string, cb: (option: any) => void): void;
beforeHighlight(pickedColors: any): void;
beforeSelect(pickedColors: any): void;
clearPick(): void;
pick(layers: ILayer[], target: IInteractionTarget): boolean;
destroy(): void;
}
export interface ITileLayerManager extends IBaseTileLayerManager{
tilePickManager: ITilePickManager;
tilePickService: ITilePickService;
pickLayers(target: IInteractionTarget): boolean;
destroy(): void;
}
export interface IBaseTileLayer {
type: string;
sourceLayer: string;
parent: ILayer;
tileLayerManager: IBaseTileLayerManager;

View File

@ -16,7 +16,7 @@ import EarthLayer from './earth';
import MaskLayer from './mask';
import WindLayer from './wind';
import TileDebugLayer from './tile/tileTest';
import TileDebugLayer from './tile/tileFactory/layers/tileTest';
// import ConfigSchemaValidationPlugin from './plugins/ConfigSchemaValidationPlugin';
import DataMappingPlugin from './plugins/DataMappingPlugin';

View File

@ -206,9 +206,6 @@ export default class FillModel extends BaseModel {
size: 1,
update: (
feature: IEncodeFeature,
featureIdx: number,
vertex: number[],
attributeIdx: number,
) => {
const { size = 5 } = feature;
return Array.isArray(size) ? [size[0]] : [size as number];
@ -231,9 +228,6 @@ export default class FillModel extends BaseModel {
size: 1,
update: (
feature: IEncodeFeature,
featureIdx: number,
vertex: number[],
attributeIdx: number,
) => {
const { shape = 2 } = feature;
const shape2d = this.layer.getLayerConfig().shape2d as string[];

View File

@ -0,0 +1,122 @@
import {
ILayer,
IPickingService,
IRendererService,
IInteractionTarget,
ITileRenderService,
} from '@antv/l7-core';
import { EventEmitter } from 'eventemitter3';
export class TilePickService extends EventEmitter{
public isLastPicked: boolean = false;
private rendererService: IRendererService;
private pickingService: IPickingService;
private children: ILayer[];
private parent: ILayer;
private tileRenderService: ITileRenderService;
constructor(
parent: ILayer,
rendererService: IRendererService,
pickingService: IPickingService,
children: ILayer[],
tileRenderService: ITileRenderService
) {
super();
this.parent = parent;
this.rendererService = rendererService;
this.pickingService = pickingService;
this.children = children;
this.tileRenderService = tileRenderService;
}
public pick(layers: ILayer[], target: IInteractionTarget) {
// Tip: 在进行拾取渲染的时候也需要先渲染一遍父组件然后再渲染子组件
// 如需要在 栅格瓦片存在 Mask 的时候发生的拾取,那么就需要先渲染父组件(渲染父组件的帧缓冲)
this.tileRenderService.renderMask(this.parent);
const isPicked = layers
.filter(
(layer) =>
this.parent.needPick(target.type) &&
layer.inited &&
layer.isVisible(),
)
.some((layer) => {
layer.hooks.beforePickingEncode.call();
if (layer.masks.length > 0) {
// 清除上一次的模版缓存
this.rendererService.clear({
stencil: 0,
depth: 1,
framebuffer: null,
});
layer.masks.map((m: ILayer) => {
m.hooks.beforeRender.call();
m.render();
m.hooks.afterRender.call();
});
}
layer.renderModels(true);
layer.hooks.afterPickingEncode.call();
const layerPicked = this.pickingService.pickFromPickingFBO(
layer,
target,
);
// RasterLayer 不参与拾取后的 shader 计算
if (layerPicked && this.parent.type !== 'RasterLayer') {
this.emit('pick', {
type: target.type,
pickedColors: this.pickingService.pickedColors,
layer,
});
this.pickingService.pickedTileLayers = [this.parent];
}
return layerPicked;
});
if (
this.parent.type !== 'RasterLayer' &&
!isPicked &&
this.isLastPicked &&
target.type !== 'click'
) {
// 只有上一次有被高亮选中,本次未选中的时候才需要清除选中状态
this.pickingService.pickedTileLayers = [];
this.emit('unpick', {});
this.beforeHighlight([0, 0, 0]);
}
this.isLastPicked = isPicked;
return isPicked;
}
public clearPick() {
this.children
.filter((child) => child.inited && child.isVisible())
.map((layer) => {
layer.hooks.beforeSelect.call([0, 0, 0]);
});
this.pickingService.pickedTileLayers = [];
}
public beforeHighlight(pickedColors: any) {
this.children
.filter((child) => child.inited && child.isVisible())
.map((child) => {
child.hooks.beforeHighlight.call(pickedColors);
});
}
public beforeSelect(pickedColors: any) {
this.children
.filter((child) => child.inited && child.isVisible())
.map((layer) => {
layer.hooks.beforeSelect.call(pickedColors);
});
}
public destroy(): void {
this.removeAllListeners();
}
}

View File

@ -0,0 +1,81 @@
import {
IMapService,
IRendererService
} from '@antv/l7-core';
import { DOM, Tile } from '@antv/l7-utils';
export function readRasterValue(
tile: Tile,
mapService: IMapService,
x: number,
y: number,
) {
const bbox = tile?.bboxPolygon?.bbox || [0, 0, 10, -10];
const [minLng = 0, minLat = 0, maxLng = 10, maxLat = -10] = bbox;
const tileXY = mapService.lngLatToContainer([minLng, minLat]);
const tileMaxXY = mapService.lngLatToContainer([maxLng, maxLat]);
const tilePixelWidth = tileMaxXY.x - tileXY.x;
const tilePixelHeight = tileXY.y - tileMaxXY.y;
const pos = [
(x - tileXY.x) / tilePixelWidth, // x
(y - tileMaxXY.y) / tilePixelHeight, // y
];
const tileWidth = tile?.data?.width || 1;
const tileHeight = tile?.data?.height || 1;
const indexX = Math.floor(pos[0] * tileWidth);
const indexY = Math.floor(pos[1] * tileHeight);
const index = Math.max(0, indexY - 1) * tileWidth + indexX;
const data = tile?.data?.data[index];
return data;
}
export function readPixel(
x: number,
y: number,
rendererService: IRendererService,
) {
const { readPixels, getContainer } = rendererService;
const xInDevicePixel = x * DOM.DPR;
const yInDevicePixel = y * DOM.DPR;
let { width, height } = getContainerSize(
getContainer() as HTMLCanvasElement | HTMLElement,
);
width *= DOM.DPR;
height *= DOM.DPR;
if (
xInDevicePixel > width - 1 * DOM.DPR ||
xInDevicePixel < 0 ||
yInDevicePixel > height - 1 * DOM.DPR ||
yInDevicePixel < 0
) {
return false;
}
const pickedColors = readPixels({
x: Math.floor(xInDevicePixel),
// 视口坐标系原点在左上,而 WebGL 在左下,需要翻转 Y 轴
y: Math.floor(height - (y + 1) * DOM.DPR),
width: 1,
height: 1,
data: new Uint8Array(1 * 1 * 4),
});
return pickedColors;
}
function getContainerSize(container: HTMLCanvasElement | HTMLElement) {
if ((container as HTMLCanvasElement).getContext) {
return {
width: (container as HTMLCanvasElement).width / DOM.DPR,
height: (container as HTMLCanvasElement).height / DOM.DPR,
};
} else {
return container.getBoundingClientRect();
}
}

View File

@ -0,0 +1,106 @@
import {
ILayer,
} from '@antv/l7-core';
import { decodePickingColor } from '@antv/l7-utils';
export function clearPickState(layers: ILayer[]) {
layers
.filter((layer) => layer.inited && layer.isVisible())
.filter((layer) => layer.getCurrentSelectedId() !== null)
.map((layer) => {
selectFeature(layer, new Uint8Array([0, 0, 0, 0]));
layer.setCurrentSelectedId(null);
});
}
export function setSelect(layers: ILayer[], pickedColors: any, renderList: ILayer[]) {
const selectedId = decodePickingColor(pickedColors);
let pickColor
layers.map((layer) => {
if (
layer.getCurrentSelectedId() === null ||
selectedId !== layer.getCurrentSelectedId()
) {
selectFeature(layer, pickedColors);
layer.setCurrentSelectedId(selectedId);
pickColor = pickedColors;
} else {
selectFeature(layer, new Uint8Array([0, 0, 0, 0])); // toggle select
layer.setCurrentSelectedId(null);
pickColor = null;
}
});
// unselect normal layer
renderList
.filter(
(layer) =>
layer.inited &&
!layer.isVector &&
layer.isVisible() &&
layer.needPick('click'),
)
.filter((layer) => layer.getCurrentSelectedId() !== null)
.map((layer) => {
selectFeature(layer, new Uint8Array([0, 0, 0, 0]));
layer.setCurrentSelectedId(null);
});
return pickColor;
}
export function setHighlight(layers: ILayer[], pickedColors: any) {
const pickId = decodePickingColor(pickedColors);
layers.filter((layer) => layer.inited && layer.isVisible() && layer.isVector)
// Tip: 使用 vectorLayer 上的 pickID 优化高亮操作(过滤重复操作)
// @ts-ignore
.filter((layer) => layer.getPickID() !== pickId)
.map((layer) => {
// @ts-ignore
layer.setPickID(pickId);
layer.hooks.beforeHighlight.call(pickedColors);
});
}
export function setPickState(layers: ILayer[], pickColors: { select: any, active: any }) {
if (pickColors.select) {
layers.map((layer) => {
// if(layer.modelLoaded) {
// selectFeature(layer, this.pickColors.select);
// } else {
// layer.once('modelLoaded', () => {
// selectFeature(layer, this.pickColors.select);
// })
// }
selectFeature(layer, pickColors.select);
});
}
if (pickColors.active) {
layers
.filter((layer) => layer.inited && layer.isVisible())
.map((layer) => {
layer.hooks.beforeHighlight.call(pickColors.active);
});
}
}
export function selectFeature(layer: ILayer, pickedColors: Uint8Array | undefined) {
// @ts-ignore
const [r, g, b] = pickedColors;
layer.hooks.beforeSelect.call([r, g, b]);
}
export function setFeatureSelect(color: any, layers: ILayer[]) {
const id = decodePickingColor(color);
layers.map((layer) => {
selectFeature(layer, color);
layer.setCurrentSelectedId(id);
});
}
export function setFeatureActive(color: any, layers: ILayer[]) {
const id = decodePickingColor(color);
layers.map((layer) => {
layer.hooks.beforeHighlight.call(color);
layer.setCurrentPickId(id);
});
}

View File

@ -2,10 +2,8 @@ import {
ILayer,
IMapService,
IRendererService,
IScaleValue,
ISource,
ISubLayerInitOptions,
ScaleAttributeType,
} from '@antv/l7-core';
import { Tile } from '@antv/l7-utils';
@ -48,9 +46,4 @@ export interface ITileFactory {
createLayer(option: ILayerTileConfig): ILayer;
updateStyle(styles: ITileStyles): string;
setStyleAttributeField(
layer: ILayer,
type: ScaleAttributeType,
value: IScaleValue,
): void;
}

View File

@ -6,6 +6,7 @@ import {
} from '@antv/l7-core';
import { Tile } from '@antv/l7-utils';
import { ITileFactory, getTileFactory, TileType } from '../tileFactory';
import { registerLayers } from '../utils';
export class TileManager {
public sourceLayer: string;
public parent: ILayer;
@ -16,18 +17,27 @@ export class TileManager {
protected initOptions: ISubLayerInitOptions;
public createTile(tile: Tile) {
return this.tileFactory.createTile(tile, this.initOptions);
const layerCollections = this.tileFactory.createTile(tile, this.initOptions);
// // regist layer
registerLayers(this.parent, layerCollections.layers);
layerCollections.layers.map(layer => {
layer.once('modelLoaded', () => {
tile.layerLoad();
})
})
return layerCollections;
}
public addChild(layer: ILayer) {
this.children.push(layer);
}
public addChilds(layers: ILayer[]) {
public addChildren(layers: ILayer[]) {
this.children.push(...layers);
}
public removeChilds(layerIDList: string[], refresh = true) {
public removeChildren(layerIDList: string[], refresh = true) {
const remveLayerList: ILayer[] = [];
const cacheLayerList: ILayer[] = [];
this.children.filter((child) => {
@ -47,7 +57,7 @@ export class TileManager {
layer.destroy();
}
public getChilds(layerIDList: string[]) {
public getChildren(layerIDList: string[]) {
return this.children.filter((child) => layerIDList.includes(child.id));
}

View File

@ -6,18 +6,24 @@ import {
IRendererService,
ISubLayerInitOptions,
ITileLayerManager,
ITilePickManager,
ITilePickService,
ITileRenderService,
ITransform,
ScaleAttributeType,
} from '@antv/l7-core';
import { TileManager } from './baseTileManager';
import { TileManager } from './base';
import { generateColorRamp, IColorRamp } from '@antv/l7-utils';
import { getLayerShape, getMaskValue, updateLayersConfig } from '../utils';
import TileConfigManager, { ITileConfigManager } from './tileConfigManager';
import TilePickManager from './tilePickerManager';
import { getLayerShape, getMaskValue } from '../utils';
import { TileStyleService, ITileStyleService } from '../style/TileStyleService';
import { TilePickService } from '../interaction/TilePickService';
import { TileRenderService } from '../render/TileRenderService';
import { styles, IStyles, Attributes } from '../style/constants';
import { updateTexture, updateLayersConfig, setStyleAttributeField } from '../style/utils';
export class TileLayerManager extends TileManager implements ITileLayerManager {
public tilePickManager: ITilePickManager;
public tileConfigManager: ITileConfigManager;
public tilePickService: ITilePickService;
public tileStyleService: ITileStyleService;
public tileRenderService: ITileRenderService
private transforms: ITransform[];
constructor(
parent: ILayer,
@ -33,13 +39,16 @@ export class TileLayerManager extends TileManager implements ITileLayerManager {
this.rendererService = rendererService;
this.transforms = transforms;
this.tilePickManager = new TilePickManager(
this.tileRenderService = new TileRenderService(rendererService);
this.tilePickService = new TilePickService(
parent,
rendererService,
pickingService,
this.children,
this.tileRenderService
);
this.tileConfigManager = new TileConfigManager();
this.tileStyleService = new TileStyleService();
this.setSubLayerInitOption();
this.setConfigListener();
@ -47,12 +56,12 @@ export class TileLayerManager extends TileManager implements ITileLayerManager {
}
public render(): void {
this.tileConfigManager?.checkConfig(this.parent);
this.tilePickManager?.normalRender(this.children);
this.tileStyleService.checkConfig(this.parent);
this.tileRenderService.render(this.children);
}
public pickLayers(target: IInteractionTarget) {
return this.tilePickManager?.pickRender(this.children, target);
return this.tilePickService.pick(this.children, target);
}
private setSubLayerInitOption() {
@ -88,11 +97,11 @@ export class TileLayerManager extends TileManager implements ITileLayerManager {
pixelConstantRGB = 0.1,
} = this.parent.getLayerConfig() as ISubLayerInitOptions;
const colorValue = this.tileConfigManager.getAttributeScale(
const colorValue = this.tileStyleService.getAttributeScale(
this.parent,
'color',
);
const sizeValue = this.tileConfigManager.getAttributeScale(
const sizeValue = this.tileStyleService.getAttributeScale(
this.parent,
'size',
);
@ -146,92 +155,55 @@ export class TileLayerManager extends TileManager implements ITileLayerManager {
}
}
private setConfigListener() {
// RasterLayer PolygonLayer LineLayer PointLayer
// All Tile Layer Need Listen
this.tileConfigManager.setConfig('opacity', this.initOptions.opacity);
this.tileConfigManager.setConfig('zIndex', this.initOptions.zIndex);
this.tileConfigManager.setConfig('mask', this.initOptions.mask);
if (this.parent.type === 'RasterLayer') {
// Raster Tile Layer Need Listen
this.tileConfigManager.setConfig(
'rampColors',
this.initOptions.rampColors,
);
this.tileConfigManager.setConfig('domain', this.initOptions.domain);
this.tileConfigManager.setConfig('clampHigh', this.initOptions.clampHigh);
this.tileConfigManager.setConfig('clampLow', this.initOptions.clampLow);
this.tileConfigManager.setConfig(
'pixelConstant',
this.initOptions.pixelConstant,
);
this.tileConfigManager.setConfig(
'pixelConstantR',
this.initOptions.pixelConstantR,
);
this.tileConfigManager.setConfig(
'pixelConstantG',
this.initOptions.pixelConstantG,
);
this.tileConfigManager.setConfig(
'pixelConstantB',
this.initOptions.pixelConstantB,
);
this.tileConfigManager.setConfig(
'pixelConstantRGB',
this.initOptions.pixelConstantRGB,
);
} else {
// Vector Tile Layer Need Listen
this.tileConfigManager.setConfig('stroke', this.initOptions.stroke);
this.tileConfigManager.setConfig(
'strokeWidth',
this.initOptions.strokeWidth,
);
this.tileConfigManager.setConfig(
'strokeOpacity',
this.initOptions.strokeOpacity,
);
this.tileConfigManager.setConfig(
'color',
this.parent.getAttribute('color')?.scale,
);
this.tileConfigManager.setConfig(
'shape',
this.parent.getAttribute('shape')?.scale,
);
this.tileConfigManager.setConfig(
'size',
this.parent.getAttribute('size')?.scale,
);
private getInitOptionValue(field: string) {
switch(field) {
case 'color': return this.parent.getAttribute('color')?.scale;
case 'shape': return this.parent.getAttribute('shape')?.scale;
case 'size': return this.parent.getAttribute('size')?.scale;
// @ts-ignore
default: return this.initOptions[field];
}
}
this.tileConfigManager.on('updateConfig', (updateConfigs) => {
private setInitOptionValue(field: string, value: any) {
// @ts-ignore
this.initOptions[field] = value;
}
private setConfigListener() {
const styleConfigs = styles[this.parent.type as IStyles] || [];
styleConfigs.map(style => {
this.tileStyleService.setConfig(style, this.getInitOptionValue(style));
})
this.tileStyleService.on('updateConfig', (updateConfigs) => {
updateConfigs.map((key: string) => {
this.updateStyle(key);
return '';
return this.updateStyle(key);
});
});
}
private updateStyle(style: string) {
let updateValue = null;
if (['size', 'color', 'shape'].includes(style)) {
private updateAttribute(style: string) {
if(Attributes.includes(style)) {
const scaleValue = this.parent.getAttribute(style)?.scale;
if (!scaleValue) {
return;
}
updateValue = scaleValue;
this.children.map((child) => {
this.tileFactory.setStyleAttributeField(
return setStyleAttributeField(
child,
this.parent,
style as ScaleAttributeType,
scaleValue,
);
return '';
});
}
}
private updateStyle(style: string) {
let updateValue = null;
if (Attributes.includes(style)) {
this.updateAttribute(style);
} else {
const layerConfig = this.parent.getLayerConfig() as ISubLayerInitOptions;
if (!(style in layerConfig)) {
@ -240,24 +212,20 @@ export class TileLayerManager extends TileManager implements ITileLayerManager {
// @ts-ignore
const config = layerConfig[style];
updateValue = config;
updateLayersConfig(this.children, style, config);
if (style === 'rampColors' && config) {
const { createTexture2D } = this.rendererService;
const imageData = generateColorRamp(config as IColorRamp) as ImageData;
this.initOptions.colorTexture = createTexture2D({
data: imageData.data,
width: imageData.width,
height: imageData.height,
flipY: false,
});
updateLayersConfig(this.children, 'colorTexture', this.initOptions.colorTexture);
switch(style) {
case 'rampColors':
const texture = updateTexture(config, this.children, this.rendererService)
this.initOptions.colorTexture = texture;
break;
default:
updateLayersConfig(this.children, style, config);
}
}
// @ts-ignore
this.initOptions[style] = updateValue;
this.setInitOptionValue(style, updateValue);
}
public destroy(): void {
this.tilePickManager.destroy();
this.tilePickService.destroy();
}
}

View File

@ -5,7 +5,7 @@ import {
ISubLayerInitOptions,
IBaseTileLayerManager,
} from '@antv/l7-core';
import { TileManager } from './baseTileManager';
import { TileManager } from './base';
import { getLayerShape, getMaskValue } from '../utils';
export class BaseMapTileLayerManager extends TileManager implements IBaseTileLayerManager {
// only support vector layer
@ -91,5 +91,4 @@ export class BaseMapTileLayerManager extends TileManager implements IBaseTileLay
workerEnabled,
};
}
}

View File

@ -1,169 +0,0 @@
import {
IInteractionTarget,
ILayer,
IPickingService,
IRendererService,
ITilePickManager,
} from '@antv/l7-core';
import { EventEmitter } from 'eventemitter3';
export default class TilePickManager extends EventEmitter
implements ITilePickManager {
public isLastPicked: boolean = false;
private rendererService: IRendererService;
private pickingService: IPickingService;
private children: ILayer[];
private parent: ILayer;
constructor(
parent: ILayer,
rendererService: IRendererService,
pickingService: IPickingService,
children: ILayer[],
) {
super();
this.parent = parent;
this.rendererService = rendererService;
this.pickingService = pickingService;
this.children = children;
}
/**
*
* @param layers
*/
public normalRender(layers: ILayer[]) {
layers
.filter((layer) => layer.inited)
.filter((layer) => layer.isVisible())
.map((layer) => {
layer.hooks.beforeRenderData.call();
layer.hooks.beforeRender.call();
if (layer.masks.length > 0) {
// 清除上一次的模版缓存
this.rendererService.clear({
stencil: 0,
depth: 1,
framebuffer: null,
});
layer.masks.map((m: ILayer) => {
m.hooks.beforeRenderData.call();
m.hooks.beforeRender.call();
m.render();
m.hooks.afterRender.call();
});
}
layer.render();
layer.hooks.afterRender.call();
});
}
public pickRender(layers: ILayer[], target: IInteractionTarget) {
// Tip: 在进行拾取渲染的时候也需要先渲染一遍父组件然后再渲染子组件
// 如需要在 栅格瓦片存在 Mask 的时候发生的拾取,那么就需要先渲染父组件(渲染父组件的帧缓冲)
if (this.parent.type === 'RasterLayer') {
this.renderMask(this.parent);
}
const isPicked = layers
.filter(
(layer) =>
this.parent.needPick(target.type) &&
layer.inited &&
layer.isVisible(),
)
.some((layer) => {
layer.hooks.beforePickingEncode.call();
if (layer.masks.length > 0) {
// 清除上一次的模版缓存
this.rendererService.clear({
stencil: 0,
depth: 1,
framebuffer: null,
});
layer.masks.map((m: ILayer) => {
m.hooks.beforeRender.call();
m.render();
m.hooks.afterRender.call();
});
}
layer.renderModels(true);
layer.hooks.afterPickingEncode.call();
const layerPicked = this.pickingService.pickFromPickingFBO(
layer,
target,
);
// RasterLayer 不参与拾取后的 shader 计算
if (layerPicked && this.parent.type !== 'RasterLayer') {
this.emit('pick', {
type: target.type,
pickedColors: this.pickingService.pickedColors,
layer,
});
this.pickingService.pickedTileLayers = [this.parent];
}
return layerPicked;
});
if (
this.parent.type !== 'RasterLayer' &&
!isPicked &&
this.isLastPicked &&
target.type !== 'click'
) {
// 只有上一次有被高亮选中,本次未选中的时候才需要清除选中状态
this.pickingService.pickedTileLayers = [];
this.emit('unpick', {});
this.beforeHighlight([0, 0, 0]);
}
this.isLastPicked = isPicked;
return isPicked;
}
public clearPick() {
this.children
.filter((child) => child.inited && child.isVisible())
.map((layer) => {
layer.hooks.beforeSelect.call([0, 0, 0]);
});
this.pickingService.pickedTileLayers = [];
}
public beforeHighlight(pickedColors: any) {
this.children
.filter((child) => child.inited && child.isVisible())
.map((child) => {
child.hooks.beforeHighlight.call(pickedColors);
});
}
public beforeSelect(pickedColors: any) {
this.children
.filter((child) => child.inited && child.isVisible())
.map((layer) => {
layer.hooks.beforeSelect.call(pickedColors);
});
}
protected renderMask(layer: ILayer) {
if (layer.inited && layer.isVisible()) {
layer.hooks.beforeRender.call();
if (layer.masks.length > 0) {
this.rendererService.clear({
stencil: 0,
depth: 1,
framebuffer: null,
});
layer.masks.map((m: ILayer) => {
m.hooks.beforeRender.call();
m.render();
m.hooks.afterRender.call();
});
}
layer.hooks.afterRender.call();
}
}
public destroy(): void {
this.removeAllListeners();
}
}

View File

@ -1,7 +1,7 @@
import { IModelUniform } from '@antv/l7-core';
import BaseModel from '../../core/BaseModel';
import { TMSTileLayer } from '../tmsTileLayer';
import { TMSBaseMapTileLayer } from '../tmsMapTileLayer';
import { TileLayer } from '../tileLayer/TileLayer';
import { MapTileLayer } from '../tileLayer/MapTileLayer';
export default class TileModel extends BaseModel {
public getUninforms(): IModelUniform {
return {};
@ -10,9 +10,9 @@ export default class TileModel extends BaseModel {
private getTileLayer(usage?: string) {
switch(usage) {
case 'basemap':
return TMSBaseMapTileLayer;
return MapTileLayer;
default:
return TMSTileLayer;
return TileLayer;
}
}

View File

@ -0,0 +1,55 @@
import { ILayer, IRendererService, ITileRenderService } from '@antv/l7-core';
/**
*
*/
export class TileRenderService implements ITileRenderService{
private rendererService: IRendererService;
constructor(rendererService: IRendererService) {
this.rendererService = rendererService;
}
public render(layers: ILayer[]) {
layers
.filter((layer) => layer.inited)
.filter((layer) => layer.isVisible())
.map((layer) => {
layer.hooks.beforeRenderData.call();
layer.hooks.beforeRender.call();
if (layer.masks.length > 0) {
// 清除上一次的模版缓存
this.rendererService.clear({
stencil: 0,
depth: 1,
framebuffer: null,
});
layer.masks.map((m: ILayer) => {
m.hooks.beforeRenderData.call();
m.hooks.beforeRender.call();
m.render();
m.hooks.afterRender.call();
});
}
layer.render();
layer.hooks.afterRender.call();
});
}
public renderMask(layer: ILayer) {
if (layer.inited && layer.isVisible() && layer.masks.length > 0) {
layer.hooks.beforeRender.call();
this.rendererService.clear({
stencil: 0,
depth: 1,
framebuffer: null,
});
layer.masks.map((m: ILayer) => {
m.hooks.beforeRender.call();
m.render();
m.hooks.afterRender.call();
});
layer.hooks.afterRender.call();
}
}
}

View File

@ -1,14 +1,14 @@
import { ILayer, IScaleValue, ISubLayerInitOptions } from '@antv/l7-core';
import EventEmitter from 'eventemitter3';
import { isEqual } from 'lodash';
export interface ITileConfigManager {
export interface ITileStyleService {
setConfig(key: string, value: any): void;
checkConfig(layer: ILayer): void;
on(event: string, fn: (...args: any[]) => void): void;
getAttributeScale(layer: ILayer, name: string): IScaleValue;
}
export default class TileConfigManager extends EventEmitter {
export class TileStyleService extends EventEmitter {
public cacheConfig: Map<string, any>;
public checkConfigList: string[] = [];
constructor() {

View File

@ -0,0 +1,58 @@
/**
*
*/
export const Attributes = ['size', 'color', 'shape'];
const common = [
'opacity',
'zIndex',
]
const rasterLayer = [
'mask',
'rampColors',
'domain',
'clampHigh',
'clampLow',
'pixelConstant',
'pixelConstantR',
'pixelConstantG',
'pixelConstantB',
'pixelConstantRGB',
...common
]
const pointLayer = [
'stroke',
'strokeWidth',
'strokeOpacity',
'color',
'shape',
'size',
...common
]
const lineLayer = [
'stroke',
'strokeWidth',
'strokeOpacity',
'color',
'shape',
'size',
...common
]
const polygonLayer = [
'color',
'shape',
...common
]
export type IStyles = 'PointLayer'| 'LineLayer' | 'PolygonLayer' | 'RasterLayer' | 'MaskLayer' | 'TileDebugLayer';
export const styles = {
'PointLayer': pointLayer,
'LineLayer': lineLayer,
'PolygonLayer': polygonLayer,
'RasterLayer': rasterLayer,
'MaskLayer': [],
'TileDebugLayer': [],
}

View File

@ -0,0 +1,134 @@
import {
ILayer,
IRendererService,
ScaleAttributeType,
IScaleValue
} from '@antv/l7-core';
import { generateColorRamp, IColorRamp } from '@antv/l7-utils';
export function updateTexture(config: IColorRamp, layers: ILayer[], rendererService: IRendererService) {
const { createTexture2D } = rendererService;
const imageData = generateColorRamp(config) as ImageData;
const texture = createTexture2D({
data: imageData.data,
width: imageData.width,
height: imageData.height,
flipY: false,
});
layers.map(layer => {
layer.updateLayerConfig({
colorTexture: texture
});
})
return texture;
}
export function updateLayersConfig(layers: ILayer[], key: string, value: any) {
layers.map((layer) => {
if (key === 'mask') {
// Tip: 栅格瓦片生效、设置全局的 mask、瓦片被全局的 mask 影响
layer.style({
mask: value,
});
} else {
layer.updateLayerConfig({
[key]: value,
});
}
});
}
export function setStyleAttributeField(
layer: ILayer,
parent: ILayer,
style: ScaleAttributeType,
value: IScaleValue | undefined | string | string[],
) {
if (Array.isArray(value)) {
// @ts-ignore
layer[style](...value);
return;
}
if (typeof value === 'string') {
layer[style](value);
return;
}
const defaultValue = getDefaultStyleAttributeField(layer, parent.type, style);
if (!value) {
layer[style](defaultValue);
return layer;
}
const params = parseScaleValue(value, style);
if (params.length === 0) {
layer[style](defaultValue);
} else {
// @ts-ignore
layer[style](...params);
}
}
export function getDefaultStyleAttributeField(layer: ILayer, type: string, style: string) {
switch (style) {
case 'size':
return 1;
case 'color':
return '#fff';
case 'shape':
return getLayerShape(type, layer);
default:
return '';
}
}
export function getLayerShape(layerType: string, layer: ILayer) {
const layerShape = layer.getAttribute('shape');
if (layerShape && layerShape.scale?.field) {
if (layerShape.scale?.values === 'text') {
return [layerShape.scale.field, layerShape.scale.values] as string[];
}
return layerShape.scale.field as string;
}
switch (layerType) {
case 'PolygonLayer':
return 'fill';
case 'LineLayer':
return 'tileline';
case 'PointLayer':
return 'circle';
case 'RasterLayer':
return 'image';
default:
return '';
}
}
export function parseScaleValue(value: IScaleValue | string, type: string) {
if (type === 'shape') {
if (typeof value === 'string') {
return [value];
} else if (value?.field) {
return [value?.field];
} else {
return [];
}
}
const { field, values, callback } = value as IScaleValue;
if (field && values && Array.isArray(values)) {
return [field, values];
} else if (field && callback) {
return [field, callback];
} else if (field) {
return [field];
}
return [];
}
export function setScale(layer: ILayer, parent: ILayer) {
const scaleOptions = parent.tileLayer.scaleField;
const scaleKeys = Object.keys(scaleOptions);
scaleKeys.map((key) => {
layer.scale(key, scaleOptions[key]);
});
}

View File

@ -3,19 +3,14 @@ import {
IMapService,
IParseDataItem,
IRendererService,
IScaleValue,
ISubLayerInitOptions,
ScaleAttributeType,
} from '@antv/l7-core';
import Source from '@antv/l7-source';
import { osmLonLat2TileXY, Tile, TilesetManager } from '@antv/l7-utils';
import {
getLayerShape,
readRasterValue,
registerLayers,
} from '../utils';
import VectorLayer from './vectorLayer';
import { setStyleAttributeField, setScale } from '../style/utils';
import { registerLayers } from '../utils';
import { readRasterValue } from '../interaction/getRasterData';
import VectorLayer from './layers/vectorLayer';
import * as turf from '@turf/helpers';
import union from '@turf/union';
@ -72,6 +67,7 @@ export default class TileFactory implements ITileFactory {
}
public getFeatureData(tile: Tile, initOptions: ISubLayerInitOptions) {
const { sourceLayer, featureId, transforms = [], layerType, shape } = initOptions;
if (!sourceLayer) {
return EMPTY_FEATURE_DATA;
@ -144,7 +140,6 @@ export default class TileFactory implements ITileFactory {
});
if(layerType) layer.type = layerType;
// Tip: sign tile layer
layer.isTileLayer = true; // vector 、raster
@ -158,13 +153,13 @@ export default class TileFactory implements ITileFactory {
layer.source(source);
// set scale attribute field
this.setStyleAttributeField(layer, 'shape', shape);
setStyleAttributeField(layer, this.parentLayer, 'shape', shape);
if(usage !== 'basemap') {
// set scale
this.setScale(layer);
setScale(layer, this.parentLayer);
this.setStyleAttributeField(layer, 'color', color);
this.setStyleAttributeField(layer, 'size', size);
setStyleAttributeField(layer, this.parentLayer, 'color', color);
setStyleAttributeField(layer, this.parentLayer, 'size', size);
} else {
layer.style({
color: basemapColor,
@ -173,7 +168,6 @@ export default class TileFactory implements ITileFactory {
}
// set mask
const layers = [layer];
if (mask && layer.isVector) {
const masklayer = new VectorLayer({layerType: "MaskLayer"})
.source({
@ -186,12 +180,10 @@ export default class TileFactory implements ITileFactory {
}
});
layers.push(masklayer as VectorLayer);
registerLayers(this.parentLayer, [masklayer]);
layer.addMaskLayer(masklayer);
}
// regist layer
registerLayers(this.parentLayer, layers);
this.layers = [layer];
@ -203,68 +195,6 @@ export default class TileFactory implements ITileFactory {
return '';
}
public getDefaultStyleAttributeField(layer: ILayer, type: string) {
switch (type) {
case 'size':
return 1;
case 'color':
return '#fff';
case 'shape':
return getLayerShape(this.parentLayer.type, layer);
default:
return '';
}
}
public setStyleAttributeField(
layer: ILayer,
type: ScaleAttributeType,
value: IScaleValue | undefined | string | string[],
) {
if (Array.isArray(value)) {
// @ts-ignore
layer[type](...value);
return;
}
if (typeof value === 'string') {
layer[type](value);
return;
}
const defaultValue = this.getDefaultStyleAttributeField(layer, type);
if (!value) {
layer[type](defaultValue);
return layer;
}
const params = this.parseScaleValue(value, type);
if (params.length === 0) {
layer[type](defaultValue);
} else {
// @ts-ignore
layer[type](...params);
}
}
protected parseScaleValue(value: IScaleValue | string, type: string) {
if (type === 'shape') {
if (typeof value === 'string') {
return [value];
} else if (value?.field) {
return [value?.field];
} else {
return [];
}
}
const { field, values, callback } = value as IScaleValue;
if (field && values && Array.isArray(values)) {
return [field, values];
} else if (field && callback) {
return [field, callback];
} else if (field) {
return [field];
}
return [];
}
protected getTile(lng: number, lat: number) {
const zoom = this.mapService.getZoom();
const z = Math.ceil(zoom) + this.zoomOffset;
@ -409,14 +339,6 @@ export default class TileFactory implements ITileFactory {
this.parentLayer.emit(eventName, e);
}
private setScale(layer: ILayer) {
const scaleOptions = this.parentLayer.tileLayer.scaleField;
const scaleKeys = Object.keys(scaleOptions);
scaleKeys.map((key) => {
layer.scale(key, scaleOptions[key]);
});
}
private getAllFeatures(featureId: number) {
const allLayers: ILayer[] = this.parentLayer.tileLayer.children;
const features: IParseDataItem[] = [];

View File

@ -1,7 +1,7 @@
import BaseLayer from '../../core/BaseLayer';
import { IRasterLayerStyleOptions } from '../../core/interface';
import RasterModel from '../../raster/models/rasterTile';
import RasterRgbModel from '../../raster/models/rasterRgb';
import BaseLayer from '../../../core/BaseLayer';
import { IRasterLayerStyleOptions } from '../../../core/interface';
import RasterModel from '../../../raster/models/rasterTile';
import RasterRgbModel from '../../../raster/models/rasterRgb';
export default class RasterTiffLayer extends BaseLayer<
Partial<IRasterLayerStyleOptions>

View File

@ -1,6 +1,6 @@
import BaseLayer from '../core/BaseLayer';
import { IBaseLayerStyleOptions } from '../core/interface';
import TileModel from './models/tileModel';
import BaseLayer from '../../../core/BaseLayer';
import { IBaseLayerStyleOptions } from '../../../core/interface';
import TileModel from '../../models/tileModel';
export default class TileDebugLayer extends BaseLayer<IBaseLayerStyleOptions> {
public type: string = 'TileDebugLayer';

View File

@ -12,21 +12,21 @@ import {
IShaderModuleService,
IStyleAttributeService,
} from '@antv/l7-core';
import BaseLayer from '../../core/BaseLayer';
import BaseLayer from '../../../core/BaseLayer';
import {
ILineLayerStyleOptions,
IPointLayerStyleOptions,
IPolygonLayerStyleOptions,
IMaskLayerStyleOptions,
} from '../../core/interface';
import lineFillModel from '../../line/models/tile';
import lineSimpleModel from '../../line/models/simpleTileLine';
} from '../../../core/interface';
import lineFillModel from '../../../line/models/tile';
import lineSimpleModel from '../../../line/models/simpleTileLine';
import pointTextModel from '../../point/models/tileText';
import pointFillModel from '../../point/models/tile';
import polygonFillModel from '../../polygon/models/tile';
import pointTextModel from '../../../point/models/tileText';
import pointFillModel from '../../../point/models/tile';
import polygonFillModel from '../../../polygon/models/tile';
import maskModel from '../../mask/models/fill';
import maskModel from '../../../mask/models/fill';
type ILayerStyleOptions = IPolygonLayerStyleOptions & ILineLayerStyleOptions & IPointLayerStyleOptions & IMaskLayerStyleOptions;

View File

@ -29,9 +29,6 @@ export default class VectorLineTile extends TileFactory {
vectorTileLayer,
source: source as Source,
});
layer.once('modelLoaded', () => {
tile.layerLoad();
})
return {
layers: [layer],
layerIDList: [layer.id],

View File

@ -30,9 +30,6 @@ export default class VectorMaskTile extends TileFactory {
source: source as Source,
needListen: false
});
layer.once('modelLoaded', () => {
tile.layerLoad();
})
return {
layers: [layer],
layerIDList: [layer.id],

View File

@ -30,9 +30,6 @@ export default class VectorPointTile extends TileFactory {
source: source as Source,
needListen: false
});
layer.once('modelLoaded', () => {
tile.layerLoad();
})
return {
layers: [layer],
layerIDList: [layer.id],

View File

@ -29,9 +29,6 @@ export default class VectorPolygonTile extends TileFactory {
vectorTileLayer,
source: source as Source,
});
layer.once('modelLoaded', () => {
tile.layerLoad();
})
return {
layers: [layer],
layerIDList: [layer.id],

View File

@ -26,9 +26,6 @@ export default class RasterTile extends TileFactory {
initOptions,
source,
});
layer.once('modelLoaded', () => {
tile.layerLoad();
})
return {
layers: [layer],
layerIDList: [layer.id],

View File

@ -1,9 +1,8 @@
import { ILayer, ISubLayerInitOptions } from '@antv/l7-core';
import { Tile } from '@antv/l7-utils';
import { ITileFactoryOptions } from '../interface';
import { registerLayers } from '../utils';
import TileFactory from './base';
import RasterDataLayer from './rasterDataLayer';
import RasterDataLayer from './layers/rasterDataLayer';
export default class RasterTiffTile extends TileFactory {
public parentLayer: ILayer;
@ -54,10 +53,6 @@ export default class RasterTiffTile extends TileFactory {
});
this.emitEvent([layer], false);
registerLayers(this.parentLayer, [layer]);
layer.once('modelLoaded', () => {
tile.layerLoad();
})
return {
layers: [layer],
layerIDList: [layer.id],

View File

@ -2,10 +2,7 @@ import { ILayer, ISubLayerInitOptions } from '@antv/l7-core';
import { Tile } from '@antv/l7-utils';
import { ITileFactoryOptions } from '../interface';
import TileFactory from './base';
import VectorLayer from './vectorLayer';
import {
registerLayers,
} from '../utils';
import VectorLayer from './layers/vectorLayer';
export default class TestTile extends TileFactory {
public parentLayer: ILayer;
@ -71,13 +68,6 @@ export default class TestTile extends TileFactory {
text.isTileLayer = true;
line.isTileLayer = true;
registerLayers(this.parentLayer, [line, text]);
text.once('modelLoaded', () => {
tile.layerLoad();
})
line.once('modelLoaded', () => {
tile.layerLoad();
})
return {
layers: [line, text],
layerIDList: [line.id, text.id],

View File

@ -0,0 +1,35 @@
import {
IBaseTileLayer,
ITileLayerOPtions,
IBaseTileLayerManager,
} from '@antv/l7-core';
import { BaseMapTileLayerManager } from '../manager/mapLayerManager';
import { Base } from './base';
export class MapTileLayer extends Base implements IBaseTileLayer {
public tileLayerManager: IBaseTileLayerManager;
constructor({
parent,
rendererService,
mapService,
layerService,
}: ITileLayerOPtions) {
super();
const parentSource = parent.getSource();
const { sourceLayer } =
parentSource?.data?.tilesetOptions || {};
this.sourceLayer = sourceLayer;
this.parent = parent;
this.mapService = mapService;
this.layerService = layerService;
this.tileLayerManager = new BaseMapTileLayerManager(
parent,
mapService,
rendererService,
);
this.initTileSetManager();
}
}

View File

@ -0,0 +1,168 @@
import {
IInteractionTarget,
ILayer,
ITileLayer,
ITileLayerManager,
ITileLayerOPtions,
} from '@antv/l7-core';
import { TileLayerManager } from '../manager/layerManager';
import { Base } from './base';
import { setSelect, setHighlight, setPickState, clearPickState } from '../interaction/utils';
export class TileLayer extends Base implements ITileLayer {
public get children() {
return this.tileLayerManager.children;
}
public tileLayerManager: ITileLayerManager;
private pickColors: {
select: any;
active: any;
} = {
select: null,
active: null,
};
constructor({
parent,
rendererService,
mapService,
layerService,
pickingService,
transforms
}: ITileLayerOPtions) {
super();
const parentSource = parent.getSource();
const { sourceLayer } =
parentSource?.data?.tilesetOptions || {};
this.sourceLayer = sourceLayer;
this.parent = parent;
this.mapService = mapService;
this.layerService = layerService;
this.tileLayerManager = new TileLayerManager(
parent,
mapService,
rendererService,
pickingService,
transforms
);
this.initTileSetManager();
this.bindSubLayerEvent();
this.bindSubLayerPick();
this.scaleField = this.parent.getScaleOptions();
}
public clearPick(type: string) {
// Tip: 瓦片只有在 mousemove 的时候需要设置清除
if (type === 'mousemove') {
this.tileLayerManager.tilePickService.clearPick();
}
}
/**
* select
*/
public clearPickState() {
clearPickState(this.children)
}
/**
*
* @param target
* @returns
*/
public pickLayers(target: IInteractionTarget) {
return this.tileLayerManager.pickLayers(target);
}
public setPickState(layers: ILayer[]) {
setPickState(layers, this.pickColors);
}
private bindSubLayerPick() {
this.tileLayerManager.tilePickService.on('pick', (e) => {
// @ts-ignore
const [r, g, b] = e.pickedColors;
if (e.type === 'click') {
const restLayers = this.children
.filter(
(child) => child.inited && child.isVisible() && child.isVector,
)
.filter((child) => child !== e.layer);
const renderList = this.layerService.getRenderList();
const color = setSelect(restLayers, [r, g, b], renderList)
this.pickColors.select = color;
} else {
setHighlight(this.children, [r, g, b]);
this.pickColors.active = [r, g, b];
}
});
this.tileLayerManager.tilePickService.on('unpick', () => {
this.pickColors.active = null;
});
}
protected bindSubLayerEvent() {
/**
* layer.on('click', (ev) => {}); // 鼠标左键点击图层事件
* layer.on('mouseenter', (ev) => {}); // 鼠标进入图层要素
* layer.on('mousemove', (ev) => {}); // 鼠标在图层上移动时触发
* layer.on('mouseout', (ev) => {}); // 鼠标移出图层要素时触发
* layer.on('mouseup', (ev) => {}); // 鼠标在图层上单击抬起时触发
* layer.on('mousedown', (ev) => {}); // 鼠标在图层上单击按下时触发
* layer.on('contextmenu', (ev) => {}); // 图层要素点击右键菜单
*
*
* layer.on('unclick', (ev) => {}); // 图层外点击
* layer.on('unmousemove', (ev) => {}); // 图层外移动
* layer.on('unmouseup', (ev) => {}); // 图层外鼠标抬起
* layer.on('unmousedown', (ev) => {}); // 图层外单击按下时触发
* layer.on('uncontextmenu', (ev) => {}); // 图层外点击右键
* layer.on('unpick', (ev) => {}); // 图层外的操作的所有事件
*/
this.parent.on('subLayerClick', (e) => {
this.parent.emit('click', { ...e });
});
this.parent.on('subLayerMouseMove', (e) =>
this.parent.emit('mousemove', { ...e }),
);
this.parent.on('subLayerMouseUp', (e) =>
this.parent.emit('mouseup', { ...e }),
);
this.parent.on('subLayerMouseEnter', (e) =>
this.parent.emit('mouseenter', { ...e }),
);
this.parent.on('subLayerMouseOut', (e) =>
this.parent.emit('mouseout', { ...e }),
);
this.parent.on('subLayerMouseDown', (e) =>
this.parent.emit('mousedown', { ...e }),
);
this.parent.on('subLayerContextmenu', (e) =>
this.parent.emit('contextmenu', { ...e }),
);
// vector layer 图层外事件
this.parent.on('subLayerUnClick', (e) =>
this.parent.emit('unclick', { ...e }),
);
this.parent.on('subLayerUnMouseMove', (e) =>
this.parent.emit('unmousemove', { ...e }),
);
this.parent.on('subLayerUnMouseUp', (e) =>
this.parent.emit('unmouseup', { ...e }),
);
this.parent.on('subLayerUnMouseDown', (e) =>
this.parent.emit('unmousedown', { ...e }),
);
this.parent.on('subLayerUnContextmenu', (e) =>
this.parent.emit('uncontextmenu', { ...e }),
);
}
}

View File

@ -0,0 +1,183 @@
import {
ILayer,
IMapService,
ILayerService,
ISource,
} from '@antv/l7-core';
import { Tile, TilesetManager } from '@antv/l7-utils';
import { debounce } from 'lodash';
import { updateTileVisible } from '../utils';
export class Base {
public tileLayerManager: any;
public get children() {
return this.tileLayerManager.children;
}
public sourceLayer: string;
public parent: ILayer;
public initedTileset: boolean = false; // 瓦片是否加载成功
public tilesetManager: TilesetManager | undefined; // 瓦片数据管理器
public scaleField: any;
protected mapService: IMapService;
protected layerService: ILayerService;
protected lastViewStates: {
zoom: number;
latLonBounds: [number, number, number, number];
};
protected mapchange() {
const { latLonBounds, zoom } = this.getCurrentView();
if (this.mapService.version === 'GAODE1.x') {
const { visible } = this.parent.getLayerConfig();
if (zoom < 3 && visible) {
this.parent.updateLayerConfig({ visible: false });
this.layerService.reRender();
} else if (zoom >= 3 && !visible) {
this.parent.updateLayerConfig({ visible: true });
this.layerService.reRender();
}
}
if (
this.lastViewStates &&
this.lastViewStates.zoom === zoom &&
this.lastViewStates.latLonBounds.toString() === latLonBounds.toString()
) {
return;
}
this.lastViewStates = { zoom, latLonBounds };
this.tilesetManager?.throttleUpdate(zoom, latLonBounds);
}
protected getCurrentView() {
const bounds = this.mapService.getBounds();
const latLonBounds: [number, number, number, number] = [
bounds[0][0],
bounds[0][1],
bounds[1][0],
bounds[1][1],
];
const zoom = this.mapService.getZoom();
return { latLonBounds, zoom };
}
protected initTileSetManager() {
const source: ISource = this.parent.getSource();
this.tilesetManager = source.tileset as TilesetManager;
if (!this.initedTileset) {
this.bindTilesetEvent();
this.initedTileset = true;
}
const { latLonBounds, zoom } = this.getCurrentView();
this.tilesetManager?.update(zoom, latLonBounds);
}
private bindTilesetEvent() {
if (!this.tilesetManager) {
return;
}
// 瓦片数据加载成功
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.tilesetManager.on('tile-loaded', (tile: Tile) => {
// 将事件抛出,图层上可以监听使用
});
// 瓦片数据从缓存删除或被执行重新加载
this.tilesetManager.on('tile-unload', (tile: Tile) => {
// 将事件抛出,图层上可以监听使用
this.tileUnLoad(tile);
});
// 瓦片数据加载失败
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.tilesetManager.on('tile-error', (error, tile: Tile) => {
// 将事件抛出,图层上可以监听使用
this.tileError(error);
});
// 瓦片显隐状态更新
this.tilesetManager.on('tile-update', () => {
this.tileUpdate();
});
// 地图视野发生改变
this.mapService.on('zoomend', () => this.viewchange());
this.mapService.on('moveend', () => this.viewchange());
}
public render() {
this.tileLayerManager.render();
}
// 防抖操作
viewchange = debounce(this.mapchange, 200)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public tileLoaded(tile: Tile) {
//
}
public tileError(error: Error) {
console.warn('error:', error);
}
public destroy() {
this.tilesetManager?.destroy();
this.tileLayerManager.destroy();
}
public tileUnLoad(tile: Tile) {
this.tileLayerManager.removeChildren(tile.layerIDList, false);
}
public tileUpdate() {
if (!this.tilesetManager) {
return;
}
this.tilesetManager.tiles
.filter((tile: Tile) => tile.isLoaded)
.map((tile: Tile) => {
if (tile.data?.layers && this.sourceLayer) {
// vector
const vectorTileLayer = tile.data.layers[this.sourceLayer];
const features = vectorTileLayer?.features;
if (!(Array.isArray(features) && features.length > 0)) {
return;
}
}
if (!tile.parentLayerIDList.includes(this.parent.id)) {
const { layers, layerIDList } = this.tileLayerManager.createTile(
tile,
);
tile.parentLayerIDList.push(this.parent.id);
tile.layerIDList.push(...layerIDList);
this.tileLayerManager.addChildren(layers);
this.setPickState(layers)
} else {
if (!tile.isVisibleChange) {
return;
}
const layers = this.tileLayerManager.getChildren(tile.layerIDList);
updateTileVisible(tile, layers, this.layerService);
this.setPickState(layers)
}
});
if (this.tilesetManager.isLoaded) {
// 将事件抛出,图层上可以使用瓦片
this.parent.emit('tiles-loaded', this.tilesetManager.currentTiles);
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public setPickState(layers: ILayer[]) {}
}

View File

@ -1,183 +0,0 @@
import {
ILayer,
ILayerService,
IMapService,
ISource,
IBaseTileLayer,
IBaseTileLayerManager,
ITileLayerOPtions,
} from '@antv/l7-core';
import { Tile, TilesetManager } from '@antv/l7-utils';
import { BaseMapTileLayerManager } from '../manager/baseMapTileLayerManager';
import { debounce } from 'lodash';
export default class BaseTileLayer implements IBaseTileLayer {
public get children() {
return this.tileLayerManager.children;
}
public type: string = 'baseTile';
public sourceLayer: string;
public parent: ILayer;
// 瓦片是否加载成功
public initedTileset: boolean = false;
// 瓦片数据管理器
public tilesetManager: TilesetManager | undefined;
public tileLayerManager: IBaseTileLayerManager;
public scaleField: any;
private lastViewStates: {
zoom: number;
latLonBounds: [number, number, number, number];
};
protected mapService: IMapService;
protected layerService: ILayerService;
constructor({
parent,
rendererService,
mapService,
layerService,
}: ITileLayerOPtions) {
const parentSource = parent.getSource();
const { sourceLayer } =
parentSource?.data?.tilesetOptions || {};
this.sourceLayer = sourceLayer;
this.parent = parent;
this.mapService = mapService;
this.layerService = layerService;
this.tileLayerManager = new BaseMapTileLayerManager(
parent,
mapService,
rendererService,
);
this.initTileSetManager();
}
/**
*
*/
public render() {
if (this.tileLayerManager) {
this.tileLayerManager.render();
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public tileLoaded(tile: Tile) {
//
}
public tileError(error: Error) {
console.warn('error:', error);
}
public tileUnLoad(tile: Tile) {
this.tileLayerManager.removeChilds(tile.layerIDList, false);
}
public tileUpdate() {
// Base Function
if (!this.tilesetManager) {
return;
}
if (this.tilesetManager.isLoaded) {
// 将事件抛出,图层上可以使用瓦片
this.parent.emit('tiles-loaded', this.tilesetManager.currentTiles);
}
}
private initTileSetManager() {
const source: ISource = this.parent.getSource();
this.tilesetManager = source.tileset as TilesetManager;
if (!this.initedTileset) {
this.bindTilesetEvent();
this.initedTileset = true;
}
const { latLonBounds, zoom } = this.getCurrentView();
this.tilesetManager?.update(zoom, latLonBounds);
}
private mapchange() {
const { latLonBounds, zoom } = this.getCurrentView();
if (this.mapService.version === 'GAODE1.x') {
const { visible } = this.parent.getLayerConfig();
if (zoom < 3 && visible) {
this.parent.updateLayerConfig({ visible: false });
this.layerService.reRender();
} else if (zoom >= 3 && !visible) {
this.parent.updateLayerConfig({ visible: true });
this.layerService.reRender();
}
}
if (
this.lastViewStates &&
this.lastViewStates.zoom === zoom &&
this.lastViewStates.latLonBounds.toString() === latLonBounds.toString()
) {
return;
}
this.lastViewStates = { zoom, latLonBounds };
this.tilesetManager?.throttleUpdate(zoom, latLonBounds);
}
private bindTilesetEvent() {
if (!this.tilesetManager) {
return;
}
// 瓦片数据加载成功
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.tilesetManager.on('tile-loaded', (tile: Tile) => {
// 将事件抛出,图层上可以监听使用
});
// 瓦片数据从缓存删除或被执行重新加载
this.tilesetManager.on('tile-unload', (tile: Tile) => {
// 将事件抛出,图层上可以监听使用
this.tileUnLoad(tile);
});
// 瓦片数据加载失败
this.tilesetManager.on('tile-error', (error, tile: Tile) => {
// 将事件抛出,图层上可以监听使用
this.tileError(error);
});
// 瓦片显隐状态更新
this.tilesetManager.on('tile-update', () => {
this.tileUpdate();
});
// 地图视野发生改变
this.mapService.on('zoomend', () => this.viewchange());
this.mapService.on('moveend', () => this.viewchange());
}
// 防抖操作
viewchange = debounce(this.mapchange, 200)
private getCurrentView() {
const bounds = this.mapService.getBounds();
const latLonBounds: [number, number, number, number] = [
bounds[0][0],
bounds[0][1],
bounds[1][0],
bounds[1][1],
];
const zoom = this.mapService.getZoom();
return { latLonBounds, zoom };
}
public destroy() {
this.tilesetManager?.destroy();
}
}

View File

@ -1,383 +0,0 @@
import {
IInteractionTarget,
ILayer,
ILayerService,
IMapService,
ISource,
ITileLayer,
ITileLayerManager,
ITileLayerOPtions,
} from '@antv/l7-core';
import { decodePickingColor, Tile, TilesetManager } from '@antv/l7-utils';
import { TileLayerManager } from '../manager/tileLayerManager';
import { debounce } from 'lodash';
export default class BaseTileLayer implements ITileLayer {
public get children() {
return this.tileLayerManager.children;
}
public type: string = 'baseTile';
public sourceLayer: string;
public parent: ILayer;
// 瓦片是否加载成功
public initedTileset: boolean = false;
// 瓦片数据管理器
public tilesetManager: TilesetManager | undefined;
public tileLayerManager: ITileLayerManager;
public scaleField: any;
private lastViewStates: {
zoom: number;
latLonBounds: [number, number, number, number];
};
protected mapService: IMapService;
protected layerService: ILayerService;
private pickColors: {
select: any;
active: any;
} = {
select: null,
active: null,
};
constructor({
parent,
rendererService,
mapService,
layerService,
pickingService,
transforms
}: ITileLayerOPtions) {
const parentSource = parent.getSource();
const { sourceLayer } =
parentSource?.data?.tilesetOptions || {};
this.sourceLayer = sourceLayer;
this.parent = parent;
this.mapService = mapService;
this.layerService = layerService;
this.tileLayerManager = new TileLayerManager(
parent,
mapService,
rendererService,
pickingService,
transforms
);
this.initTileSetManager();
this.bindSubLayerEvent();
this.bindSubLayerPick();
this.scaleField = this.parent.getScaleOptions();
}
/**
*
*/
public render() {
if (this.tileLayerManager) {
this.tileLayerManager.render();
}
}
public clearPick(type: string) {
if (type === 'mousemove') {
this.tileLayerManager.tilePickManager.clearPick();
}
}
/**
* select
*/
public clearPickState() {
this.children
.filter((child) => child.inited && child.isVisible())
.filter((child) => child.getCurrentSelectedId() !== null)
.map((child) => {
this.selectFeature(child, new Uint8Array([0, 0, 0, 0]));
child.setCurrentSelectedId(null);
});
}
/**
*
* @param target
* @returns
*/
public pickLayers(target: IInteractionTarget) {
return this.tileLayerManager.pickLayers(target);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public tileLoaded(tile: Tile) {
//
}
public tileError(error: Error) {
console.warn('error:', error);
}
public tileUnLoad(tile: Tile) {
this.tileLayerManager.removeChilds(tile.layerIDList, false);
}
public tileUpdate() {
// Base Function
if (!this.tilesetManager) {
return;
}
if (this.tilesetManager.isLoaded) {
// 将事件抛出,图层上可以使用瓦片
this.parent.emit('tiles-loaded', this.tilesetManager.currentTiles);
}
}
protected setPickState(layers: ILayer[]) {
if (this.pickColors.select) {
const selectedId = decodePickingColor(this.pickColors.select);
layers.map((layer) => {
this.selectFeature(layer, this.pickColors.select);
layer.setCurrentSelectedId(selectedId);
});
}
if (this.pickColors.active) {
const selectedId = decodePickingColor(this.pickColors.active);
layers
.filter((layer) => layer.inited && layer.isVisible())
.map((layer) => {
layer.hooks.beforeHighlight.call(this.pickColors.active);
layer.setCurrentPickId(selectedId);
});
}
}
private bindSubLayerPick() {
this.tileLayerManager.tilePickManager.on('pick', (e) => {
// @ts-ignore
const [r, g, b] = e.pickedColors;
if (e.type === 'click') {
const restLayers = this.children
.filter(
(child) => child.inited && child.isVisible() && child.isVector,
)
.filter((child) => child !== e.layer);
this.setSelect(restLayers, [r, g, b]);
} else {
this.setHighlight([r, g, b]);
}
});
this.tileLayerManager.tilePickManager.on('unpick', () => {
this.pickColors.active = null;
});
}
private setHighlight(pickedColors: any) {
const pickId = decodePickingColor(pickedColors);
this.pickColors.active = pickedColors;
this.children
.filter((child) => child.inited && child.isVisible() && child.isVector)
// Tip: 使用 vectorLayer 上的 pickID 优化高亮操作(过滤重复操作)
// @ts-ignore
.filter((child) => child.getPickID() !== pickId)
.map((child) => {
// @ts-ignore
child.setPickID(pickId);
child.hooks.beforeHighlight.call(pickedColors);
});
}
private setSelect(layers: ILayer[], pickedColors: any) {
const selectedId = decodePickingColor(pickedColors);
layers.map((layer) => {
if (
layer.getCurrentSelectedId() === null ||
selectedId !== layer.getCurrentSelectedId()
) {
this.selectFeature(layer, pickedColors);
layer.setCurrentSelectedId(selectedId);
this.pickColors.select = pickedColors;
} else {
this.selectFeature(layer, new Uint8Array([0, 0, 0, 0])); // toggle select
layer.setCurrentSelectedId(null);
this.pickColors.select = null;
}
});
// unselect normal layer
const renderList = this.layerService.getRenderList();
renderList
.filter(
(layer) =>
layer.inited &&
!layer.isVector &&
layer.isVisible() &&
layer.needPick('click'),
)
.filter((layer) => layer.getCurrentSelectedId() !== null)
.map((layer) => {
this.selectFeature(layer, new Uint8Array([0, 0, 0, 0]));
layer.setCurrentSelectedId(null);
});
}
private selectFeature(layer: ILayer, pickedColors: Uint8Array | undefined) {
// @ts-ignore
const [r, g, b] = pickedColors;
layer.hooks.beforeSelect.call([r, g, b]);
}
private bindSubLayerEvent() {
/**
* layer.on('click', (ev) => {}); // 鼠标左键点击图层事件
* layer.on('mouseenter', (ev) => {}); // 鼠标进入图层要素
* layer.on('mousemove', (ev) => {}); // 鼠标在图层上移动时触发
* layer.on('mouseout', (ev) => {}); // 鼠标移出图层要素时触发
* layer.on('mouseup', (ev) => {}); // 鼠标在图层上单击抬起时触发
* layer.on('mousedown', (ev) => {}); // 鼠标在图层上单击按下时触发
* layer.on('contextmenu', (ev) => {}); // 图层要素点击右键菜单
*
*
* layer.on('unclick', (ev) => {}); // 图层外点击
* layer.on('unmousemove', (ev) => {}); // 图层外移动
* layer.on('unmouseup', (ev) => {}); // 图层外鼠标抬起
* layer.on('unmousedown', (ev) => {}); // 图层外单击按下时触发
* layer.on('uncontextmenu', (ev) => {}); // 图层外点击右键
* layer.on('unpick', (ev) => {}); // 图层外的操作的所有事件
*/
this.parent.on('subLayerClick', (e) => {
this.parent.emit('click', { ...e });
});
this.parent.on('subLayerMouseMove', (e) =>
this.parent.emit('mousemove', { ...e }),
);
this.parent.on('subLayerMouseUp', (e) =>
this.parent.emit('mouseup', { ...e }),
);
this.parent.on('subLayerMouseEnter', (e) =>
this.parent.emit('mouseenter', { ...e }),
);
this.parent.on('subLayerMouseOut', (e) =>
this.parent.emit('mouseout', { ...e }),
);
this.parent.on('subLayerMouseDown', (e) =>
this.parent.emit('mousedown', { ...e }),
);
this.parent.on('subLayerContextmenu', (e) =>
this.parent.emit('contextmenu', { ...e }),
);
// vector layer 图层外事件
this.parent.on('subLayerUnClick', (e) =>
this.parent.emit('unclick', { ...e }),
);
this.parent.on('subLayerUnMouseMove', (e) =>
this.parent.emit('unmousemove', { ...e }),
);
this.parent.on('subLayerUnMouseUp', (e) =>
this.parent.emit('unmouseup', { ...e }),
);
this.parent.on('subLayerUnMouseDown', (e) =>
this.parent.emit('unmousedown', { ...e }),
);
this.parent.on('subLayerUnContextmenu', (e) =>
this.parent.emit('uncontextmenu', { ...e }),
);
}
private initTileSetManager() {
const source: ISource = this.parent.getSource();
this.tilesetManager = source.tileset as TilesetManager;
if (!this.initedTileset) {
this.bindTilesetEvent();
this.initedTileset = true;
}
const { latLonBounds, zoom } = this.getCurrentView();
this.tilesetManager?.update(zoom, latLonBounds);
}
private mapchange() {
const { latLonBounds, zoom } = this.getCurrentView();
if (this.mapService.version === 'GAODE1.x') {
const { visible } = this.parent.getLayerConfig();
if (zoom < 3 && visible) {
this.parent.updateLayerConfig({ visible: false });
this.layerService.reRender();
} else if (zoom >= 3 && !visible) {
this.parent.updateLayerConfig({ visible: true });
this.layerService.reRender();
}
}
if (
this.lastViewStates &&
this.lastViewStates.zoom === zoom &&
this.lastViewStates.latLonBounds.toString() === latLonBounds.toString()
) {
return;
}
this.lastViewStates = { zoom, latLonBounds };
this.tilesetManager?.throttleUpdate(zoom, latLonBounds);
}
private bindTilesetEvent() {
if (!this.tilesetManager) {
return;
}
// 瓦片数据加载成功
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.tilesetManager.on('tile-loaded', (tile: Tile) => {
// 将事件抛出,图层上可以监听使用
});
// 瓦片数据从缓存删除或被执行重新加载
this.tilesetManager.on('tile-unload', (tile: Tile) => {
// 将事件抛出,图层上可以监听使用
this.tileUnLoad(tile);
});
// 瓦片数据加载失败
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.tilesetManager.on('tile-error', (error, tile: Tile) => {
// 将事件抛出,图层上可以监听使用
this.tileError(error);
});
// 瓦片显隐状态更新
this.tilesetManager.on('tile-update', () => {
this.tileUpdate();
});
// 地图视野发生改变
this.mapService.on('zoomend', () => this.viewchange());
this.mapService.on('moveend', () => this.viewchange());
}
// 防抖操作
viewchange = debounce(this.mapchange, 200)
private getCurrentView() {
const bounds = this.mapService.getBounds();
const latLonBounds: [number, number, number, number] = [
bounds[0][0],
bounds[0][1],
bounds[1][0],
bounds[1][1],
];
const zoom = this.mapService.getZoom();
return { latLonBounds, zoom };
}
public destroy() {
this.tilesetManager?.destroy();
this.tileLayerManager.destroy();
}
}

View File

@ -1,47 +0,0 @@
import { Tile } from '@antv/l7-utils';
import BaseTileLayer from './tileLayer/baseMapTileLayer';
import { updateTileVisible } from './utils';
export class TMSBaseMapTileLayer extends BaseTileLayer {
public type: string = 'BaseMapTMS';
public tileUnLoad(tile: Tile) {
this.tileLayerManager.removeChilds(tile.layerIDList, false);
}
public tileUpdate() {
if (!this.tilesetManager) {
return;
}
this.tilesetManager.tiles
.filter((tile: Tile) => tile.isLoaded)
.map((tile: Tile) => {
if (tile.data?.layers && this.sourceLayer) {
// vector
const vectorTileLayer = tile.data.layers[this.sourceLayer];
const features = vectorTileLayer?.features;
if (!(Array.isArray(features) && features.length > 0)) {
return;
}
}
if (!tile.parentLayerIDList.includes(this.parent.id)) {
const { layers, layerIDList } = this.tileLayerManager.createTile(
tile,
);
tile.parentLayerIDList.push(this.parent.id);
tile.layerIDList.push(...layerIDList);
this.tileLayerManager.addChilds(layers);
} else {
if (!tile.isVisibleChange) {
return;
}
const layers = this.tileLayerManager.getChilds(tile.layerIDList);
updateTileVisible(tile, layers, this.layerService);
}
});
if (this.tilesetManager.isLoaded) {
// 将事件抛出,图层上可以使用瓦片
this.parent.emit('tiles-loaded', this.tilesetManager.currentTiles);
}
}
}

View File

@ -1,49 +0,0 @@
import { Tile } from '@antv/l7-utils';
import BaseTileLayer from './tileLayer/baseTileLayer';
import { updateTileVisible } from './utils';
export class TMSTileLayer extends BaseTileLayer {
public type: string = 'TMS';
public tileUnLoad(tile: Tile) {
this.tileLayerManager.removeChilds(tile.layerIDList, false);
}
public tileUpdate() {
if (!this.tilesetManager) {
return;
}
this.tilesetManager.tiles
.filter((tile: Tile) => tile.isLoaded)
.map((tile: Tile) => {
if (tile.data?.layers && this.sourceLayer) {
// vector
const vectorTileLayer = tile.data.layers[this.sourceLayer];
const features = vectorTileLayer?.features;
if (!(Array.isArray(features) && features.length > 0)) {
return;
}
}
if (!tile.parentLayerIDList.includes(this.parent.id)) {
const { layers, layerIDList } = this.tileLayerManager.createTile(
tile,
);
tile.parentLayerIDList.push(this.parent.id);
tile.layerIDList.push(...layerIDList);
this.tileLayerManager.addChilds(layers);
this.setPickState(layers);
} else {
if (!tile.isVisibleChange) {
return;
}
const layers = this.tileLayerManager.getChilds(tile.layerIDList);
updateTileVisible(tile, layers, this.layerService);
this.setPickState(layers);
}
});
if (this.tilesetManager.isLoaded) {
// 将事件抛出,图层上可以使用瓦片
this.parent.emit('tiles-loaded', this.tilesetManager.currentTiles);
}
}
}

View File

@ -1,12 +1,7 @@
import {
createLayerContainer,
ILayer,
IMapService,
IRendererService,
ILayerService,
} from '@antv/l7-core';
import { createLayerContainer, ILayer, ILayerService } from '@antv/l7-core';
import { DOM, Tile } from '@antv/l7-utils';
import { Container } from 'inversify';
import { updateLayersConfig } from './style/utils';
export const tileVectorParser = ['mvt', 'geojsonvt', 'testTile'];
@ -72,78 +67,15 @@ export function getContainerSize(container: HTMLCanvasElement | HTMLElement) {
}
}
export function readRasterValue(
tile: Tile,
mapService: IMapService,
x: number,
y: number,
) {
const bbox = tile?.bboxPolygon?.bbox || [0, 0, 10, -10];
const [minLng = 0, minLat = 0, maxLng = 10, maxLat = -10] = bbox;
const tileXY = mapService.lngLatToContainer([minLng, minLat]);
const tileMaxXY = mapService.lngLatToContainer([maxLng, maxLat]);
const tilePixelWidth = tileMaxXY.x - tileXY.x;
const tilePixelHeight = tileXY.y - tileMaxXY.y;
const pos = [
(x - tileXY.x) / tilePixelWidth, // x
(y - tileMaxXY.y) / tilePixelHeight, // y
];
const tileWidth = tile?.data?.width || 1;
const tileHeight = tile?.data?.height || 1;
const indexX = Math.floor(pos[0] * tileWidth);
const indexY = Math.floor(pos[1] * tileHeight);
const index = Math.max(0, indexY - 1) * tileWidth + indexX;
const data = tile?.data?.data[index];
return data;
}
export function readPixel(
x: number,
y: number,
rendererService: IRendererService,
) {
const { readPixels, getContainer } = rendererService;
const xInDevicePixel = x * DOM.DPR;
const yInDevicePixel = y * DOM.DPR;
let { width, height } = getContainerSize(
getContainer() as HTMLCanvasElement | HTMLElement,
);
width *= DOM.DPR;
height *= DOM.DPR;
if (
xInDevicePixel > width - 1 * DOM.DPR ||
xInDevicePixel < 0 ||
yInDevicePixel > height - 1 * DOM.DPR ||
yInDevicePixel < 0
) {
return false;
}
const pickedColors = readPixels({
x: Math.floor(xInDevicePixel),
// 视口坐标系原点在左上,而 WebGL 在左下,需要翻转 Y 轴
y: Math.floor(height - (y + 1) * DOM.DPR),
width: 1,
height: 1,
data: new Uint8Array(1 * 1 * 4),
});
return pickedColors;
}
export function isTileLoaded(tile: Tile) {
return tile.layerIDList.length === tile.loadedLayers;
}
export function isTileChildLoaded(tile: Tile) {
const childs = tile.children;
return childs.filter((child) => isTileLoaded(child)).length === childs.length;
const children = tile.children;
return (
children.filter((child) => isTileLoaded(child)).length === children.length
);
}
export function isTileParentLoaded(tile: Tile) {
@ -167,21 +99,6 @@ export function tileAllLoad(tile: Tile, callback: () => void) {
}, 36);
}
export function updateLayersConfig(layers: ILayer[], key: string, value: any) {
layers.map((layer) => {
if (key === 'mask') {
// Tip: 栅格瓦片生效、设置全局的 mask、瓦片被全局的 mask 影响
layer.style({
mask: value,
});
} else {
layer.updateLayerConfig({
[key]: value,
});
}
});
}
function dispatchTileVisibleChange(tile: Tile, callback: () => void) {
if (tile.isVisible) {
callback();