fix: 修复冲突

This commit is contained in:
象数 2022-10-14 16:25:25 +08:00
commit 8219b8702f
53 changed files with 643 additions and 384 deletions

View File

@ -0,0 +1,135 @@
import { Scene, GaodeMapV2 } from "@antv/l7";
import React, { useEffect } from "react";
import { LineLayer, PointLayer } from "@antv/l7";
const lineList: Feature<LineString>[] = [
{
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: [
[119.988511, 30.269614],
[119.9851, 30.269323],
[119.985438, 30.267852],
[119.990291, 30.267257],
[119.991454, 30.261762],
[119.994974, 30.256115],
[119.983641, 30.246146],
[119.985286, 30.241228],
[119.983351, 30.224089],
[119.985473, 30.221814],
[119.99271, 30.22088],
],
},
}
];
import {
coordAll,
Feature,
featureCollection,
LineString,
point
} from "@turf/turf";
import { debounce } from "lodash";
const id = String(Math.random());
const getPointFeatureCollection = (lineList: Feature<LineString>[]) => {
return featureCollection(
coordAll(featureCollection(lineList)).map((item) => point(item))
);
};
const Demo: React.FC = () => {
useEffect(() => {
const scene = new Scene({
id,
map: new GaodeMapV2({
center: [120.151634, 30.244831],
pitch: 0,
style: "dark",
zoom: 10
})
});
scene.on("loaded", () => {
const lineLayer = new LineLayer();
lineLayer
.source(
featureCollection(
lineList.map((item, index) => {
item.properties = {
index
};
return item;
})
)
)
.size(4)
.color("#f00");
const pointLayer = new PointLayer();
pointLayer
.source(getPointFeatureCollection(lineList))
.size(6)
.shape("circle")
.style({
stroke: "#00f",
strokeWidth: 3
});
scene.addLayer(lineLayer);
scene.addLayer(pointLayer);
let isDrag = false;
let dragFeature: Feature<LineString> | null = null;
let prePosition = [0, 0];
lineLayer.on("mousedown", (e) => {
const { lng, lat } = e.lngLat;
prePosition = [lng, lat];
isDrag = true;
scene.setMapStatus({
dragEnable: false
});
dragFeature = e.feature;
});
scene.on("mousemove", (e) => {
requestAnimationFrame(() => {
if (isDrag) {
const { lng, lat } = e.lnglat;
const [lastLng, lastLat] = prePosition;
if (dragFeature) {
const positions = coordAll(dragFeature);
positions.forEach((position) => {
position[0] += lng - lastLng;
position[1] += lat - lastLat;
});
dragFeature.geometry.coordinates = positions;
lineList[dragFeature.properties?.index] = dragFeature;
}
prePosition = [lng, lat];
pointLayer.setData(getPointFeatureCollection([dragFeature]));
lineLayer.setData(featureCollection(lineList));
// scene.render();
}
});
});
scene.on("mouseup", (e) => {
isDrag = false;
scene.setMapStatus({
dragEnable: true
});
});
});
}, []);
return (
<div>
<div id={id} style={{ height: 400, position: "relative" }} />
</div>
);
};
export default Demo;

View File

@ -0,0 +1,3 @@
### source 更新
<code src="./demos/source-update.tsx"></code>

View File

@ -0,0 +1,3 @@
### 枚举类型
<code src="./cat.tsx"></code>

View File

@ -0,0 +1,85 @@
import { ILayer, PolygonLayer, Scene } from '@antv/l7';
import { Button } from 'antd';
import { Map } from '@antv/l7-maps';
import React, { useEffect, useState } from 'react';
import { useData, addLayers } from './useLine';
export default () => {
const { geoData } = useData();
const [filllayer, setFillLayer] = useState<ILayer>();
const [mapScene, setScene] = useState<Scene>();
const colors = [
['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0'],
['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e'],
['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99'],
['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6'],
['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00'],
['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3'],
];
useEffect(() => {
const scene = new Scene({
id: 'map',
map: new Map({
pitch: 0,
style: 'light',
center: [-96, 37.8],
zoom: 3,
}),
});
if (geoData) {
const layer = new PolygonLayer({})
.source(geoData.county, {
transforms: [
{
type: 'join',
sourceField: 'id',
targetField: 'id',
data: geoData.unemploymentdata,
},
],
})
.shape('fill')
.color('name', colors[0])
.style({
opacity: 1,
});
scene.addLayer(layer);
setScene(scene);
setFillLayer(layer);
layer.on('legend:color', (color) => {
console.log('color', color);
});
addLayers(geoData, scene, layer);
}
return () => {
scene.destroy();
};
}, [geoData]);
const changeColor = () => {
const index = Math.round(Math.random() * 6);
filllayer?.color('name', colors[index]);
mapScene?.render();
console.log(filllayer?.getLegend('color'));
};
return (
<div>
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
<Button onClick={changeColor} type="primary" size={'large'}>
</Button>
</div>
);
};

View File

@ -0,0 +1,144 @@
import { useEffect, useState } from 'react';
import { LineLayer, PolygonLayer } from '@antv/l7';
interface IData {
county: any;
state: any;
unemploymentdata: any;
}
interface IData2 {
country: any;
turnout: any;
}
export function useData() {
const [data, setData] = useState<IData | undefined>(undefined);
useEffect(() => {
Promise.all([
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/5c4c7e02-a796-4c09-baba-629a99c909aa.json',
).then((d) => d.json()),
// https://lab.isaaclin.cn/nCoV/api/area?latest=1
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/738993d1-cc7e-4630-a318-80d6452fd125.csv',
).then((d) => d.text()),
fetch(
' https://gw.alipayobjects.com/os/bmw-prod/d13721bf-f0c2-4897-b6e6-633e6e022c09.json',
).then((d) => d.json()),
]).then(([county, unemployment, state]) => {
const unemploymentdata = unemployment
.split('\n')
.slice(0)
.map((line) => {
const item = line.split(',');
return {
id: item[0],
state: item[1],
county: item[2],
rate: item[3] * 1,
};
});
setData({
county,
unemploymentdata,
state,
});
});
}, []);
return { geoData: data };
}
export function useEuropeData() {
const [data, setData] = useState<IData2 | undefined>(undefined);
useEffect(() => {
Promise.all([
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/01ff872b-99c6-4e41-bd3a-34c2134da597.json',
).then((d) => d.json()),
// https://lab.isaaclin.cn/nCoV/api/area?latest=1
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/64124f12-e086-4fe6-a900-bd57b410af69.csv',
).then((d) => d.text()),
]).then(([country, turnoutData,]) => {
const turnout = turnoutData
.split('\n')
.slice(0)
.map((line) => {
const item = line.split(',');
return {
country: item[0],
turnout: item[1] *1,
};
});
setData({
country,
turnout,
});
});
}, []);
return { geoData: data };
}
export function addLayers(data: IData, scene, mainLayer) {
const linelayer = new PolygonLayer({})
.source(data.county)
.size(0.5)
.shape('line')
.color('#fff')
.style({
opacity: 1,
});
const stateLayer = new PolygonLayer({})
.source(data.state)
.size(1)
.shape('line')
.color('#fff')
.style({
opacity: 1,
});
scene.addLayer(linelayer);
scene.addLayer(stateLayer);
addhightLayer(scene, mainLayer)
}
export function addEuropeLayers(data: IData2, scene, mainLayer) {
const linelayer = new PolygonLayer({})
.source(data.country)
.size(0.5)
.shape('line')
.color('#fff')
.style({
opacity: 1,
});
scene.addLayer(linelayer);
addhightLayer(scene, mainLayer)
}
function addhightLayer(scene, mainLayer) {
const hightLayer = new LineLayer({
zIndex: 4, // 设置显示层级
name: 'hightlight',
})
.source({
type: 'FeatureCollection',
features: [],
})
.shape('line')
.size(0.8)
.color('#000')
.style({
opacity: 1,
});
scene.addLayer(hightLayer);
mainLayer.on('click', (feature) => {
// console.log(feature)
hightLayer.setData({
type: 'FeatureCollection',
features: [feature.feature],
});
});
}

View File

@ -76,7 +76,7 @@ export default () => {
// thetaOffset: 0.5,
});
source.on('sourceUpdate', () => {
source.on('update', () => {
// console.log(scene.getMapService().version)
// const midPoints = lineAtOffset(source, 0.3, 'arc', 'offset');
const midPoints = lineAtOffset(source, {

View File

@ -78,7 +78,7 @@ export default () => {
.color('#f00')
.style({});
source.on('sourceUpdate', () => {
source.on('update', () => {
console.log(source);
const midPoints = lineAtOffset(source, {
offset: 0.1,

View File

@ -77,7 +77,7 @@ export default () => {
thetaOffset: 0.5,
});
source.on('sourceUpdate', () => {
source.on('update', () => {
const midPoints = lineAtOffset(source, {
offset: 0.1,
shape: 'arc',

View File

@ -68,7 +68,7 @@ export default () => {
.shape('circle')
.size(20)
.color('#f00');
// scene.addLayer(point)
scene.addLayer(point)
scene.on('loaded', () => {
// const point = new PointLayer({
@ -90,7 +90,7 @@ export default () => {
// .size(20)
// .color('#f00');
// scene.addLayer(point)
// point.on('update', ( ) =>point.renderLayers())
fetch(
'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json',
)
@ -145,6 +145,12 @@ export default () => {
},
});
scene.addLayer(heatmapLayer);
// scene.render()
// setTimeout(() =>{
// scene.render();
// }, 1000)
// console.log('rrr')
});
});

View File

@ -42,6 +42,30 @@ export default () => {
],
};
const data2 = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
testOpacity: 0.8,
},
geometry: {
type: 'Polygon',
coordinates: [
[
[113.8623046875, 30.031055426540206],
[115.3232421875, 30.031055426540206],
[115.3232421875, 31.090574094954192],
[113.8623046875, 31.090574094954192],
[113.8623046875, 30.031055426540206],
],
],
},
},
],
};
const layer = new PolygonLayer({})
.source(data)
@ -53,6 +77,16 @@ export default () => {
scene.on('loaded', () => {
scene.addLayer(layer);
setTimeout(() =>{
layer.setData(data2)
}, 200)
layer.on('mousemove', () =>{
console.log('mousemove')
})
layer.on('unmousemove', () =>{
console.log('unmousemove')
})
});
}, []);
return (

View File

@ -79,20 +79,3 @@ export default {
如果传入了错误的配置项则会在控制台给出提示。
## Layer 子类配置项 Schema
Layer 子类可以通过重载 `getConfigSchema()` 方法定义自身的特有属性。例如 `PolygonLayer` 需要定义透明度:
```javascript
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
```

View File

@ -106,27 +106,6 @@ protected setupShaders() {
}
```
### 配置项校验服务
开发者不需要显式调用该服务。
Layer 子类可以通过重载 `getConfigSchema()` 方法定义自身的特有属性。例如 `PolygonLayer` 需要定义透明度,详见[ConfigSchemaValidation 使用方法](ConfigSchemaValidation.md)
```typescript
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
```
以上就是供开发者使用的常见全局服务,下面我们将介绍场景容器及其内部服务。
## Scene 容器
场景可以承载多个图层,与地图底图一一对应。每个场景都有自己独立的容器确保多个场景间服务不会互相干扰,同时继承全局容器以便访问全局服务。容器内服务包括:

View File

@ -31,6 +31,7 @@ import {
IStyleAttribute,
IStyleAttributeService,
IStyleAttributeUpdateOptions,
ScaleTypeName,
StyleAttrField,
StyleAttributeField,
StyleAttributeOption,
@ -106,8 +107,15 @@ export interface IActiveOption {
type ILngLat = [number, number];
export interface ILegend {
type: ScaleTypeName | undefined
field: StyleAttributeField | undefined;
items:LegendItems
}
// 分段图例
export interface ILegendSegmentItem {
field:string;// 图例字段
value: [number, number];
[key: string]: any;
}
@ -177,7 +185,7 @@ export interface IBaseTileLayerManager {
parent: ILayer;
children: ILayer[];
createTile(tile: Tile): { layers: ILayer[]; layerIDList: string[] };
addTile(tile: Tile): { layers: ILayer[]; layerIDList: string[] };
addChild(layer: ILayer): void;
addChildren(layers: ILayer[]): void;
@ -241,6 +249,9 @@ export interface ITileLayerOPtions {
export type LayerEventType =
| 'inited'
| 'legend'
| 'legend:color'
| 'legend:size'
| 'add'
| 'remove'
| 'destroy'
@ -384,7 +395,8 @@ export interface ILayer {
style(options: unknown): ILayer;
hide(): ILayer;
show(): ILayer;
getLegendItems(name: string): LegendItems;
getLegendItems(name: string,index?: number): LegendItems;
getLegend(name: string):ILegend;
setIndex(index: number): ILayer;
isVisible(): boolean;
setMaxZoom(min: number): ILayer;

View File

@ -4,6 +4,7 @@ import {
} from '../renderer/IAttribute';
import { IBufferInitializationOptions } from '../renderer/IBuffer';
import { IElements } from '../renderer/IElements';
import { ILayer } from './ILayerService';
/**
* 1. Layer
@ -225,6 +226,7 @@ export interface IStyleAttributeService {
features: IEncodeFeature[],
startFeatureIdx?: number,
endFeatureIdx?: number,
layer?: ILayer
): void;
/**
*

View File

@ -6,7 +6,7 @@ import { gl } from '../renderer/gl';
import { IAttribute } from '../renderer/IAttribute';
import { IElements } from '../renderer/IElements';
import { IRendererService } from '../renderer/IRendererService';
import { IWorkerOption } from './ILayerService';
import { ILayer, IWorkerOption } from './ILayerService';
import {
IAttributeScale,
IEncodeFeature,
@ -121,6 +121,7 @@ export default class StyleAttributeService implements IStyleAttributeService {
features: IEncodeFeature[],
startFeatureIdx: number = 0,
endFeatureIdx?: number,
layer?:ILayer
) {
const attributeToUpdate = this.attributes.find(
(attribute) => attribute.name === attributeName,
@ -179,6 +180,11 @@ export default class StyleAttributeService implements IStyleAttributeService {
data: updatedBufferData,
offset: bufferOffsetInBytes,
});
// size color 触发更新事件
layer?.emit(`legend:${attributeName}`,{
type:attributeName,
attr:attributeToUpdate
})
}
}
}

View File

@ -29,17 +29,6 @@ export default class GeometryLayer extends BaseLayer<
});
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getDefaultConfig() {
const type = this.getModelType();
const defaultConfig = {

View File

@ -146,18 +146,6 @@ export default class BillBoardModel extends BaseModel {
}
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected registerBuiltinAttributes() {
this.styleAttributeService.registerStyleAttribute({
name: 'extrude',

View File

@ -356,18 +356,6 @@ export default class PlaneModel extends BaseModel {
}
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected registerBuiltinAttributes() {
// point layer size;
this.styleAttributeService.registerStyleAttribute({

View File

@ -223,18 +223,6 @@ export default class SpriteModel extends BaseModel {
}
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected registerBuiltinAttributes() {
return '';
}

View File

@ -45,17 +45,6 @@ export default class CanvasLayer extends BaseLayer<ICanvasLayerStyleOptions> {
return this;
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getDefaultConfig() {
const type = this.getModelType();
const defaultConfig = {

View File

@ -19,17 +19,6 @@ export default class CityBuildingLayer extends BaseLayer {
time: t,
});
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getModelType(): string {
return 'citybuilding';

View File

@ -24,6 +24,7 @@ import {
ILayerModelInitializationOptions,
ILayerPlugin,
ILayerService,
ILegend,
ILegendClassificaItem,
ILegendSegmentItem,
IMapService,
@ -974,7 +975,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
this.hooks.beforeDestroy.call();
// 清除sources事件
this.layerSource.off('sourceUpdate', this.sourceEvent);
this.layerSource.off('update', this.sourceEvent);
this.multiPassRenderer?.destroy();
@ -1033,7 +1034,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
public setSource(source: Source) {
// 解除原 sources 事件
if (this.layerSource) {
this.layerSource.off('sourceUpdate', this.sourceEvent);
this.layerSource.off('update', this.sourceEvent);
}
this.layerSource = source;
@ -1052,12 +1053,12 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
this.sourceEvent();
});
}
// this.layerSource.inited 为 true sourceUpdate 事件不会再触发
this.layerSource.on('sourceUpdate', () => {
// this.layerSource.inited 为 true update 事件不会再触发
this.layerSource.on('update', () => {
if (this.coordCenter === undefined) {
const layerCenter = this.layerSource.center;
this.coordCenter = layerCenter;
this.mapService.setCoordCenter &&
this.mapService?.setCoordCenter &&
this.mapService.setCoordCenter(layerCenter);
}
this.sourceEvent();
@ -1084,9 +1085,19 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
return this.styleAttributeService.getLayerAttributeScale(name);
}
public getLegend(name: string): ILegend {
const attribute = this.styleAttributeService.getLayerStyleAttribute(name);
const scales = attribute?.scale?.scalers || [];
return {
type: scales[0].option?.type,
field: attribute?.scale?.field,
items: this.getLegendItems(name),
};
}
public getLegendItems(name: string): LegendItems {
const scale = this.styleAttributeService.getLayerAttributeScale(name);
// 函数自定义映射,没有 scale 返回为空数组
if (!scale) {
return [];
@ -1363,10 +1374,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
console.warn('empty fn');
}
protected getConfigSchema() {
throw new Error('Method not implemented.');
}
protected getModelType(): unknown {
throw new Error('Method not implemented.');
}

View File

@ -49,18 +49,6 @@ export default class HeatMapLayer extends BaseLayer<IHeatMapLayerStyleOptions> {
}
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getModelType(): HeatMapModelType {
const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute(
'shape',

View File

@ -15,17 +15,7 @@ export default class ImageLayer extends BaseLayer<IImageLayerStyleOptions> {
this.dispatchModelLoad(models);
});
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getDefaultConfig() {
const type = this.getModelType();
const defaultConfig = {

View File

@ -120,18 +120,6 @@ export default class ImageDataModel extends BaseModel {
this.initModels(callbackModel);
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected registerBuiltinAttributes() {
this.styleAttributeService.registerStyleAttribute({
name: 'uv',

View File

@ -97,18 +97,6 @@ export default class ImageModel extends BaseModel {
this.initModels(callbackModel);
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected registerBuiltinAttributes() {
this.styleAttributeService.registerStyleAttribute({
name: 'uv',

View File

@ -105,18 +105,6 @@ export default class ImageDataModel extends BaseModel {
this.initModels(callbackModel);
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected registerBuiltinAttributes() {
this.styleAttributeService.registerStyleAttribute({
name: 'uv',

View File

@ -39,17 +39,6 @@ export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
});
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getDefaultConfig() {
const type = this.getModelType();
const defaultConfig = {

View File

@ -114,17 +114,6 @@ export default class MaskLayer extends BaseLayer<IMaskLayerStyleOptions> {
this.dispatchModelLoad(models);
});
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getModelType(): MaskModelType {
const parserType = this.layerSource.getParserType();

View File

@ -33,7 +33,14 @@ export default class DataMappingPlugin implements ILayerPlugin {
) {
layer.hooks.init.tapPromise('DataMappingPlugin', async () => {
// 初始化重新生成 map
this.generateMaping(layer, { styleAttributeService });
const source = layer.getSource();
if (source.inited) {
this.generateMaping(layer, { styleAttributeService });
} else {
source.once('update', () => {
this.generateMaping(layer, { styleAttributeService });
});
}
});
layer.hooks.beforeRenderData.tap('DataMappingPlugin', () => {
@ -42,7 +49,7 @@ export default class DataMappingPlugin implements ILayerPlugin {
if (source.inited) {
this.generateMaping(layer, { styleAttributeService });
} else {
source.once('sourceUpdate', () => {
source.once('update', () => {
this.generateMaping(layer, { styleAttributeService });
});
}

View File

@ -25,11 +25,8 @@ export default class DataSourcePlugin implements ILayerPlugin {
if (source.inited) {
this.updateClusterData(layer);
} else {
await new Promise((resolve) => {
source.on('inited', () => {
this.updateClusterData(layer);
resolve(null);
});
source.once('update', () => {
this.updateClusterData(layer);
});
}
});

View File

@ -47,7 +47,7 @@ export default class FeatureScalePlugin implements ILayerPlugin {
if (source.inited) {
callback(source.data);
} else {
source.once('sourceUpdate', () => {
source.once('update', () => {
callback(source.data);
});
}

View File

@ -41,7 +41,7 @@ export default class LayerModelPlugin implements ILayerPlugin {
if (source.inited) {
this.prepareLayerModel(layer);
} else {
source.once('sourceUpdate', () => {
source.once('update', () => {
this.prepareLayerModel(layer);
});
}

View File

@ -52,6 +52,7 @@ export default class UpdateStyleAttributePlugin implements ILayerPlugin {
layer.getEncodedData(), // 获取经过 mapping 最新的数据
attribute.featureRange.startIndex,
attribute.featureRange.endIndex,
layer,
);
attribute.needRegenerateVertices = false;
});

View File

@ -55,17 +55,7 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
}
return 'normal';
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getDefaultConfig() {
const type = this.getModelType();
const defaultConfig = {

View File

@ -26,17 +26,6 @@ export default class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
this.dispatchModelLoad(models);
});
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getModelType(): PolygonModelType {
const parserType = this.layerSource.getParserType();

View File

@ -15,17 +15,7 @@ export default class RaterLayer extends BaseLayer<IRasterLayerStyleOptions> {
this.dispatchModelLoad(models);
});
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getDefaultConfig() {
const type = this.getModelType();
const defaultConfig = {

View File

@ -66,17 +66,6 @@ export default class RasterLayer extends BaseLayer<IRasterLayerStyleOptions> {
return this;
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
private buildRasterModel() {
const source = this.getSource();

View File

@ -7,7 +7,7 @@ import {
import { Tile } from '@antv/l7-utils';
import { ITileFactory, getTileFactory, TileType } from '../tileFactory';
import { registerLayers } from '../utils';
export class TileManager {
export class Base {
public sourceLayer: string;
public parent: ILayer;
public children: ILayer[];
@ -16,10 +16,32 @@ export class TileManager {
protected tileFactory: ITileFactory;
protected initOptions: ISubLayerInitOptions;
public createTile(tile: Tile) {
private tileCache: Map<string, Tile> = new Map()
public hasTile(tile: Tile){
return !!this.tileCache.has(tile.key);
}
public addTile(tile: Tile) {
// oldTile 存在的时候暂时直接结束
// TODO合并不存在的时候
if(this.hasTile(tile)) return {
layers: [],
layerIDList: [],
}
// 存储当前 tile
this.tileCache.set(tile.key, tile);
// 创建 tile 对应的 layers
const layerCollections = this.tileFactory.createTile(tile, this.initOptions);
// // regist layer
registerLayers(this.parent, layerCollections.layers);
// regist layer 将创建出来的 layer 进行注册初始化操作
registerLayers(this.parent, layerCollections.layers);
tile.layerIDList.push(...layerCollections.layerIDList);
// add layer into layerGroup
this.addChildren(layerCollections.layers);
layerCollections.layers.map(layer => {
layer.once('inited', () => {
@ -29,6 +51,11 @@ export class TileManager {
return layerCollections;
}
public removeTile(tile: Tile){
this.tileCache.delete(tile.key);
this.removeChildren(tile.layerIDList, false);
}
public addChild(layer: ILayer) {
this.children.push(layer);
}

View File

@ -11,7 +11,7 @@ import {
ITransform,
ScaleAttributeType,
} from '@antv/l7-core';
import { TileManager } from './base';
import { Base } from './base';
import { generateColorRamp, IColorRamp } from '@antv/l7-utils';
import { getLayerShape, getMaskValue } from '../utils';
import { TileStyleService, ITileStyleService } from '../style/TileStyleService';
@ -20,7 +20,7 @@ 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 {
export class TileLayerManager extends Base implements ITileLayerManager {
public tilePickService: ITilePickService;
public tileStyleService: ITileStyleService;
public tileRenderService: ITileRenderService

View File

@ -5,9 +5,9 @@ import {
ISubLayerInitOptions,
IBaseTileLayerManager,
} from '@antv/l7-core';
import { TileManager } from './base';
import { Base } from './base';
import { getLayerShape, getMaskValue } from '../utils';
export class BaseMapTileLayerManager extends TileManager implements IBaseTileLayerManager {
export class BaseMapTileLayerManager extends Base implements IBaseTileLayerManager {
// only support vector layer
constructor(
parent: ILayer,

View File

@ -28,17 +28,6 @@ export default class RasterTiffLayer extends BaseLayer<
return RasterModel;
}
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getDefaultConfig() {
return {};

View File

@ -222,17 +222,6 @@ export default class VectorLayer extends BaseLayer<
return pointFillModel;
}
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getDefaultConfig() {
return {};

View File

@ -126,57 +126,58 @@ export class Base {
}
public tileError(error: Error) {
console.warn('error:', error);
console.warn('error:', error);
}
public destroy() {
this.tilesetManager?.destroy();
this.tileLayerManager.destroy();
}
this.tilesetManager?.destroy();
this.tileLayerManager.destroy();
}
public tileUnLoad(tile: Tile) {
this.tileLayerManager.removeChildren(tile.layerIDList, false);
public tileUnLoad(tile: Tile) {
this.tileLayerManager.removeTile(tile);
}
public tileUpdate() {
if (!this.tilesetManager) {
return;
}
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;
}
this.tilesetManager.tiles
.filter((tile: Tile) => tile.isLoaded)
.map((tile: Tile) => {
if(!this.isTileReady(tile)) return;
if (!this.tileLayerManager.hasTile(tile)) {
const { layers } = this.tileLayerManager.addTile(tile);
this.setPickState(layers)
} else {
if (!tile.isVisibleChange) {
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);
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);
}
}
public isTileReady(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 false;
}
}
return true;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public setPickState(layers: ILayer[]) {}

View File

@ -23,17 +23,7 @@ export default class WindLayer extends BaseLayer<IWindLayerStyleOptions> {
return this;
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getDefaultConfig() {
const type = this.getModelType();
const defaultConfig = {

View File

@ -158,18 +158,6 @@ export default class WindModel extends BaseModel {
this.wind?.destroy();
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected registerBuiltinAttributes() {
// point layer size;
this.styleAttributeService.registerStyleAttribute({

View File

@ -175,32 +175,39 @@ class Scene
layer.setContainer(layerContainer, this.container);
this.sceneService.addLayer(layer);
const layerConfig = layer.getLayerConfig();
if (layerConfig) {
// 若 layer 未初始化成功,则 layerConfig 为 undefined scene loaded 尚未执行完成)
const {
mask,
maskfence,
maskColor = '#000',
maskOpacity = 0,
} = layerConfig;
if (mask && maskfence) {
const maskInstance = new MaskLayer()
.source(maskfence)
.shape('fill')
.style({
color: maskColor,
opacity: maskOpacity,
});
this.addMask(maskInstance, layer.id);
}
// mask 在 scene loaded 之后执行
if (layer.inited) {
const maskInstance = this.initMask(layer);
this.addMask(maskInstance as ILayer, layer.id);
} else {
console.warn('addLayer should run after scene loaded!');
layer.on('inited', () => {
const maskInstance = this.initMask(layer);
this.addMask(maskInstance as ILayer, layer.id);
})
}
}
public initMask(layer: ILayer) {
const {
mask,
maskfence,
maskColor = '#000',
maskOpacity = 0,
} = layer.getLayerConfig();
if(!mask) return undefined;
const maskInstance = new MaskLayer()
.source(maskfence)
.shape('fill')
.style({
color: maskColor,
opacity: maskOpacity,
});
return maskInstance;
}
public addMask(mask: ILayer, layerId: string) {
if(!mask) return;
const parent = this.getLayer(layerId);
if (parent) {
const layerContainer = createLayerContainer(this.container);

View File

@ -39,6 +39,44 @@ layer.on('add', (type) => console.log(type));
layer.on('remove', (type) => console.log(type));
```
### legend
数据映射更新,图例发生变化,主要color、size
参数 option
- type 映射通道、图例类型
- attr 映射实例
```js
layer.on('legend', (ev) => console.log(ev));
```
### legend:color
数据映射更新,图例发生变化,color 颜色改变
参数 option
- type 映射通道、图例类型
- attr 映射实例
```js
layer.on('legend:color', (ev) => console.log(ev));
```
### legend:size
数据映射更新,图例发生变化,color 大小改变
参数 option
- type 映射通道、图例类型
- attr 映射实例
```js
layer.on('legend:color', (ev) => console.log(ev));
```
## 图层框选
### boxSelect

View File

@ -135,9 +135,25 @@ const size2 = sizeScale('n2'); // 20
获取图例配置
- type 图例类型
- index 可选 默认
```javascript
layer.getLegendItems('color');
layer.getLegendItems('size');
```
### getLegend(type: string)
获取图例 getLegendItems 加强版返回更多信息
返回值
- type 图例类型
- field 映射字段
- items 图例项
```javascript
layer.getLegend('color');
layer.getLegend('size');
```

View File

@ -240,9 +240,11 @@ export default class Source extends EventEmitter implements ISource {
}
private async init() {
// this.hooks.init.call(this);
this.inited = false;
await this.handleData();
this.handleData().then(() => {
this.inited = true;
this.emit('update');
});
}
/**

View File

@ -23,7 +23,7 @@ export function lineAtOffsetAsyc(source: Source, option: ILineAtOffset) {
if (source.inited) {
resolve(lineAtOffset(source, option));
} else {
source.once('sourceUpdate', () => {
source.once('update', () => {
resolve(lineAtOffset(source, option));
});
}

View File

@ -24,7 +24,6 @@ export class Tile extends EventEmitter {
public isCurrent = false;
// 是否可以见发生变化
public isVisibleChange = false;
public parentLayerIDList: string[] = [];
public layerIDList: string[] = [];
public loadedLayers: number = 0;

View File

@ -96,7 +96,7 @@ export default class Demo extends React.Component {
},
},
);
source.on('sourceUpdate', () => {
source.on('update', () => {
const layer = new PointLayer();
layer.source(source);
layer
@ -309,7 +309,7 @@ export default class Demo extends React.Component {
.shape('circle')
.size(10)
.color('#f00');
source.on('sourceUpdate', () => {
source.on('update', () => {
layer.source(source);
});
this.scene.addLayer(layer);
@ -356,7 +356,7 @@ export default class Demo extends React.Component {
.shape('circle')
.size(10)
.color('#f00');
source.on('sourceUpdate', () => {
source.on('update', () => {
setTimeout(() => {
layer.source(source);
}, 2000);
@ -390,7 +390,7 @@ export default class Demo extends React.Component {
.shape('circle')
.size(10)
.color('#f00');
source.on('sourceUpdate', () => {
source.on('update', () => {
setTimeout(() => {
layer.source(source);
}, 2000);