chore(l7): remove react,draw, boundary moudule

This commit is contained in:
thinkinggis 2020-09-15 20:21:56 +08:00
parent 4f73e3ff91
commit a924bd4a2b
90 changed files with 6588 additions and 12257 deletions

View File

@ -18,9 +18,6 @@ exports.onCreateWebpackConfig = ({ getConfig }) => {
'@antv/l7-renderer': path.resolve(__dirname, 'packages/renderer/src'),
'@antv/l7-scene': path.resolve(__dirname, 'packages/scene/src'),
'@antv/l7-source': path.resolve(__dirname, 'packages/source/src'),
'@antv/l7-utils': path.resolve(__dirname, 'packages/utils/src'),
'@antv/l7-react': path.resolve(__dirname, 'packages/react/src'),
'@antv/l7-draw': path.resolve(__dirname, 'packages/draw/src'),
'@antv/l7-district': path.resolve(__dirname, 'packages/boundary/src')
};
'@antv/l7-utils': path.resolve(__dirname, 'packages/utils/src')
}
};

View File

@ -7,6 +7,9 @@
},
"devDependencies": {
"@antv/g2": "^3.5.9",
"@antv/l7-draw": "^2.2.37",
"@antv/l7-react": "^2.2.37",
"@antv/l7-district": "^2.2.37",
"@antv/gatsby-theme-antv": "^0.10.71",
"@babel/cli": "^7.6.4",
"@babel/core": "^7.6.4",

View File

@ -1,11 +0,0 @@
# `district`
> TODO: description
## Usage
```
const district = require('district');
// TODO: DEMONSTRATE API
```

View File

@ -1,34 +0,0 @@
// import { WorldLayer } from '@antv/l7-district';
describe('baseLayer', () => {
it('set option', () => {
const option = {
adcode: [],
data: [
{
name: 1,
code: 2,
},
{
name: 2,
code: 3,
},
{
name: 3,
code: 4,
},
],
};
// @ts-ignore
// const layer = new WorldLayer(null, option);
// layer.setOption({
// data: [
// {
// name: 1,
// code: 4,
// },
// ],
// });
// // @ts-ignore
// expect(layer.options.data.length).toBe(1);
});
});

View File

@ -1,62 +0,0 @@
{
"name": "@antv/l7-district",
"version": "2.2.37",
"description": "L7 district moudules",
"keywords": [],
"author": "thinkinggis <lzx199065@gmail.com>",
"license": "ISC",
"main": "lib/index.js",
"module": "es/index.js",
"unpkg": "dist/l7-district.js",
"types": "es/index.d.ts",
"sideEffects": true,
"files": [
"dist",
"lib",
"es",
"README.md"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/antvis/L7.git"
},
"scripts": {
"tsc": "tsc --project tsconfig.build.json",
"clean": "rimraf dist; rimraf es; rimraf lib;",
"build": "run-p build:*",
"build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"build:cdn": "node_modules/.bin/rollup -c",
"test": "jest",
"sync": "tnpm sync"
},
"dependencies": {
"@antv/l7": "2.2.37",
"@babel/runtime": "^7.7.7",
"@turf/circle": "^6.0.1",
"@turf/distance": "^6.0.1",
"@turf/helpers": "^6.1.4",
"@turf/midpoint": "^5.1.5",
"@turf/turf": "^5.1.6",
"eventemitter3": "^4.0.0",
"geobuf": "^3.0.1",
"lodash": "^4.6.2",
"pbf": "^3.2.1",
"simplify-geojson": "^1.0.3"
},
"bugs": {
"url": "https://github.com/antvis/L7/issues"
},
"homepage": "https://github.com/antvis/L7#readme",
"devDependencies": {
"postcss": "^7.0.27",
"postcss-url": "^8.0.0",
"rollup": "^2.3.3",
"rollup-plugin-less": "^1.1.2"
},
"gitHead": "20154fe30d512024b03ac5e40f77731bc0580bb0"
}

View File

@ -1,51 +0,0 @@
import pkg from './package.json';
import typescript from 'rollup-plugin-typescript';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import buble from 'rollup-plugin-buble';
import postcss from 'rollup-plugin-postcss';
import { terser } from 'rollup-plugin-terser';
import url from 'postcss-url';
export default {
input: './src/index.ts',
plugins: [
// less(),
typescript({
exclude: 'node_modules/**',
typescript: require('typescript')
}),
resolve({
preferBuiltins: false
}),
postcss({
plugins: [
url({ url: 'inline' })
]
}),
commonjs({
namedExports: {
eventemitter3: [ 'EventEmitter' ],
lodash: [ 'merge', 'mergeWith', 'clone', 'isObject' ]
}
}),
buble({
transforms: { generator: false }
}),
terser()
],
external: [
'@antv/l7'
],
output: [
{
format: 'umd',
name: 'L7.District',
file: pkg.unpkg,
sourcemap: true,
globals: {
'@antv/l7': 'L7'
}
}
]
};

View File

@ -1,263 +0,0 @@
// tslint:disable-next-line:no-submodule-imports
import merge from 'lodash/merge';
let DataLevel = 2; // d
const dataLevel2: { [key: string]: any } = {
world: {
fill: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/ad26cd25-96ea-40fd-935d-7e21a5c08893.bin',
},
line: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/62f61f5f-cca7-4137-845d-13c8f9969664.bin',
},
label: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/90c51eb3-04d7-402f-bd05-95e4bd27dd62.bin',
parser: {
type: 'geojson',
},
},
nationalBoundaries: {
type: 'json',
url:
'https://gw.alipayobjects.com/os/bmw-prod/ee493a41-0558-4c0e-bee6-520276c4f1a8.json',
},
},
country: {
CHN: {
1: {
fill: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/25228941-b2ac-4591-b07d-8261ac08d06f.bin',
},
line: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/70ec087e-c48a-4b76-8825-6452f17bae7a.bin',
},
provinceLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/0024caaf-86b2-4e75-a3d1-6d2146490b67.bin',
},
label: {
type: 'json',
url:
'https://gw.alipayobjects.com/os/bmw-prod/36832a45-68f8-4b51-b006-9dec71f92a23.json',
},
},
2: {
fill: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/522c6496-c711-4581-88db-c3741cd39abd.bin',
},
line: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/f6a4e2b1-359b-43a6-921c-39d2088d1dab.bin',
},
cityLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/f6a4e2b1-359b-43a6-921c-39d2088d1dab.bin',
},
provinceLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/0024caaf-86b2-4e75-a3d1-6d2146490b67.bin',
},
},
3: {
fill: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/516b2703-d692-44e6-80dd-b3f5df0186e7.bin',
},
line: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/bc97875a-90f2-42c0-a62c-43d2efd7460d.bin',
},
countryLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/bc97875a-90f2-42c0-a62c-43d2efd7460d.bin',
},
cityLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/8bfbfe7e-bd0e-4bbe-84d8-629f4dc7abc4.bin',
},
provinceLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/778ad7ba-5a3f-4ed6-a94a-b8ab8acae9d6.bin',
},
},
nationalBoundaries: {
type: 'json',
url:
'https://gw.alipayobjects.com/os/bmw-prod/ee493a41-0558-4c0e-bee6-520276c4f1a8.json',
},
nationalBoundaries2: {
type: 'json',
url:
'https://gw.alipayobjects.com/os/bmw-prod/f2189cc4-662b-4358-8573-36f0f918b7ca.json',
},
island: {
type: 'json',
url:
'https://gw.alipayobjects.com/os/bmw-prod/fe49b393-1147-4769-94ed-70471f4ff15d.json',
},
},
},
province: {
110000: '',
},
};
const dataLevel1: { [key: string]: any } = {
world: {
fill: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/35bb8365-1926-471c-b357-db2c02ff3a81.bin',
},
line: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/8ec671c3-a4f9-4fdf-8e88-85d2ab1d8930.bin',
},
label: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/90c51eb3-04d7-402f-bd05-95e4bd27dd62.bin',
parser: {
type: 'geojson',
},
},
nationalBoundaries: {
type: 'json',
url:
'https://gw.alipayobjects.com/os/bmw-prod/ee493a41-0558-4c0e-bee6-520276c4f1a8.json',
},
},
country: {
CHN: {
1: {
fill: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/380370e0-76aa-4240-8874-5732de77e71d.bin',
},
line: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/70ec087e-c48a-4b76-8825-6452f17bae7a.bin',
},
provinceLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/778ad7ba-5a3f-4ed6-a94a-b8ab8acae9d6.bin',
},
label: {
type: 'json',
url:
'https://gw.alipayobjects.com/os/bmw-prod/36832a45-68f8-4b51-b006-9dec71f92a23.json',
},
},
2: {
fill: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/feeb1f06-11c6-4495-84c9-f41ea6f77123.bin',
},
line: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/8bfbfe7e-bd0e-4bbe-84d8-629f4dc7abc4.bin',
},
cityLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/8bfbfe7e-bd0e-4bbe-84d8-629f4dc7abc4.bin',
},
provinceLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/778ad7ba-5a3f-4ed6-a94a-b8ab8acae9d6.bin',
},
},
3: {
fill: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/24a9ee83-2be1-4fc1-b187-769ac939269d.bin',
},
line: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/bc97875a-90f2-42c0-a62c-43d2efd7460d.bin',
},
countryLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/bc97875a-90f2-42c0-a62c-43d2efd7460d.bin',
},
cityLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/8bfbfe7e-bd0e-4bbe-84d8-629f4dc7abc4.bin',
},
provinceLine: {
type: 'pbf',
url:
'https://gw.alipayobjects.com/os/bmw-prod/778ad7ba-5a3f-4ed6-a94a-b8ab8acae9d6.bin',
},
},
nationalBoundaries: {
type: 'json',
url:
'https://gw.alipayobjects.com/os/bmw-prod/ee493a41-0558-4c0e-bee6-520276c4f1a8.json',
},
nationalBoundaries2: {
type: 'json',
url:
'https://gw.alipayobjects.com/os/bmw-prod/f2189cc4-662b-4358-8573-36f0f918b7ca.json',
},
island: {
type: 'json',
url:
'https://gw.alipayobjects.com/os/bmw-prod/fe49b393-1147-4769-94ed-70471f4ff15d.json',
},
},
},
province: {
110000: '',
},
};
const DataLevelMap: { [key: string]: any } = {
1: dataLevel1, // 高精度数据
2: dataLevel2,
};
function setDataConfig(config: any, level: number = DataLevel) {
merge(DataLevelMap[level], config);
}
function getDataConfig(level: number = DataLevel) {
return DataLevelMap[level];
}
function setDataLevel(level: number) {
DataLevel = level;
}
const DataConfig = DataLevelMap[DataLevel];
export { setDataConfig, setDataLevel, getDataConfig, DataConfig };

View File

@ -1,17 +0,0 @@
// import { DataConfig, setDataConfig } from './config_1';
import CityLayer from './layer/city';
import CountryLayer from './layer/country';
import CountyLayer from './layer/county';
import DrillDownLayer from './layer/drillDown';
import ProvinceLayer from './layer/province';
import WorldLayer from './layer/world';
export {
WorldLayer,
CountryLayer,
ProvinceLayer,
CityLayer,
CountyLayer,
DrillDownLayer,
};
export * from './config';
export * from './layer/interface';

View File

@ -1,380 +0,0 @@
import {
ILayer,
IPopup,
LineLayer,
PointLayer,
PolygonLayer,
Popup,
Scene,
StyleAttrField,
} from '@antv/l7';
import { EventEmitter } from 'eventemitter3';
// @ts-ignore
import geobuf from 'geobuf';
// tslint:disable-next-line: no-submodule-imports
import isObject from 'lodash/isObject';
// tslint:disable-next-line: no-submodule-imports
import mergeWith from 'lodash/mergeWith';
// @ts-ignore
import Pbf from 'pbf';
// @ts-ignore
import simplify from 'simplify-geojson';
import { setDataLevel } from '../config';
import { AttributeType, IDistrictLayerOption } from './interface';
function mergeCustomizer(objValue: any, srcValue: any) {
if (Array.isArray(srcValue)) {
return srcValue;
}
}
export default class BaseLayer extends EventEmitter {
public fillLayer: ILayer;
public lineLayer: ILayer;
public labelLayer: ILayer;
public bubbleLayer: ILayer;
protected scene: Scene;
protected options: IDistrictLayerOption;
protected layers: ILayer[] = [];
protected fillData: any;
protected bubbleData: any;
private popup: IPopup;
constructor(scene: Scene, option: Partial<IDistrictLayerOption> = {}) {
super();
this.scene = scene;
this.options = mergeWith(this.getDefaultOption(), option, mergeCustomizer);
setDataLevel(this.options.geoDataLevel);
}
public destroy() {
this.layers.forEach((layer) => this.scene.removeLayer(layer));
this.layers.length = 0;
}
public show() {
this.layers.forEach((layer) => layer.show());
}
public hide() {
this.layers.forEach((layer) => layer.hide());
}
public setOption(newOption: { [key: string]: any }) {
this.options = mergeWith(this.options, newOption, mergeCustomizer);
}
public getFillData() {
return this.fillData;
}
public updateData(
newData?: Array<{ [key: string]: any }>,
joinByField?: [string, string],
) {
this.setOption({
data: newData,
joinBy: joinByField,
});
const { data = [], joinBy } = this.options;
this.fillLayer.setData(this.fillData, {
transforms:
data.length === 0
? []
: [
{
type: 'join',
sourceField: joinBy[1], // data1 对应字段名
targetField: joinBy[0], // data 对应字段名 绑定到的地理数据
data,
},
],
});
// 气泡图也需要更新
if (this.bubbleLayer) {
this.bubbleLayer.setData(this.bubbleData, {
transforms:
data.length === 0
? []
: [
{
type: 'join',
sourceField: joinBy[1], // data1 对应字段名
targetField: joinBy[0], // data 对应字段名 绑定到的地理数据
data,
},
],
});
}
}
protected async fetchData(data: { url: any; type: string }) {
if (data.type === 'pbf') {
const buffer = await (await fetch(data.url)).arrayBuffer();
let geojson = geobuf.decode(new Pbf(buffer));
if (this.options.simplifyTolerance !== false) {
geojson = simplify(geojson, this.options.simplifyTolerance);
}
return geojson;
} else {
return isObject(data.url) ? data.url : (await fetch(data.url)).json();
}
}
protected getDefaultOption(): IDistrictLayerOption {
return {
zIndex: 0,
visible: true,
geoDataLevel: 2,
depth: 1,
adcode: [],
joinBy: ['name', 'name'],
simplifyTolerance: false,
label: {
enable: true,
color: '#000',
field: 'name',
size: 10,
stroke: '#fff',
strokeWidth: 2,
textAllowOverlap: true,
opacity: 1,
textOffset: [0, 0],
padding: [5, 5],
},
bubble: {
enable: false,
shape: 'circle',
color: '#1AA9FF',
size: 15,
style: {
opacity: 1,
stroke: '#fff',
strokeWidth: 1,
},
},
fill: {
scale: null,
color: '#ddd',
style: {
opacity: 1.0,
},
activeColor: false,
},
autoFit: true,
showBorder: true,
stroke: '#bdbdbd',
strokeVisible: true,
strokeWidth: 0.6,
cityStroke: '#636363',
cityStrokeWidth: 0.6,
countyStrokeWidth: 0.6,
provinceStrokeWidth: 0.6,
provinceStroke: '#f0f0f0',
provinceStrokeVisible: true,
countyStroke: '#525252',
coastlineStroke: '#4190da',
coastlineWidth: 0.6,
nationalStroke: '#c994c7',
nationalWidth: 0.5,
chinaNationalStroke: 'gray',
chinaNationalWidth: 1,
popup: {
enable: true,
openTriggerEvent: 'mousemove',
closeTriggerEvent: 'mouseout',
option: {},
Html: (properties: any) => {
return `${properties.name}`;
},
},
};
}
protected addFillLayer(fillCountry: any) {
// 添加省份填充
const { popup, data = [], fill, autoFit, joinBy, visible } = this.options;
this.fillData = fillCountry;
const fillLayer = new PolygonLayer({
autoFit,
visible,
}).source(fillCountry, {
transforms:
data.length === 0
? []
: [
{
type: 'join',
sourceField: joinBy[1], // data1 对应字段名
targetField: joinBy[0], // data 对应字段名 绑定到的地理数据
data,
},
],
});
this.setLayerAttribute(fillLayer, 'color', fill.color as AttributeType);
this.setLayerAttribute(fillLayer, 'filter', fill.filter as AttributeType);
if (fill.scale && isObject(fill.color)) {
fillLayer.scale('color', {
type: fill.scale,
field: fill.color.field as string,
});
}
fillLayer.shape('fill').style(fill.style);
if (fill.activeColor) {
fillLayer.active({
color: fill.activeColor as string,
});
}
this.fillLayer = fillLayer;
this.layers.push(fillLayer);
this.scene.addLayer(fillLayer);
if (this.options.bubble && this.options.bubble?.enable !== false) {
const labeldata = fillCountry.features.map((feature: any) => {
return {
...feature.properties,
center: [feature.properties.x, feature.properties.y],
};
});
this.bubbleData = labeldata;
this.addBubbleLayer(labeldata);
}
if (popup.enable) {
this.addPopup();
}
this.emit('loaded');
}
protected addFillLine(provinceLine: any) {
const { stroke, strokeWidth, zIndex, visible } = this.options;
const layer2 = new LineLayer({
zIndex: zIndex + 0.1,
visible,
})
.source(provinceLine)
.color(stroke)
.size(strokeWidth)
.style({
opacity: 1,
});
this.scene.addLayer(layer2);
this.layers.push(layer2);
this.lineLayer = layer2;
}
protected addLabelLayer(labelData: any, type: string = 'json') {
const labelLayer = this.addLabel(labelData, type);
this.scene.addLayer(labelLayer);
this.layers.push(labelLayer);
this.labelLayer = labelLayer;
}
protected addBubbleLayer(labelData: any, type: string = 'json') {
const { bubble, zIndex, data = [], joinBy, visible } = this.options;
const bubbleLayer = new PointLayer({
zIndex: zIndex + 0.3,
visible,
}).source(labelData, {
parser: {
type,
coordinates: 'center',
},
transforms:
data.length === 0
? []
: [
{
type: 'join',
sourceField: joinBy[1], // data1 对应字段名
targetField: joinBy[0], // data 对应字段名 绑定到的地理数据
data,
},
],
});
this.setLayerAttribute(bubbleLayer, 'color', bubble.color as AttributeType);
this.setLayerAttribute(bubbleLayer, 'size', bubble.size as AttributeType);
this.setLayerAttribute(bubbleLayer, 'shape', bubble.shape as AttributeType);
this.setLayerAttribute(
bubbleLayer,
'filter',
bubble.filter as AttributeType,
);
if (bubble.scale) {
bubbleLayer.scale(bubble.scale.field, {
type: bubble.scale.type,
});
}
bubbleLayer.style(bubble.style);
this.scene.addLayer(bubbleLayer);
this.layers.push(bubbleLayer);
this.bubbleLayer = bubbleLayer;
return bubbleLayer;
}
protected addLabel(labelData: any, type: string = 'json') {
const { label, zIndex, visible } = this.options;
const labelLayer = new PointLayer({
zIndex: zIndex + 5,
visible,
})
.source(labelData, {
parser: {
type,
coordinates: 'center',
},
})
.shape(label.field as StyleAttrField, 'text')
.style(label);
this.setLayerAttribute(labelLayer, 'color', label.color as AttributeType);
this.setLayerAttribute(labelLayer, 'size', label.size as AttributeType);
this.setLayerAttribute(labelLayer, 'filter', label.filter);
return labelLayer;
}
protected addPopup() {
const { popup } = this.options;
let popupLayer;
if (popup.triggerLayer) {
popupLayer =
popup.triggerLayer === 'bubble' ? this.bubbleLayer : this.fillLayer;
} else {
popupLayer = this.options.bubble.enable
? this.bubbleLayer
: this.fillLayer;
}
popupLayer.on(popup.openTriggerEvent as string, (e) => {
const html = popup.Html
? popup.Html(e.feature.properties ? e.feature.properties : e.feature)
: '';
this.popup = new Popup({
closeButton: false,
...popup.option,
})
.setLnglat(e.lngLat)
.setHTML(html);
this.scene.addPopup(this.popup);
});
popupLayer.on(popup.closeTriggerEvent as string, (e) => {
if (this.popup) {
this.popup.remove();
}
});
}
private setLayerAttribute(
layer: ILayer,
type: 'color' | 'size' | 'shape' | 'filter',
attr: AttributeType | undefined,
) {
if (!attr) {
return;
}
if (isObject(attr)) {
// @ts-ignore
layer[type](attr.field, attr.values);
} else {
// @ts-ignore
layer[type](attr);
}
}
}

View File

@ -1,41 +0,0 @@
// tslint:disable-next-line: no-submodule-imports
import merge from 'lodash/merge';
import { adcodeType, IDistrictLayerOption } from './interface';
import ProvinceLayer from './province';
export interface IProvinceLayerOption extends IDistrictLayerOption {
adcode: adcodeType;
}
export default class CityLayer extends ProvinceLayer {
protected getDefaultOption(): IProvinceLayerOption {
const config = super.getDefaultOption();
return merge({}, config, {
adcode: ['110000'],
depth: 3,
});
}
protected filterData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.features.filter((fe: any) => {
const code = fe.properties.adcode_cit;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return { type: 'FeatureCollection', features };
}
protected filterLabelData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.filter((fe: any) => {
const code = fe.adcode_cit;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return features;
}
}

View File

@ -1,278 +0,0 @@
import { AttributeType, LineLayer, PointLayer, Scene } from '@antv/l7';
import { getDataConfig } from '../index';
import BaseLayer from './baseLayer';
import { IDistrictLayerOption } from './interface';
export default class CountryLayer extends BaseLayer {
constructor(scene: Scene, option: Partial<IDistrictLayerOption> = {}) {
super(scene, option);
const { depth, showBorder } = this.options;
this.addProvinceFill();
this.addProvinceLabel();
const countryConfig = getDataConfig(this.options.geoDataLevel).country.CHN[
depth
];
if (showBorder) {
this.addProvinceLine(countryConfig.provinceLine);
if (depth === 2 * 1) {
this.addCityBorder(countryConfig.fill);
}
if (depth === 3 * 1) {
this.addCountyBorder(countryConfig.fill);
}
}
}
protected async addProvinceFill() {
const { depth } = this.options;
const countryConfig = getDataConfig(this.options.geoDataLevel).country.CHN[
depth
];
const fillData = await this.fetchData(countryConfig.fill);
this.addFillLayer(fillData);
}
protected async addProvinceLabel() {
const { depth } = this.options;
const countryConfig = getDataConfig(this.options.geoDataLevel).country.CHN[
depth
];
const fillLabel = countryConfig.label
? await this.fetchData(countryConfig.label)
: null;
if (fillLabel && this.options.label?.enable) {
this.addLabelLayer(
fillLabel.filter((v: any) => {
return v.name !== '澳门';
}),
);
this.addMCLabel();
}
}
// 国界,省界
protected async addProvinceLine(cfg: any) {
const lineData = await this.fetchData(cfg);
const border1 = lineData.features.filter((feature: any) => {
const type = feature.properties.type;
return type === '1';
});
// 香港 澳门
const border2 = lineData.features.filter((feature: any) => {
const type = feature.properties.type;
return type === '4';
});
const borderFc = {
type: 'FeatureCollection',
features: border1,
};
const borderFc2 = {
type: 'FeatureCollection',
features: border2,
};
const nationalBorder = lineData.features.filter((feature: any) => {
const type = feature.properties.type;
return type !== '1' && type !== '4';
});
const nationalFc = {
type: 'FeatureCollection',
features: nationalBorder,
};
this.addNationBorder(nationalFc, borderFc, borderFc2);
}
// 国界,省界
// protected addFillLine(lineData: any) {
// const border1 = lineData.features.filter((feature: any) => {
// const type = feature.properties.type;
// return type === '1' || type === '4';
// });
// const borderFc = {
// type: 'FeatureCollection',
// features: border1,
// };
// const nationalBorder = lineData.features.filter((feature: any) => {
// const type = feature.properties.type;
// return type !== '1' && type !== '4';
// });
// const nationalFc = {
// type: 'FeatureCollection',
// features: nationalBorder,
// };
// this.addNationBorder(nationalFc, borderFc);
// }
private async loadData() {
const { depth } = this.options;
const countryConfig = getDataConfig(this.options.geoDataLevel).country.CHN[
depth
];
const fillData = await this.fetchData(countryConfig.fill);
const fillLabel = countryConfig.label
? await this.fetchData(countryConfig.label)
: null;
return [fillData, fillLabel];
}
// 省级行政区划
private async addNationBorder(
boundaries: any,
boundaries2: any,
boundaries3: any,
) {
const {
nationalStroke,
provinceStroke,
provinceStrokeWidth,
nationalWidth,
chinaNationalStroke,
chinaNationalWidth,
coastlineStroke,
coastlineWidth,
showBorder,
stroke,
strokeWidth,
visible,
zIndex,
} = this.options;
// 添加国界线
const lineLayer = new LineLayer({
zIndex: zIndex + 0.1,
visible: visible && showBorder,
})
.source(boundaries)
.size('type', (v: string) => {
if (v === '3') {
return provinceStrokeWidth;
} else if (v === '2') {
return coastlineWidth;
} else if (v === '0') {
return chinaNationalWidth;
} else {
return '#fff';
}
})
.shape('line')
.color('type', (v: string) => {
if (v === '3') {
return provinceStroke; // 省界
} else if (v === '2') {
return coastlineStroke; // 海岸线
} else if (v === '0') {
return chinaNationalStroke; // 中国国界线
} else {
return '#fff';
}
});
// 添加未定国界
const lineLayer2 = new LineLayer({
zIndex: zIndex + 0.1,
visible: visible && showBorder,
})
.source(boundaries2)
.size(chinaNationalWidth)
.shape('line')
.color(chinaNationalStroke)
.style({
lineType: 'dash',
dashArray: [2, 2],
});
// 添加澳门香港界限
const lineLayer3 = new LineLayer({
zIndex: zIndex + 0.1,
visible: visible && showBorder,
})
.source(boundaries3)
.size(provinceStrokeWidth)
.shape('line')
.color(provinceStroke)
.style({
lineType: 'dash',
dashArray: [4, 2, 2, 2],
});
this.scene.addLayer(lineLayer);
this.scene.addLayer(lineLayer2);
this.scene.addLayer(lineLayer3);
this.layers.push(lineLayer, lineLayer2, lineLayer3);
}
// 市边界
private async addCityBorder(cfg: any) {
const border1 = await this.fetchData(cfg);
const { cityStroke, cityStrokeWidth, visible } = this.options;
const cityline = new LineLayer({
zIndex: 2,
visible,
})
.source(border1)
.color(cityStroke)
.size(cityStrokeWidth)
.style({
opacity: 0.5,
});
this.scene.addLayer(cityline);
this.layers.push(cityline);
}
// 县级边界
private async addCountyBorder(cfg: any) {
const border1 = await this.fetchData(cfg);
const { countyStrokeWidth, countyStroke, visible } = this.options;
const cityline = new LineLayer({
zIndex: 2,
visible,
})
.source(border1)
.color(countyStroke)
.size(countyStrokeWidth)
.style({
opacity: 0.5,
});
this.scene.addLayer(cityline);
this.layers.push(cityline);
}
private addMCLabel() {
const data = [
{
name: '澳门',
center: [113.537747, 22.187009],
},
];
const labelLayer1 = this.addText(data, { maxZoom: 2.9 }, [-45, -10]);
const labelLayer2 = this.addText(data, { minZoom: 3, maxZoom: 4 }, [
-35,
-10,
]);
const labelLayer = this.addText(data, { minZoom: 4.1 }, [0, 0]);
this.scene.addLayer(labelLayer);
this.scene.addLayer(labelLayer1);
this.scene.addLayer(labelLayer2);
this.layers.push(labelLayer, labelLayer1, labelLayer2);
}
private addText(labelData: any, option: any, offset: [number, number]) {
const { label, zIndex, visible } = this.options;
const labelLayer = new PointLayer({
zIndex: zIndex + 0.4,
visible,
...option,
})
.source(labelData, {
parser: {
type: 'json',
coordinates: 'center',
},
})
.color(label.color as AttributeType)
.shape('name', 'text')
.size(label.size as AttributeType)
.style({
opacity: label.opacity,
stroke: label.stroke,
strokeWidth: label.strokeWidth,
textAllowOverlap: label.textAllowOverlap,
textOffset: offset,
});
return labelLayer;
}
}

View File

@ -1,41 +0,0 @@
import { Scene } from '@antv/l7';
// tslint:disable-next-line: no-submodule-imports
import merge from 'lodash/merge';
import { adcodeType, IDistrictLayerOption } from './interface';
import ProvinceLayer from './province';
export interface IProvinceLayerOption extends IDistrictLayerOption {
adcode: adcodeType;
}
export default class CityLayer extends ProvinceLayer {
protected getDefaultOption(): IProvinceLayerOption {
const config = super.getDefaultOption();
return merge({}, config, {
adcode: ['110100'],
depth: 3,
});
}
protected filterData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.features.filter((fe: any) => {
const code = fe.properties.adcode;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return { type: 'FeatureCollection', features };
}
protected filterLabelData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.filter((fe: any) => {
const code = fe.adcode;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return features;
}
}

View File

@ -1,204 +0,0 @@
import { Scene } from '@antv/l7';
// tslint:disable-next-line: no-submodule-imports
import mergeWith from 'lodash/mergeWith';
import CityLayer from './city';
import CountryLayer from './country';
import { adcodeType, IDrillDownOption } from './interface';
import ProvinceLayer from './province';
function mergeCustomizer(objValue: any, srcValue: any) {
if (Array.isArray(srcValue)) {
return srcValue;
}
}
export default class DrillDownLayer {
private options: Partial<IDrillDownOption>;
private cityLayer: ProvinceLayer;
private countyLayer: CityLayer;
private provinceLayer: CountryLayer;
private scene: Scene;
private drillState: 0 | 1 | 2 = 0;
private layers: any = [];
constructor(scene: Scene, option: Partial<IDrillDownOption>) {
this.options = mergeWith(this.getDefaultOption(), option, mergeCustomizer);
this.scene = scene;
this.provinceLayer = new CountryLayer(
scene,
this.getLayerOption('province'),
);
this.cityLayer = new ProvinceLayer(scene, this.getLayerOption('city'));
this.countyLayer = new CityLayer(scene, this.getLayerOption('county'));
this.scene.setMapStatus({ doubleClickZoom: false });
if (!this.options.customTrigger) {
this.provinceLayer.on('loaded', () => {
this.addCountryEvent();
this.layers.push(this.provinceLayer);
});
this.cityLayer.on('loaded', () => {
this.addProvinceEvent();
this.layers.push(this.cityLayer);
});
this.countyLayer.on('loaded', () => {
this.addCityEvent();
this.layers.push(this.cityLayer);
});
}
}
public getDefaultOption() {
return {
drillDepth: 2,
customTrigger: false,
drillDownTriggerEvent: 'click',
drillUpTriggerEvent: 'undblclick',
provinceData: [],
cityData: [],
countyData: [],
city: {
adcode: [],
},
county: {
adcode: [],
},
};
}
public addCountryEvent() {
const { drillDownTriggerEvent } = this.options;
// 省级下钻到市
this.provinceLayer.fillLayer.on(
drillDownTriggerEvent as string,
(e: any) => {
this.provinceLayer.hide();
this.drillDown(e.feature.properties.adcode);
},
);
}
public addProvinceEvent() {
const { drillDownTriggerEvent, drillUpTriggerEvent } = this.options;
this.cityLayer.fillLayer.on(drillUpTriggerEvent as string, () => {
this.drillUp();
});
this.cityLayer.fillLayer.on(drillDownTriggerEvent as string, (e: any) => {
this.drillDown(e.feature.properties.adcode);
});
}
public addCityEvent() {
const { drillDownTriggerEvent, drillUpTriggerEvent } = this.options;
this.countyLayer.fillLayer.on(drillUpTriggerEvent as string, () => {
this.drillUp();
});
}
public show() {
this.layers.forEach((layer: any) => layer.show());
}
public hide() {
this.layers.forEach((layer: any) => layer.hide());
}
public destroy() {
this.layers.forEach((layer: any) => layer.destroy());
}
public showProvinceView(
adcode: adcodeType,
newData?: Array<{ [key: string]: any }>,
joinByField?: [string, string],
) {
this.cityLayer.show();
this.cityLayer.updateDistrict(adcode, newData, joinByField);
this.cityLayer.fillLayer.fitBounds();
this.countyLayer.hide();
this.drillState = 1;
}
public showCityView(
code: adcodeType,
newData?: Array<{ [key: string]: any }>,
joinByField?: [string, string],
) {
this.countyLayer.show();
let adcode = `${code}`;
if (adcode.substr(2, 2) === '00') {
adcode = adcode.substr(0, 2) + '0100';
}
// 更新县级行政区划
this.countyLayer.updateDistrict(adcode, newData, joinByField);
this.countyLayer.fillLayer.fitBounds();
this.cityLayer.hide();
this.drillState = 2;
}
/**
*
*/
public drillUp() {
switch (this.drillState) {
case 2:
this.cityLayer.show();
this.cityLayer.fillLayer.fitBounds();
this.countyLayer.hide();
this.drillState = 1;
break;
case 1:
this.provinceLayer.show();
this.provinceLayer.fillLayer.fitBounds();
this.cityLayer.hide();
this.drillState = 0;
break;
}
}
public drillDown(
adcode: adcodeType,
newData?: Array<{ [key: string]: any }>,
joinByField?: [string, string],
) {
const { drillDepth } = this.options;
if (this.drillState === drillDepth) {
return;
}
switch (this.drillState) {
case 0:
this.showProvinceView(adcode, newData, joinByField);
break;
case 1:
this.showCityView(adcode, newData, joinByField);
break;
}
}
public updateData(
layer: 'province' | 'city' | 'county',
newData: Array<{ [key: string]: any }>,
joinByField?: [string, string],
) {
switch (layer) {
case 'province':
this.provinceLayer.updateData(newData, joinByField);
break;
case 'city':
this.cityLayer.updateData(newData, joinByField);
break;
case 'county':
this.countyLayer.updateData(newData, joinByField);
}
}
private getLayerOption(type: 'province' | 'city' | 'county') {
const { joinBy, label, bubble, fill, popup, geoDataLevel } = this.options;
const datatype = (type + 'Data') as
| 'provinceData'
| 'cityData'
| 'countyData';
return {
data: this.options[datatype],
joinBy,
label,
bubble,
fill,
popup,
geoDataLevel,
...this.options[type],
};
}
}

View File

@ -1,153 +0,0 @@
import {
IPopupOption,
ScaleTypeName,
StyleAttributeField,
StyleAttributeOption,
} from '@antv/l7';
export type anchorType =
| 'right'
| 'top-right'
| 'left'
| 'bottom-right'
| 'left'
| 'top-left'
| 'bottom-left'
| 'bottom'
| 'bottom-right'
| 'bottom-left'
| 'top'
| 'top-right'
| 'top-left'
| 'center';
export interface ILabelOption {
enable: boolean;
color: AttributeType;
field: string;
size: AttributeType;
stroke: string;
strokeWidth: number;
textAllowOverlap: boolean;
padding: [number, number];
strokeOpacity: number;
fontWeight: number;
spacing: number;
textAnchor: anchorType;
textOffset: [number, number];
opacity: number;
filter: AttributeType;
}
export interface IAttributeOption {
field: StyleAttributeField;
values: StyleAttributeOption;
}
export type AttributeType = IAttributeOption | string | number;
export interface IPopupOptions {
enable: boolean;
openTriggerEvent: TriggeEventType;
closeTriggerEvent: TriggeEventType;
triggerLayer: 'fill' | 'bubble';
option?: Partial<IPopupOption>;
Html: (properties: any) => string;
}
export interface IFillOptions {
scale: ScaleTypeName | null;
// field: string | null;
color: AttributeType;
values: StyleAttributeOption;
style: any;
activeColor: string | boolean;
filter: AttributeType;
}
export type TriggeEventType =
| 'mousemove'
| 'click'
| 'mousedown'
| 'mouseenter'
| 'mouseout'
| 'dblclick'
| 'contextmenu'
| 'mouseup';
export type DrillUpTriggeEventType =
| 'mousemove'
| 'unclick'
| 'unmousedown'
| 'undblclick'
| 'uncontextmenu'
| 'unmouseup';
export interface IBubbleOption {
enable: boolean;
shape: AttributeType;
size: AttributeType;
color: AttributeType;
filter: AttributeType;
scale: {
field: string;
type: ScaleTypeName;
};
style: {
opacity: number;
stroke: string;
strokeWidth: number;
};
}
export type adcodeType = string[] | string | number | number[];
export interface IDistrictLayerOption {
zIndex: number;
visible: boolean;
geoDataLevel: 1 | 2;
data?: Array<{ [key: string]: any }>;
joinBy: [string, string];
adcode: adcodeType;
simplifyTolerance: number | boolean;
depth: 0 | 1 | 2 | 3;
label: Partial<ILabelOption>;
bubble: Partial<IBubbleOption>;
fill: Partial<IFillOptions>;
showBorder: boolean;
autoFit: boolean;
stroke: string;
strokeVisible: boolean;
strokeWidth: number;
provinceStroke: string;
provinceStrokeVisible: boolean;
cityStroke: string;
provinceStrokeWidth: number;
cityStrokeWidth: number;
countyStroke: string;
countyStrokeWidth: number;
coastlineStroke: string;
coastlineWidth: number;
nationalStroke: string;
nationalWidth: number;
chinaNationalStroke: string;
chinaNationalWidth: number;
popup: Partial<IPopupOptions>;
}
interface IDrawOption {
joinBy: [string, string];
label: Partial<ILabelOption>;
bubble: Partial<IBubbleOption>;
fill: Partial<IFillOptions>;
}
export interface IDrillDownOption {
drillDepth: 0 | 1 | 2;
geoDataLevel: 1 | 2;
customTrigger: boolean;
drillDownTriggerEvent: TriggeEventType;
drillUpTriggerEvent: TriggeEventType & DrillUpTriggeEventType;
provinceData?: Array<{ [key: string]: any }>;
cityData?: Array<{ [key: string]: any }>;
countyData?: Array<{ [key: string]: any }>;
joinBy: [string, string];
label: Partial<ILabelOption>;
bubble: Partial<IBubbleOption>;
fill: Partial<IFillOptions>;
popup: Partial<IPopupOptions>;
province: Partial<IDrawOption>;
city: Partial<IDrawOption>;
county: Partial<IDrawOption>;
}

View File

@ -1,142 +0,0 @@
import {
ILayer,
LineLayer,
PointLayer,
PolygonLayer,
Scene,
StyleAttrField,
} from '@antv/l7';
// tslint:disable-next-line: no-submodule-imports
import merge from 'lodash/merge';
import { getDataConfig } from '../';
import BaseLayer from './baseLayer';
import { adcodeType, IDistrictLayerOption } from './interface';
export interface IProvinceLayerOption extends IDistrictLayerOption {
adcode: adcodeType;
}
export default class ProvinceLayer extends BaseLayer {
private fillRawData: any;
private lineRawData: any;
private labelRawData: any;
constructor(scene: Scene, option: Partial<IProvinceLayerOption> = {}) {
super(scene, option);
this.addProvinceFillLayer();
// this.addProvinceLineLayer();
}
// 通过adcode 更新
public updateDistrict(
adcode: adcodeType,
newData?: Array<{ [key: string]: any }>,
joinByField?: [string, string],
) {
if (!adcode && Array.isArray(adcode) && adcode.length === 0) {
this.hide();
return;
}
const { label, showBorder } = this.options;
this.setOption({ adcode });
const fillData = this.filterData(this.fillRawData, adcode);
const lineData = this.filterData(this.lineRawData, adcode);
const labelData = this.filterLabelData(this.labelRawData, adcode);
if (this.options.bubble && this.options.bubble?.enable !== false) {
const bubbleData = fillData.features.map((feature: any) => {
return {
...feature.properties,
center: [feature.properties.x, feature.properties.y],
};
});
this.bubbleLayer.setData(bubbleData);
}
this.fillData = fillData;
this.updateData(newData, joinByField);
if (showBorder) {
this.lineLayer.setData(lineData);
}
if (label.enable) {
this.labelLayer.setData(labelData);
}
this.show();
}
protected getDefaultOption(): IProvinceLayerOption {
const config = super.getDefaultOption();
return merge({}, config, {
adcode: ['110000'],
depth: 2,
label: {
field: 'NAME_CHN',
textAllowOverlap: false,
},
popup: {
enable: true,
Html: (props: any) => {
return `<span>${props.NAME_CHN}</span>`;
},
},
});
}
protected filterData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.features.filter((fe: any) => {
const code = fe.properties.adcode_pro;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return { type: 'FeatureCollection', features };
}
protected filterLabelData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.filter((fe: any) => {
const code = fe.adcode_pro;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return features;
}
private async addProvinceFillLayer() {
const { depth, adcode, label, showBorder } = this
.options as IProvinceLayerOption;
const countryConfig = getDataConfig(this.options.geoDataLevel).country.CHN[
depth
];
const fillData = await this.fetchData(countryConfig.fill);
this.labelRawData = fillData.features.map((feature: any) => {
return {
...feature.properties,
center: [feature.properties.x, feature.properties.y],
};
});
const data = this.filterData(fillData, adcode);
this.fillData = data;
const labelData = this.filterLabelData(this.labelRawData, adcode);
this.fillRawData = fillData;
this.addFillLayer(data);
if (label.enable) {
this.addLabelLayer(labelData);
}
this.lineRawData = fillData;
if (showBorder) {
this.addFillLine(data);
}
}
private async addProvinceLineLayer() {
const { depth, adcode } = this.options as IProvinceLayerOption;
const countryConfig = getDataConfig(this.options.geoDataLevel).country.CHN[
depth
];
const fillData = await this.fetchData(countryConfig.line);
const data = this.filterData(fillData, adcode);
this.lineRawData = fillData;
this.addFillLine(data);
}
}

View File

@ -1,141 +0,0 @@
import {
ILayer,
LineLayer,
PointLayer,
PolygonLayer,
Scene,
StyleAttrField,
} from '@antv/l7';
import { getDataConfig } from '../';
import BaseLayer from './baseLayer';
import { IDistrictLayerOption } from './interface';
export default class WorldLayer extends BaseLayer {
constructor(scene: Scene, option: Partial<IDistrictLayerOption> = {}) {
super(scene, option);
this.loadData().then(([fillData, lineData, fillLabel]) => {
this.addFillLayer(fillData);
if (this.options.showBorder) {
this.addFillLine(lineData);
}
if (this.options.label?.enable) {
this.addLabelLayer(fillLabel, 'json');
}
});
}
public addFillLine(data: any) {
// 未定国界
const bord1 = data.features.filter((feature: any) => {
return (
feature.properties.type === '10' ||
feature.properties.type === '1' ||
feature.properties.type === '11' ||
feature.properties.type === '8'
);
});
const bordFc = {
type: 'FeatureCollection',
features: bord1,
};
// 已确定国界
const nationalBorder = data.features.filter((feature: any) => {
return (
feature.properties.type !== '10' &&
feature.properties.type !== '1' &&
feature.properties.type !== '11' &&
feature.properties.type !== '8'
);
});
const nationalFc = {
type: 'FeatureCollection',
features: nationalBorder,
};
this.addNationBorder(nationalFc, bordFc);
}
private async loadData() {
const countryConfig = getDataConfig(this.options.geoDataLevel).world;
const fillData = await this.fetchData(countryConfig.fill);
const lineData = await this.fetchData(countryConfig.line);
// const fillLabel = await this.fetchData(countryConfig.label);
const fillLabel = fillData.features.map((feature: any) => {
return {
...feature.properties,
center: [feature.properties.x, feature.properties.y],
};
});
return [fillData, lineData, fillLabel];
}
private addNationBorder(boundaries: any, boundaries2: any) {
const {
nationalStroke,
nationalWidth,
coastlineStroke,
chinaNationalStroke,
chinaNationalWidth,
coastlineWidth,
visible,
zIndex,
} = this.options;
// 添加国界线
const lineLayer = new LineLayer({
zIndex: zIndex + 0.1,
visible,
})
.source(boundaries)
// .size(0.6)
.size('type', (v: string) => {
if (v === '0') {
return chinaNationalWidth; // 中国国界线
} else if (v === '2' || v === '9') {
return coastlineWidth; // 中国海岸线
} else if (v === '7') {
return nationalWidth; // 国外国界
} else {
return nationalWidth;
}
})
.color('type', (v: string) => {
if (v === '0') {
return chinaNationalStroke; // 中国国界线
} else if (v === '2' || v === '9') {
return coastlineStroke; // 中国海岸线
} else if (v === '7') {
return nationalStroke; // 国外国界
} else {
return nationalStroke;
}
});
// 添加未定国界
const lineLayer2 = new LineLayer({
zIndex: zIndex + 0.1,
visible,
})
.source(boundaries2)
.size('type', (v: string) => {
if (v === '1') {
return chinaNationalWidth;
} else {
return nationalWidth;
}
})
.shape('line')
.color('type', (v: string) => {
if (v === '1') {
return chinaNationalStroke;
} else {
return nationalStroke;
}
})
.style({
lineType: 'dash',
dashArray: [2, 2],
});
this.scene.addLayer(lineLayer);
this.scene.addLayer(lineLayer2);
this.layers.push(lineLayer, lineLayer2);
}
}

View File

@ -1,9 +0,0 @@
{
"extends": "../../tsconfig.build.json",
"compilerOptions": {
"declarationDir": "./es",
"rootDir": "./src",
"baseUrl": "./"
},
"include": ["./src"]
}

View File

@ -1,47 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.1.12](https://github.com/antvis/L7/compare/v2.1.11...v2.1.12) (2020-04-10)
### Bug Fixes
* **heatmap:** 修复热力图某些设备上黑色 fix [#278](https://github.com/antvis/L7/issues/278) ([b8f5899](https://github.com/antvis/L7/commit/b8f58992d1fce38fdaac9d82ebfbec14e35298bd))
* 绘制组件高德地图mousedown事件不能监听的问题 ([1eb3313](https://github.com/antvis/L7/commit/1eb3313919b2c7c9162bee70a249846b897ef4b4))
## [2.1.11](https://github.com/antvis/L7/compare/v2.1.10...v2.1.11) (2020-04-07)
**Note:** Version bump only for package @antv/l7-draw
## [2.1.8](https://github.com/antvis/L7/compare/v2.1.7...v2.1.8) (2020-03-26)
**Note:** Version bump only for package @antv/l7-draw
## [2.1.7](https://github.com/antvis/L7/compare/v2.1.6...v2.1.7) (2020-03-26)
**Note:** Version bump only for package @antv/l7-draw
## [2.1.5](https://github.com/antvis/L7/compare/v2.1.4...v2.1.5) (2020-03-20)
### Bug Fixes
* observerable打包问题 ([412e2a8](https://github.com/antvis/L7/commit/412e2a83f78a9a448f0a5b65ccaf2ea97f78b47a))

View File

@ -1,56 +0,0 @@
# `draw`
地图绘制组件,支持点、线、面的绘制编辑,
## 使用
l7-draw 需要引用
```
import { DrawControl } from '@antv/l7-draw';
```
CDN 版本引用
```html
<head>
<! --引入最新版的L7-Draw -->
<script src = 'https://unpkg.com/@antv/l7-draw'></script>
</head>
```
### example
```javascript
import { Scene } from '@antv/l7';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import { DrawControl } from '@antv/l7-draw';
const scene = new Scene({
id: 'map',
map: new GaodeMap({
pitch: 0,
style: 'dark', // hosted style id
center: [112.874, 32.76], // starting position
zoom: 12, // starting zoom
}),
});
this.scene = scene;
scene.on('loaded', () => {
const drawControl = new DrawControl(scene, {
position: 'topright',
layout: 'horizontal', // horizontal vertical
controls: {
point: true,
polygon: true,
line: true,
circle: true,
rect: true,
delete: true,
},
});
scene.addControl(drawControl);
});
```

View File

@ -1,50 +0,0 @@
import { Feature, Geometry, point, Properties } from '@turf/helpers';
import {
createCircle,
createPoint,
createPolygon,
createRect,
} from '../../src/util/create_geometry';
const circleData = {
type: 'Feature',
properties: {
units: 'kilometers',
steps: 4,
id: '1',
pointFeatures: [
{
type: 'Feature',
properties: {},
geometry: { type: 'Point', coordinates: [113, 40] },
},
],
active: true,
type: 'circle',
radius: 1115.6518229264275,
startPoint: { lng: 112, lat: 30 },
endPoint: { lng: 113, lat: 40 },
},
geometry: {
type: 'Polygon',
coordinates: [
[
[112, 40.03328403184138],
[100.45355724910682, 29.495378543228927],
[112, 19.966715968158613],
[123.54644275089319, 29.495378543228927],
[112, 40.03328403184138],
],
],
},
};
describe('creat_geometry', () => {
it('creatCircle', () => {
const circle = createCircle([112, 30], [113, 40], {
units: 'kilometers',
steps: 4,
id: '1',
pointFeatures: [point([113, 40])],
});
expect(circleData).toEqual(circle);
});
});

View File

@ -1,85 +0,0 @@
import { Feature, Geometry, Properties } from '@turf/helpers';
import moveFeature from '../../src/util/move_featrues';
describe('moveFeature', () => {
const delta = {
lng: 1,
lat: 1,
};
const pointFeature: Feature<Geometry, Properties> = {
type: 'Feature',
properties: {},
geometry: {
type: 'Point',
coordinates: [130, 47],
},
};
const polyon: Feature<Geometry, Properties> = {
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: [
[
[49.5703125, 45.583289756006316],
[71.3671875, 45.583289756006316],
[71.3671875, 57.136239319177434],
[49.5703125, 57.136239319177434],
[49.5703125, 45.583289756006316],
],
],
},
};
const line: Feature<Geometry, Properties> = {
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: [
[54.31640625, 62.91523303947614],
[71.015625, 62.59334083012024],
[70.48828125, 58.07787626787517],
[77.16796875, 54.36775852406841],
[83.3203125, 58.26328705248601],
[83.3203125, 66.37275500247455],
[94.74609375, 66.65297740055279],
[94.74609375, 62.512317938386914],
],
},
};
it('move Point', () => {
const res = moveFeature([pointFeature], delta) as Array<
Feature<Geometry, Properties>
>;
expect(res[0]?.geometry?.coordinates).toEqual([131, 48]);
});
it('move BBox', () => {
const res = moveFeature([polyon], delta) as Array<
Feature<Geometry, Properties>
>;
expect(res[0]?.geometry?.coordinates).toEqual([
[
[50.5703125, 46.583289756006316],
[72.3671875, 46.583289756006316],
[72.3671875, 58.136239319177434],
[50.5703125, 58.136239319177434],
[50.5703125, 46.583289756006316],
],
]);
});
it('move line', () => {
const res = moveFeature([line], delta) as Array<
Feature<Geometry, Properties>
>;
expect(res[0]?.geometry?.coordinates).toEqual([
[55.31640625, 63.91523303947614],
[72.015625, 63.59334083012024],
[71.48828125, 59.07787626787517],
[78.16796875, 55.36775852406841],
[84.3203125, 59.26328705248601],
[84.3203125, 67.37275500247455],
[95.74609375, 67.65297740055279],
[95.74609375, 63.512317938386914],
]);
});
});

View File

@ -1,60 +0,0 @@
{
"name": "@antv/l7-draw",
"version": "2.2.37",
"description": "L7 Draw moudules",
"keywords": [],
"author": "thinkinggis <lzx199065@gmail.com>",
"license": "ISC",
"main": "lib/index.js",
"module": "es/index.js",
"unpkg": "dist/l7-draw.js",
"types": "es/index.d.ts",
"sideEffects": true,
"files": [
"dist",
"lib",
"es",
"README.md"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/antvis/L7.git"
},
"scripts": {
"tsc": "tsc --project tsconfig.build.json",
"clean": "rimraf dist; rimraf es; rimraf lib;",
"build": "run-p build:*",
"build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"build:cdn": "node_modules/.bin/rollup -c",
"lint:ts": "run-p -c lint:ts-*",
"test": "jest",
"sync": "tnpm sync"
},
"dependencies": {
"@antv/l7": "2.2.37",
"@babel/runtime": "^7.7.7",
"@turf/circle": "^6.0.1",
"@turf/distance": "^6.0.1",
"@turf/helpers": "^6.1.4",
"@turf/midpoint": "^5.1.5",
"@turf/turf": "^5.1.6",
"eventemitter3": "^4.0.0",
"lodash": "^4.6.2"
},
"bugs": {
"url": "https://github.com/antvis/L7/issues"
},
"homepage": "https://github.com/antvis/L7#readme",
"devDependencies": {
"postcss": "^7.0.27",
"postcss-url": "^8.0.0",
"rollup": "^2.3.3",
"rollup-plugin-less": "^1.1.2"
},
"gitHead": "20154fe30d512024b03ac5e40f77731bc0580bb0"
}

View File

@ -1,51 +0,0 @@
import pkg from './package.json';
import typescript from 'rollup-plugin-typescript';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import buble from 'rollup-plugin-buble';
import postcss from 'rollup-plugin-postcss';
import { terser } from 'rollup-plugin-terser';
import url from 'postcss-url';
export default {
input: './src/index.ts',
plugins: [
// less(),
typescript({
exclude: 'node_modules/**',
typescript: require('typescript')
}),
resolve({
preferBuiltins: false
}),
postcss({
plugins: [
url({ url: 'inline' })
]
}),
commonjs({
namedExports: {
eventemitter3: [ 'EventEmitter' ],
lodash: [ 'merge', 'clone' ]
}
}),
buble({
transforms: { generator: false }
}),
terser()
],
external: [
'@antv/l7'
],
output: [
{
format: 'umd',
name: 'L7.Draw',
file: pkg.unpkg,
sourcemap: true,
globals: {
'@antv/l7': 'L7'
}
}
]
};

View File

@ -1,70 +0,0 @@
.l7-control-draw {
border-radius: 4px;
background: #fff;
box-shadow: 0 0 0 1px rgba(0,0,0,.1);
display: flex;
button {
background-repeat: no-repeat;
background-position: center;
background-size: 20px 20px;
width: 30px;
height: 30px;
display: block;
padding: 0;
outline: none;
border: 0;
margin: 1px;
box-sizing: border-box;
cursor: pointer;
}
button:not(:disabled):hover {
background-color: rgba(0, 0, 0, 0.05);
}
button:focus {
box-shadow: 0 0 2px 2px #0096ff;
}
.draw-point {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTg1NjYxMTY0NjA0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDExOTQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjI5MzUiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTQ5LjI1IiBoZWlnaHQ9IjEyOCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNNjA5LjUzNiA3MDcuMDcyYTE5NS4wNzIgMTk1LjA3MiAwIDEgMSAwLTM5MC4xNDQgMTk1LjA3MiAxOTUuMDcyIDAgMCAxIDAgMzkwLjE0NHoiIGZpbGw9IiMyYzJjMmMiIHAtaWQ9IjI5MzYiPjwvcGF0aD48cGF0aCBkPSJNMTA0OC40MDUzMzMgNDE0LjQ2NGExNDYuMjYxMzMzIDE0Ni4yNjEzMzMgMCAxIDEgMC0yOTIuNTIyNjY3IDE0Ni4yNjEzMzMgMTQ2LjI2MTMzMyAwIDAgMSAwIDI5Mi41MjI2Njd6TTE3MC42NjY2NjcgOTk5LjU5NDY2N2ExNDYuMjYxMzMzIDE0Ni4yNjEzMzMgMCAxIDEgMC0yOTIuNTIyNjY3IDE0Ni4yNjEzMzMgMTQ2LjI2MTMzMyAwIDAgMSAwIDI5Mi41MjI2Njd6IG0wLTY4Mi42NjY2NjdBMTQ2LjI2MTMzMyAxNDYuMjYxMzMzIDAgMSAxIDE3MC42NjY2NjcgMjQuNDA1MzMzYTE0Ni4yNjEzMzMgMTQ2LjI2MTMzMyAwIDAgMSAwIDI5Mi41MjI2Njd6IiBmaWxsPSIjMmMyYzJjIiBwLWlkPSIyOTM3Ij48L3BhdGg+PC9zdmc+');
}
.draw-line {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTg1NjYxMDY5NTk0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjIxOTMiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNOTAwLjkzIDMwMC4yOThjLTQxLjA2NyAwLTc0LjQ3IDMzLjQyOS03NC40NyA3NC40OTEgMCAxMCAxLjk5MiAxOS41MzMgNS41ODEgMjguMjU3bC0yMjAuMjYyIDIwNS4xOGE3My45OSA3My45OSAwIDAgMC00MS4yMzItMTIuNTA0IDc0LjE3IDc0LjE3IDAgMCAwLTIyLjQ1MSAzLjQ1MWwtNzAuMTEzLTEzOS42MzhhNzQuMTM4IDc0LjEzOCAwIDAgMCA4LjE0Ni0zMy45MmMwLTQxLjA2Mi0zMy4zODMtNzQuNDktNzQuNDQ1LTc0LjQ5cy03NC40NDUgMzMuNDI4LTc0LjQ0NSA3NC40OWMwIDMuODI1IDAuMjkyIDcuNjA0IDAuODU1IDExLjMxNkwxNjAuODYgNjI3LjIyYTczLjg4NyA3My44ODcgMCAwIDAtMzkuNzk4LTExLjU5N2MtNDEuMDYyIDAtNzQuNDcgMzMuNDIzLTc0LjQ3IDc0LjQ5IDAgNDEuMDgzIDMzLjQwOCA3NC41MTcgNzQuNDcgNzQuNTE3IDQxLjA0MiAwIDc0LjQyLTMzLjQyOCA3NC40Mi03NC41MTZhNzQuMjMgNzQuMjMgMCAwIDAtMy4yOTMtMjEuODk5bDE3MS40MzMtMTg1LjcxMmE3NC40NTUgNzQuNDU1IDAgMCAwIDc2LjMzNCAxMi4wNzhsNjcuMzkgMTM2LjE5MmE3NC4xNjggNzQuMTY4IDAgMCAwLTExLjIzOCAzOS40NWMwIDQxLjA4MiAzMy4zODIgNzQuNTE2IDc0LjQ0NCA3NC41MTYgNDEuMDY4IDAgNzQuNDQ1LTMzLjQyOSA3NC40NDUtNzQuNTE3YTc0LjM0MiA3NC4zNDIgMCAwIDAtMi43MjQtMTkuOTE2bDIyNC42NzEtMjA5LjI2NWE3My45NjQgNzMuOTY0IDAgMCAwIDMzLjk5MiA4LjI0OGM0MS4wNDIgMCA3NC40MTktMzMuNDI4IDc0LjQxOS03NC40OS0wLjAxLTQxLjA2OC0zMy4zODgtNzQuNTAyLTc0LjQyNC03NC41MDJ6TTEyMS4wNjkgNzEzLjA0MmEyMi45MTcgMjIuOTE3IDAgMCAxIDAtNDUuODMgMjIuOTMyIDIyLjkzMiAwIDAgMSAyMi44NzYgMjIuOTAzYy0wLjAwNSAxMi42NDYtMTAuMjg2IDIyLjkyNy0yMi44NzYgMjIuOTI3eiBtMjc2LjMxLTI2OS41MzdhMjIuODYgMjIuODYgMCAwIDEtOC41OS0xNy44OSAyMi45MzggMjIuOTM4IDAgMCAxIDIyLjkwMS0yMi45MDEgMjIuOTEyIDIyLjkxMiAwIDAgMSAyMi44NzYgMjIuOTAxYzAgNi4wNDctMi4zMiAxMS43MjUtNi41MDcgMTYuMDFsLTAuMiAwLjE4NWMtOS4wNjggOS4wNTItMjUuMDQyIDYuMDc3LTMwLjQ4IDEuNjk1ek01NzAuNTUzIDY5My4xNGEyMi45MjIgMjIuOTIyIDAgMCAxLTIyLjg3Ni0yMi45MjcgMjIuNzMzIDIyLjczMyAwIDAgMSA4LjI4LTE3LjYyM2MwLjMzNy0wLjI0IDAuNjg1LTAuNDgxIDEuMDEzLTAuNzQyIDAuMi0wLjE1OSAwLjM5LTAuMzIzIDAuNTg0LTAuNDkyYTIyLjY0IDIyLjY0IDAgMCAxIDEyLjk5NC00LjA0NSAyMi45MjcgMjIuOTI3IDAgMCAxIDIyLjg4MSAyMi45MDIgMjIuOTM4IDIyLjkzOCAwIDAgMS0yMi44NzYgMjIuOTI3eiBtMzMwLjM3OS0yOTUuNDVjLTEyLjY1MiAwLTIyLjkwMi0xMC4yOC0yMi45MDItMjIuOXMxMC4yNS0yMi45MDMgMjIuOTAyLTIyLjkwM2EyMi45MjcgMjIuOTI3IDAgMCAxIDIyLjg3IDIyLjkwMiAyMi45MjcgMjIuOTI3IDAgMCAxLTIyLjg3IDIyLjkwMnoiIHAtaWQ9IjIxOTQiPjwvcGF0aD48L3N2Zz4=');
}
.draw-polygon {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTg1NjI5MzI3Nzc1IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE3MzkiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNNDIxLjE0OSA5OTAuNDA0bC0xNDMuMzE4LTEzNy4xNS00My42NzktNDEuNzY0TDMxLjg0OSA2MTcuODUzbDIzNC4wNzQtNDg1LjQ4OCAxMjUuMTQxIDE3LjAyNiAxMDMuNjE0IDE0LjA0MS04LjA1NyA1OS40NTYtMTAzLjYzLTE0LjA0My04MS45Ni0xMS4xNTEtOTguMTAzIDIwMy40MzItOTguMTA1IDIwMy41MTkgMTcwLjgwNiAxNjMuNDkgNDMuNjgxIDQxLjc2NiAzNi4xNTcgMzQuNjE2IDc1LjY5OCA3Mi40IDM2LjUyOS0xOS42MjEgNTUuNzE4LTI5Ljk3MSA1MS43MDctMjcuNzM2IDUxLjgzNC0yNy45NjcgMTcuMTEtOS4xMTQgMTcuMTg4LTkuMyAzNC40NzYtMTguNDggMTcuMjM5LTkuMyAzNC41NDItMTguNTA1IDE3LjMxNS05LjM4NyAxNy4yNTYtOS4yMDEgNDYuOTgtMjUuMjkzLTQuOTk1LTI3LjM3NS04LjgzNi00OC45NjYtMTUuMzQxLTg0Ljg5MSA1OS4wNDQtMTAuNjcgMTUuMzQyIDg0Ljg5OCA4LjgyNyA0OC45MTggMTIuODMxIDcwLjMyOC0zMy43MTcgMTguMDQ5LTUxLjgyNyAyNy45MDQtMTcuMjM2IDkuMTktMTcuMjcyIDkuMzY1LTM0LjQ5MyAxOC40NzgtMzQuNTMxIDE4LjU3Ni0xNy4yMTMgOS4yMi0xNy4yOTIgOS4zNTYtMTcuMDk3IDkuMTA2LTE3LjIxOCA5LjMzNXoiIGZpbGw9IiMzRTNBMzkiIHAtaWQ9IjE3NDAiPjwvcGF0aD48cGF0aCBkPSJNNzUyLjUyNCA1NS40MzRoNjB2MzcwLjMyM2gtNjB6IiBmaWxsPSIjM0UzQTM5IiBwLWlkPSIxNzQxIj48L3BhdGg+PHBhdGggZD0iTTU5Ny4zODUgMjA1LjY5N2gzNzAuMjc5djYwSDU5Ny4zODV6IiBmaWxsPSIjM0UzQTM5IiBwLWlkPSIxNzQyIj48L3BhdGg+PC9zdmc+');
}
.draw-rect {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTg1NjI5Mjk5NTYxIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjEwMDEiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNNzY1LjIzNCA2OS40MTdoNjB2MzcwLjYwNWgtNjB6IiBmaWxsPSIjM0UzQTM5IiBwLWlkPSIxMDAyIj48L3BhdGg+PHBhdGggZD0iTTYxNC4xOTMgMjE5LjgwN2gzNjIuMTI4djYwSDYxNC4xOTN6IiBmaWxsPSIjM0UzQTM5IiBwLWlkPSIxMDAzIj48L3BhdGg+PHBhdGggZD0iTTgyNS4yMzQgOTc1LjkzNkg4OS44MTlWMjI0LjcwN2gzNjcuNzA4djYwSDE0OS44MTl2NjMxLjIyOWg2MTUuNDE1VjYwMC4yOTloNjB6IiBmaWxsPSIjM0UzQTM5IiBwLWlkPSIxMDA0Ij48L3BhdGg+PC9zdmc+');
}
.draw-circle {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTg1NjI5MjYwMDI2IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjI3NzYiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNNTEyIDg4MS4wNjY2NjdBMzY5LjA2NjY2NyAzNjkuMDY2NjY3IDAgMSAxIDg4MS4wNjY2NjcgNTEyIDM2OS40OTMzMzMgMzY5LjQ5MzMzMyAwIDAgMSA1MTIgODgxLjA2NjY2N3ogbTAtNjgyLjY2NjY2N0EzMTMuNiAzMTMuNiAwIDEgMCA4MjUuNiA1MTIgMzE0LjAyNjY2NyAzMTQuMDI2NjY3IDAgMCAwIDUxMiAxOTguNHoiIGZpbGw9IiIgcC1pZD0iMjc3NyI+PC9wYXRoPjwvc3ZnPg==');
}
.draw-delete {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTg1NzMwNDEyNjU0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQ4MDQiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNMjEzLjMzMzMzMyAyODIuODM3MzMzYzAtMjAuNjkzMzMzIDE2LjE3MDY2Ny0zNy40MTg2NjcgMzYuMDk2LTM3LjQxODY2NmgxODAuNDh2LTM3LjM3NmMwLTIwLjY1MDY2NyAxNi4yMTMzMzMtMzcuMzc2IDM2LjEzODY2Ny0zNy4zNzZoNzIuMTkyYzE5Ljk2OCAwIDM2LjEzODY2NyAxNi43MjUzMzMgMzYuMTM4NjY3IDM3LjM3NnYzNy4zNzZoMTgwLjQ4YzE5Ljk2OCAwIDM2LjA5NiAxNi43MjUzMzMgMzYuMDk2IDM3LjQxODY2NnYzNy4zNzZIMjEzLjMzMzMzM3YtMzcuMzc2eiBtNTQxLjUyNTMzNCAxMTIuMTI4djQyMC45OTJjMCAyMC42MDgtMTYuMTI4IDM3LjM3Ni0zNi4wOTYgMzcuMzc2SDI4NS41MjUzMzNjLTE5LjkyNTMzMyAwLTM2LjA5Ni0xNi43NjgtMzYuMDk2LTM3LjM3NlYzNTcuNTQ2NjY3aDUwNS40MjkzMzR2MzcuMzc2ek0zOTMuODU2IDQ2OS43NmMwLTIwLjY1MDY2Ny0xNi4xNzA2NjctMzcuNDE4NjY3LTM2LjA5Ni0zNy40MTg2NjctMTkuOTY4IDAtMzYuMTM4NjY3IDE2Ljc2OC0zNi4xMzg2NjcgMzcuNDE4NjY3djI3MS40MDI2NjdjMCAyMC42NTA2NjcgMTYuMjEzMzMzIDM3LjQxODY2NyAzNi4xMzg2NjcgMzcuNDE4NjY2IDE5LjkyNTMzMyAwIDM2LjA5Ni0xNi43NjggMzYuMDk2LTM3LjQxODY2NlY0NjkuNzZ6IG0xNDQuMzg0IDBjMC0yMC42NTA2NjctMTYuMTI4LTM3LjQxODY2Ny0zNi4wOTYtMzcuNDE4NjY3LTE5LjkyNTMzMyAwLTM2LjA5NiAxNi43NjgtMzYuMDk2IDM3LjQxODY2N3YyNzEuNDAyNjY3YzAgMjAuNjUwNjY3IDE2LjE3MDY2NyAzNy40MTg2NjcgMzYuMDk2IDM3LjQxODY2NiAxOS45NjggMCAzNi4wOTYtMTYuNzY4IDM2LjA5Ni0zNy40MTg2NjZWNDY5Ljc2eiBtMTQ0LjQyNjY2NyAwYzAtMjAuNjUwNjY3LTE2LjE3MDY2Ny0zNy40MTg2NjctMzYuMDk2LTM3LjQxODY2Ny0xOS45NjggMC0zNi4wOTYgMTYuNzY4LTM2LjA5NiAzNy40MTg2Njd2MjcxLjQwMjY2N2MwIDIwLjY1MDY2NyAxNi4xMjggMzcuNDE4NjY3IDM2LjA5NiAzNy40MTg2NjYgMTkuOTI1MzMzIDAgMzYuMDk2LTE2Ljc2OCAzNi4wOTYtMzcuNDE4NjY2VjQ2OS43NnoiIHAtaWQ9IjQ4MDUiPjwvcGF0aD48L3N2Zz4=');
}
}
.horizontal {
flex-direction: row;
button:focus:first-child {
border-radius: 4px 0px 0px 4px;
}
button:focus:last-child {
border-radius: 0px 4px 4px 4px;
}
button+button {
border-left: 1px solid #eee;
}
}
.vertical {
flex-direction: column;
button:focus:first-child {
border-radius: 4px 4px 0 0;
}
button:focus:last-child {
border-radius: 0px 0px 4px 4px;
}
button+button {
border-top: 1px solid #eee;
}
}

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg5738" width="20" height="20" version="1.1"><defs id="defs5740"><linearGradient id="linearGradient4184" x1="3003" x2="3017" y1="10" y2="10" gradientTransform="translate(1,2.6171874e-6)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4103"/><linearGradient id="linearGradient4103"><stop id="stop4105" offset="0" stop-color="#000" stop-opacity="1"/><stop id="stop4107" offset="1" stop-color="#000" stop-opacity="0"/></linearGradient></defs><metadata id="metadata5743"/><g id="layer1" transform="translate(0,-1032.3622)"><path color="#000" style="isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1;marker:none" id="rect9198" fill="#000" fill-opacity="1" fill-rule="nonzero" stroke="none" stroke-dasharray="none" stroke-dashoffset="0" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="4" stroke-opacity="1" stroke-width="2" d="M 12.050781 2 C 11.795262 2 11.539542 2.0971762 11.34375 2.2929688 L 10.298828 3.3378906 C 9.9072437 3.7294757 9.9072437 4.360368 10.298828 4.7519531 L 15.248047 9.7011719 C 15.639631 10.092757 16.270525 10.092757 16.662109 9.7011719 L 17.707031 8.65625 C 18.098616 8.2646649 18.098616 7.6337726 17.707031 7.2421875 L 12.757812 2.2929688 C 12.56202 2.0971762 12.306301 2 12.050781 2 z M 8 8 C 7 8 7 9 7.5 9.5 C 7.833333 9.8333 8.5 10.5 8.5 10.5 L 7.5 11.5 C 7.5 11.5 7 12 7.5 12.5 C 8 13 8.5 12.5 8.5 12.5 L 9.5 11.5 L 10.5 12.5 C 11 13 12 13 12 12 L 12 8 L 8 8 z M 4 10.003906 C 3.74451 10.003906 3.4906916 10.103039 3.2949219 10.298828 L 2.2988281 11.294922 C 1.9072888 11.6865 1.9072888 12.315453 2.2988281 12.707031 L 3.296875 13.707031 C 3.6884144 14.098609 4.3193981 14.098609 4.7109375 13.707031 L 5.7070312 12.710938 C 6.0985706 12.31936 6.0985706 11.688453 5.7070312 11.296875 L 4.7070312 10.298828 C 4.5112616 10.103039 4.25549 10.003906 4 10.003906 z M 7.9960938 14 C 7.7405942 14 7.4848395 14.097187 7.2890625 14.292969 L 6.2949219 15.289062 C 5.9033679 15.680626 5.9033679 16.311561 6.2949219 16.703125 L 7.2929688 17.701172 C 7.6845227 18.092735 8.3135242 18.092735 8.7050781 17.701172 L 9.7011719 16.705078 C 10.092726 16.313515 10.092726 15.684532 9.7011719 15.292969 L 8.703125 14.292969 C 8.507348 14.097187 8.2515933 14 7.9960938 14 z" clip-rule="nonzero" color-interpolation="sRGB" color-interpolation-filters="linearRGB" color-rendering="auto" display="inline" enable-background="accumulate" image-rendering="auto" opacity="1" overflow="visible" shape-rendering="auto" text-rendering="auto" transform="translate(0,1032.3622)" visibility="visible"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="svg19167" width="20" height="20" version="1.1" viewBox="0 0 20 20"><metadata id="metadata19172"/><g id="layer1" transform="translate(0,-1032.3622)"><path id="rect6467" fill="#000" fill-opacity="1" fill-rule="nonzero" stroke="none" stroke-width="3" d="m 13.5,1035.8622 c -1.380712,0 -2.5,1.1193 -2.5,2.5 0,0.3208 0.04614,0.6244 0.15625,0.9063 l -3.75,3.75 c -0.281836,-0.1102 -0.585421,-0.1563 -0.90625,-0.1563 -1.380712,0 -2.5,1.1193 -2.5,2.5 0,1.3807 1.119288,2.5 2.5,2.5 1.380712,0 2.5,-1.1193 2.5,-2.5 0,-0.3208 -0.04614,-0.6244 -0.15625,-0.9062 l 3.75,-3.75 c 0.281836,0.1101 0.585421,0.1562 0.90625,0.1562 1.380712,0 2.5,-1.1193 2.5,-2.5 0,-1.3807 -1.119288,-2.5 -2.5,-2.5 z" color="#000" display="inline" enable-background="accumulate" overflow="visible" visibility="visible" style="marker:none"/></g></svg>

Before

Width:  |  Height:  |  Size: 896 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="svg19167" width="20" height="20" version="1.1" viewBox="0 0 20 20"><metadata id="metadata19172"/><g id="layer1" transform="translate(0,-1032.3622)"><path id="path12561" fill="#000" fill-opacity="1" fill-rule="evenodd" stroke="none" stroke-dasharray="none" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-opacity="1" stroke-width="2" d="m 36,1040.3622 c 6e-6,3.3093 -5.988612,10 -5.988612,10 0,0 -5.998776,-6.668 -6.011345,-9.9772 -0.01257,-3.3092 2.656576,-6.0039 5.965792,-6.0227 3.309189,-0.019 6.00884,2.6452 6.033992,5.9543" clip-rule="nonzero" color="#000" color-interpolation="sRGB" color-interpolation-filters="linearRGB" color-rendering="auto" display="inline" enable-background="accumulate" image-rendering="auto" opacity="1" overflow="visible" shape-rendering="auto" text-rendering="auto" visibility="visible" style="isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1;marker:none"/><path id="path12563" fill="#fff" fill-opacity="1" fill-rule="evenodd" stroke="none" stroke-dasharray="none" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-opacity="1" stroke-width="2" d="m 34.000115,1040.3622 c -5e-6,2.2062 -3.992523,7.0001 -3.992523,7.0001 0,0 -3.999291,-4.7787 -4.007679,-6.9849 -0.0084,-2.2062 1.771082,-4.0027 3.97731,-4.0153 2.20621,-0.013 4.006037,1.7635 4.022777,3.9697" clip-rule="nonzero" color="#000" color-interpolation="sRGB" color-interpolation-filters="linearRGB" color-rendering="auto" display="inline" enable-background="accumulate" image-rendering="auto" opacity="1" overflow="visible" shape-rendering="auto" text-rendering="auto" visibility="visible" style="isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1;marker:none"/><path id="path12568" fill="#000" fill-opacity="1" fill-rule="evenodd" stroke="none" stroke-dasharray="none" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-opacity="1" stroke-width="2" d="M 9.9667969,1014.3622 C 6.6575809,1014.381 3.98743,1017.0764 4,1020.3856 c 0.012569,3.3092 6.011719,8.9766 6.011719,8.9766 0,0 5.988287,-5.6907 5.988281,-9 l 0,-0.045 c -0.02515,-3.3091 -2.724014,-5.9741 -6.0332031,-5.9551 z m 0.00977,2 c 2.2062061,-0.013 4.0066931,1.7626 4.0234331,3.9688 l 0,0.031 c -5e-6,2.2062 -3.992188,6 -3.992188,6 0,0 -3.999424,-3.7782 -4.007812,-5.9844 -0.0084,-2.2062 1.7703345,-4.003 3.9765625,-4.0156 z" clip-rule="nonzero" color="#000" color-interpolation="sRGB" color-interpolation-filters="linearRGB" color-rendering="auto" display="inline" enable-background="accumulate" image-rendering="auto" opacity="1" overflow="visible" shape-rendering="auto" text-rendering="auto" visibility="visible" style="isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1;marker:none"/><path id="path17305" fill="#000" fill-opacity="1" stroke="none" stroke-dasharray="none" stroke-dashoffset="0" stroke-linecap="butt" stroke-linejoin="bevel" stroke-miterlimit="4" stroke-opacity="1" stroke-width="2" d="M 10 2 C 6.686292 2 4 4.6863 4 8 C 4 11.3137 10 17 10 17 C 10 17 16 11.3137 16 8 C 16 4.6863 13.313708 2 10 2 z M 10 4 C 12.071068 4 13.75 5.6789 13.75 7.75 C 13.75 9.2053278 11.93111 11.644393 10.830078 13 L 9.1699219 13 C 8.0688903 11.644393 6.25 9.2053278 6.25 7.75 C 6.25 5.6789 7.928932 4 10 4 z" opacity="1" transform="translate(0,1032.3622)" style="marker:none"/></g></svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="svg19167" width="20" height="20" version="1.1" viewBox="0 0 20 20"><metadata id="metadata19172"/><g id="layer1" transform="translate(0,-1032.3622)"><path id="rect7797" fill="#000" fill-opacity="1" fill-rule="nonzero" stroke="none" stroke-width=".5" d="m 5,1039.3622 0,6 2,2 6,0 2,-2 0,-6 -2,-2 -6,0 z m 3,0 4,0 1,1 0,4 -1,1 -4,0 -1,-1 0,-4 z" color="#000" display="inline" enable-background="accumulate" overflow="visible" visibility="visible" style="marker:none"/><circle id="path4364" cx="6" cy="1046.362" r="2" fill="#000" fill-opacity="1" fill-rule="nonzero" stroke="none" stroke-width="1.6" color="#000" display="inline" enable-background="accumulate" overflow="visible" visibility="visible" style="marker:none"/><circle id="path4368" cx="14" cy="1046.362" r="2" fill="#000" fill-opacity="1" fill-rule="nonzero" stroke="none" stroke-width="1.6" color="#000" display="inline" enable-background="accumulate" overflow="visible" visibility="visible" style="marker:none"/><circle id="path4370" cx="6" cy="1038.362" r="2" fill="#000" fill-opacity="1" fill-rule="nonzero" stroke="none" stroke-width="1.6" color="#000" display="inline" enable-background="accumulate" overflow="visible" visibility="visible" style="marker:none"/><circle id="path4372" cx="14" cy="1038.362" r="2" fill="#000" fill-opacity="1" fill-rule="nonzero" stroke="none" stroke-width="1.6" color="#000" display="inline" enable-background="accumulate" overflow="visible" visibility="visible" style="marker:none"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="svg5738" width="20" height="20" version="1.1" viewBox="0 0 20 20"><metadata id="metadata5743"/><g id="layer1" transform="translate(0,-1032.3622)"><path id="rect2439-7" fill="#000" fill-opacity="1" fill-rule="nonzero" stroke="none" stroke-width="1" d="m 10,1035.7743 c -0.7849253,8e-4 -1.4968376,0.4606 -1.8203125,1.1758 l -3.1796875,0 -1,1 0,1 12,0 0,-1 -1,-1 -3.179688,0 c -0.323475,-0.7152 -1.035387,-1.175 -1.820312,-1.1758 z m -5,4.5879 0,7 c 0,1 1,2 2,2 l 6,0 c 1,0 2,-1 2,-2 l 0,-7 -2,0 0,5.5 -1.5,0 0,-5.5 -3,0 0,5.5 -1.5,0 0,-5.5 z" color="#000" display="inline" enable-background="accumulate" overflow="visible" visibility="visible" style="marker:none"/></g></svg>

Before

Width:  |  Height:  |  Size: 756 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg5738" width="20" height="20" version="1.1"><defs id="defs5740"><linearGradient id="linearGradient4184" x1="3003" x2="3017" y1="10" y2="10" gradientTransform="translate(1,2.6171874e-6)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4103"/><linearGradient id="linearGradient4103"><stop id="stop4105" offset="0" stop-color="#000" stop-opacity="1"/><stop id="stop4107" offset="1" stop-color="#000" stop-opacity="0"/></linearGradient></defs><metadata id="metadata5743"/><g id="layer1" transform="translate(0,-1032.3622)"><path color="#000" style="isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1;marker:none" id="rect9198" fill="#000" fill-opacity="1" fill-rule="nonzero" stroke="none" stroke-dasharray="none" stroke-dashoffset="0" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="4" stroke-opacity="1" stroke-width="2" d="M 12.005859 2 C 11.75036 2 11.494605 2.097187 11.298828 2.2929688 L 10.302734 3.2890625 C 9.9111804 3.680626 9.9111804 4.3115615 10.302734 4.703125 L 11.302734 5.7011719 C 11.694288 6.0927354 12.32329 6.0927354 12.714844 5.7011719 L 13.710938 4.7050781 C 14.102491 4.3135146 14.102491 3.6825791 13.710938 3.2910156 L 12.712891 2.2929688 C 12.517114 2.097187 12.261359 2 12.005859 2 z M 16.001953 5.9941406 C 15.746463 5.9941406 15.490692 6.0932735 15.294922 6.2890625 L 14.298828 7.2851562 C 13.907289 7.6767342 13.907289 8.3056877 14.298828 8.6972656 L 15.296875 9.6972656 C 15.688414 10.088844 16.319398 10.088844 16.710938 9.6972656 L 17.707031 8.7011719 C 18.098571 8.3095939 18.098571 7.6786873 17.707031 7.2871094 L 16.708984 6.2890625 C 16.513215 6.0932735 16.257443 5.9941406 16.001953 5.9941406 z M 9 7 C 8 7 8 8 8.5 8.5 C 8.833333 8.8333 9.5 9.5 9.5 9.5 L 8.5 10.5 C 8.5 10.5 8 11 8.5 11.5 C 9 12 9.5 11.5 9.5 11.5 L 10.5 10.5 L 11.5 11.5 C 12 12 13 12 13 11 L 13 7 L 9 7 z M 4.0488281 10.001953 C 3.7933087 10.001953 3.5375891 10.099129 3.3417969 10.294922 L 2.2988281 11.337891 C 1.9072437 11.729476 1.9072437 12.360368 2.2988281 12.751953 L 7.2480469 17.701172 C 7.6396313 18.092757 8.270525 18.092757 8.6621094 17.701172 L 9.7050781 16.658203 C 10.096663 16.266618 10.096663 15.635726 9.7050781 15.244141 L 4.7558594 10.294922 C 4.5600672 10.099129 4.3043475 10.001953 4.0488281 10.001953 z" clip-rule="nonzero" color-interpolation="sRGB" color-interpolation-filters="linearRGB" color-rendering="auto" display="inline" enable-background="accumulate" image-rendering="auto" opacity="1" overflow="visible" shape-rendering="auto" text-rendering="auto" transform="translate(0,1032.3622)" visibility="visible"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1,200 +0,0 @@
/*
* @Author: lzxue
* @Date: 2020-04-03 19:24:16
* @Last Modified by: lzxue
* @Last Modified time: 2020-06-22 17:33:14
*/
import { Control, DOM, IControlOption, PositionType, Scene } from '@antv/l7';
import './css/draw.less';
import {
DrawCircle,
DrawDelete,
DrawFeature,
DrawLine,
DrawPoint,
DrawPolygon,
DrawRect,
} from './modes';
import { IDrawFeatureOption } from './modes/draw_feature';
const DrawType: {
[key: string]: any;
} = {
point: DrawPoint,
line: DrawLine,
polygon: DrawPolygon,
circle: DrawCircle,
rect: DrawRect,
};
import { isObject, polygon } from '@turf/helpers';
import { DrawEvent, DrawModes } from './util/constant';
export interface IControls {
[key: string]: boolean | IDrawFeatureOption;
}
export interface IDrawControlOption extends IControlOption {
pickBuffer: number;
controls: IControls;
layout: 'horizontal' | 'vertical';
style: any;
}
export class DrawControl extends Control {
private draw: {
[key: string]: DrawFeature;
} = {};
private currentDraw: DrawFeature;
private scene: Scene;
constructor(scene: Scene, options: Partial<IDrawControlOption>) {
super(options);
this.scene = scene;
}
public getDefault() {
return {
position: PositionType.TOPLEFT,
controls: {
point: true,
line: true,
polygon: true,
rect: true,
circle: true,
delete: true,
},
name: 'draw',
};
}
public onAdd(): HTMLElement {
const { layout } = this.controlOption;
const controlClass = 'l7-control-draw' + ' ' + layout;
const { controls } = this.controlOption as IDrawControlOption;
const container = DOM.create('div', controlClass) as HTMLElement;
this.addControls(controls, container);
// 代理每个绘制组件的事件
this.addControlEvent();
// 监听组件 选中, 编辑
return container;
}
public onRemove() {
for (const draw in this.draw) {
if (this.draw[draw]) {
this.draw[draw].destroy();
}
}
}
public getDraw(type: string): DrawFeature | null {
const { controls } = this.controlOption as IDrawControlOption;
if (controls[type]) {
return this.draw[type];
}
return null;
}
public getAllData() {
const res: { [key: string]: any } = {};
for (const draw in this.draw) {
if (this.draw[draw]) {
res[draw] = this.draw[draw].getData();
}
}
return res;
}
public removeAllData() {
for (const draw in this.draw) {
if (this.draw[draw]) {
this.draw[draw].removeAllData();
}
}
}
private addControls(controls: IControls, container: HTMLElement) {
const { style } = this.controlOption as IDrawControlOption;
for (const type in controls) {
if (DrawType[type] && controls[type] !== false) {
const drawOption: Partial<IDrawFeatureOption> = isObject(controls[type])
? (controls[type] as Partial<IDrawFeatureOption>)
: {};
if (style) {
drawOption.style = style;
}
const draw = new DrawType[type](this.scene, drawOption);
draw.on(DrawEvent.MODE_CHANGE, this.onModeChange.bind(null, type));
this.draw[type] = draw;
this.createButton(
draw.title,
'draw-' + type,
container,
'click',
this.onButtonClick.bind(null, type),
);
} else if (type === 'delete' && controls[type] !== false) {
const draw = new DrawDelete(this.scene);
draw.on(DrawEvent.MODE_CHANGE, this.onModeChange.bind(null, type));
this.createButton(
draw.title,
'draw-' + type,
container,
'mousedown',
this.onDeleteMode.bind(null, type),
);
}
}
}
private addControlEvent() {
for (const draw in this.draw) {
if (this.draw[draw]) {
['draw.create', 'draw.update', 'draw.delete'].forEach(
(type: string) => {
this.draw[draw].on(type, (feature) => {
this.emit(type, {
drawType: draw,
feature,
});
});
},
);
}
}
}
private createButton(
tile: string,
className: string,
container: HTMLElement,
eventType: string,
fn: (...arg: any[]) => any,
) {
const link = DOM.create('button', className, container);
link.title = tile;
link.addEventListener(eventType, fn, false);
return link;
}
private onButtonClick = (type: string, e: MouseEvent) => {
for (const draw in this.draw) {
if (draw === type) {
this.draw[draw].enable();
} else {
this.draw[draw].disable();
}
}
};
private onDeleteMode = (type: string, e: MouseEvent) => {
e.stopPropagation();
if (!this.currentDraw) {
return;
}
this.currentDraw.deleteMode.enable();
return false;
};
private onModeChange = (type: string, mode: string) => {
if (mode === DrawModes.SIMPLE_SELECT) {
this.currentDraw = this.draw[type];
}
};
}

View File

@ -1,2 +0,0 @@
export * from './modes/index';
export * from './draw_control';

View File

@ -1,168 +0,0 @@
import {
IInteractionTarget,
ILayer,
ILngLat,
PointLayer,
Scene,
} from '@antv/l7';
import {
Feature,
featureCollection,
Geometries,
Properties,
} from '@turf/helpers';
import { DrawEvent, DrawModes, unitsType } from '../util/constant';
import { createCircle, createPoint } from '../util/create_geometry';
import moveFeatures, { movePoint } from '../util/move_featrues';
import DrawFeature, { IDrawFeatureOption } from './draw_feature';
export default class DrawCircle extends DrawFeature {
protected startPoint: ILngLat;
protected endPoint: ILngLat;
protected pointFeatures: Feature[];
protected centerLayer: ILayer;
constructor(scene: Scene, options: Partial<IDrawFeatureOption> = {}) {
super(scene, options);
this.type = 'circle';
}
public drawFinish() {
return null;
}
public setCurrentFeature(feature: Feature) {
this.currentFeature = feature as Feature;
// @ts-ignore
this.pointFeatures = feature.properties.pointFeatures;
// @ts-ignore
this.startPoint = feature.properties.startPoint;
// @ts-ignore
this.endPoint = feature.properties.endPoint;
this.source.setFeatureActive(feature);
}
protected getDefaultOptions(): Partial<IDrawFeatureOption> {
return {
...super.getDefaultOptions(),
title: '绘制圆',
};
}
protected onDragStart = (e: IInteractionTarget) => {
if (this.drawStatus !== 'Drawing') {
this.drawLayer.emit('unclick', null);
}
this.startPoint = e.lngLat;
this.setCursor('grabbing');
this.initCenterLayer();
this.centerLayer.setData([this.startPoint]);
};
protected onDragging = (e: IInteractionTarget) => {
this.endPoint = e.lngLat;
const feature = this.createFeature() as Feature<Geometries, Properties>;
const properties = feature.properties as { pointFeatures: Feature[] };
this.drawLayer.update(featureCollection([feature]));
this.drawVertexLayer.update(featureCollection(properties.pointFeatures));
};
protected onDragEnd = () => {
const feature = this.createFeature(`${this.getUniqId()}`);
const properties = feature.properties as { pointFeatures: Feature[] };
this.drawLayer.update(featureCollection([feature]));
this.drawVertexLayer.update(featureCollection(properties.pointFeatures));
this.emit(DrawEvent.CREATE, this.currentFeature);
this.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_SELECT);
this.disable();
};
protected moveFeature(delta: ILngLat): void {
const newFeature = moveFeatures([this.currentFeature as Feature], delta);
this.drawLayer.updateData(featureCollection(newFeature));
const newPointFeture = moveFeatures(this.pointFeatures, delta);
this.drawVertexLayer.updateData(featureCollection(newPointFeture));
const newStartPoint = movePoint(
[this.startPoint.lng, this.startPoint.lat],
delta,
);
this.startPoint = {
lat: newStartPoint[1],
lng: newStartPoint[0],
};
const newEndPoint = movePoint(
[this.endPoint.lng, this.endPoint.lat],
delta,
);
const endPointObj = {
lat: newEndPoint[1],
lng: newEndPoint[0],
};
newFeature[0].properties = {
...newFeature[0].properties,
startPoint: this.startPoint,
endPoint: endPointObj,
pointFeatures: newPointFeture,
};
this.centerLayer.setData([this.startPoint]);
this.setCurrentFeature(newFeature[0]);
const changeFeature = {
...newFeature[0],
};
this.emit(DrawEvent.CHANGE, changeFeature);
}
protected createFeature(id: string = '0'): Feature {
const points = createPoint([this.endPoint]);
const feature = createCircle(
[this.startPoint.lng, this.startPoint.lat],
[this.endPoint.lng, this.endPoint.lat],
{
pointFeatures: points.features,
units: this.getOption('units'),
steps: this.getOption('steps'),
id,
},
);
this.setCurrentFeature(feature as Feature);
return feature;
}
protected editFeature(endPoint: ILngLat): void {
this.endPoint = endPoint;
const newFeature = this.createFeature();
const properties = newFeature.properties as { pointFeatures: Feature[] };
this.drawLayer.updateData(featureCollection([newFeature]));
this.drawVertexLayer.updateData(
featureCollection(properties.pointFeatures),
);
this.emit(DrawEvent.CHANGE, featureCollection([newFeature]).features[0]);
}
protected showOtherLayer() {
this.centerLayer.setData([this.currentFeature?.properties?.startPoint]);
this.centerLayer.show();
}
protected hideOtherLayer() {
if (this.currentFeature) {
this.centerLayer.hide();
}
}
private initCenterLayer() {
const centerStyle = this.getStyle('active').point;
const layer = new PointLayer()
.source([this.startPoint], {
parser: {
type: 'json',
x: 'lng',
y: 'lat',
},
})
.shape('circle')
.color(centerStyle.color)
.size(centerStyle.size)
.style(centerStyle.style);
this.scene.addLayer(layer);
this.centerLayer = layer;
}
}

View File

@ -1,38 +0,0 @@
import { IInteractionTarget, ILngLat, Scene } from '@antv/l7';
import { Feature } from '@turf/helpers';
import { DrawEvent } from '../util/constant';
import { IDrawFeatureOption } from './draw_feature';
import DrawFeature, { IDrawOption } from './draw_mode';
export default class DrawDelete extends DrawFeature {
// 绘制完成之后显示
constructor(scene: Scene, options: Partial<IDrawFeatureOption> = {}) {
super(scene, options);
}
public enable() {
this.emit(DrawEvent.DELETE, '');
}
public disable() {
return null;
}
protected getDefaultOptions(): Partial<IDrawFeatureOption> {
return {
...super.getDefaultOptions(),
title: '删除图形',
};
}
protected onDragStart(e: any): void {
throw new Error('Method not implemented.');
}
protected onDragging = (e: IInteractionTarget) => {
return;
};
protected onDragEnd = () => {
throw new Error('Method not implemented.');
};
protected onClick = () => {
return null;
};
}

View File

@ -1,43 +0,0 @@
import { IInteractionTarget, ILngLat, Scene } from '@antv/l7';
import { Feature } from '@turf/helpers';
import { DrawEvent } from '../util/constant';
import { IDrawFeatureOption } from './draw_feature';
import DrawFeature, { IDrawOption } from './draw_mode';
export default class DrawEdit extends DrawFeature {
private endPoint: ILngLat;
// 绘制完成之后显示
constructor(scene: Scene, options: Partial<IDrawFeatureOption> = {}) {
super(scene, options);
}
public setEditFeature(feature: Feature) {
this.currentFeature = feature;
}
protected onDragStart = (e: IInteractionTarget) => {
// @ts-ignore
};
protected getDefaultOptions() {
return {
steps: 64,
units: 'kilometres',
cursor: 'move',
};
}
protected onDragging = (e: IInteractionTarget) => {
this.endPoint = e.lngLat;
this.emit(DrawEvent.Edit, this.endPoint);
return;
};
protected onDragEnd = () => {
this.emit(DrawEvent.UPDATE, this.currentFeature);
this.resetCursor();
this.disable();
};
protected onClick = () => {
return null;
};
}

View File

@ -1,262 +0,0 @@
import { IInteractionTarget, ILayer, ILngLat, Popup, Scene } from '@antv/l7';
import {
Feature,
FeatureCollection,
featureCollection,
point,
Units,
unitsFactors,
} from '@turf/helpers';
import DrawRender from '../render/draw';
import RenderLayer from '../render/draw_result';
import DrawVertexLayer from '../render/draw_vertex';
import { DrawEvent, DrawModes } from '../util/constant';
import DrawDelete from './draw_delete';
import DrawEdit from './draw_edit';
import DrawMode, { IDrawOption } from './draw_mode';
import DrawSelected from './draw_selected';
export interface IDrawFeatureOption extends IDrawOption {
units: Units;
steps: number;
editEnable: boolean;
selectEnable: boolean;
cursor: string;
}
export default abstract class DrawFeature extends DrawMode {
// 绘制完成之后显示
public selectMode: DrawSelected;
public editMode: DrawEdit;
public deleteMode: DrawDelete;
public editEnable: boolean;
public selectEnable: boolean;
protected normalLayer: RenderLayer;
protected drawLayer: DrawRender;
protected drawVertexLayer: DrawVertexLayer;
constructor(scene: Scene, options: Partial<IDrawFeatureOption> = {}) {
super(scene, options);
this.drawLayer = new DrawRender(this);
this.drawVertexLayer = new DrawVertexLayer(this);
this.normalLayer = new RenderLayer(this);
this.selectEnable = this.getOption('selectEnable');
this.editEnable = this.getOption('editEnable');
// this.editLayer = new EditLayer(this);
this.selectMode = new DrawSelected(this.scene, {});
this.editMode = new DrawEdit(this.scene, {});
this.deleteMode = new DrawDelete(this.scene, {});
this.selectMode.on(DrawEvent.UPDATE, this.onDrawUpdate);
this.selectMode.on(DrawEvent.Move, this.onDrawMove);
this.editMode.on(DrawEvent.MODE_CHANGE, this.onModeChange);
this.editMode.on(DrawEvent.UPDATE, this.onDrawUpdate);
this.editMode.on(DrawEvent.Edit, this.onDrawEdit);
this.selectMode.on(DrawEvent.MODE_CHANGE, this.onModeChange);
this.deleteMode.on(DrawEvent.DELETE, this.onDrawDelete);
this.on(DrawEvent.CREATE, this.onDrawCreate);
this.on(DrawEvent.MODE_CHANGE, this.onModeChange);
document.addEventListener('keydown', this.addKeyDownEvent);
if (this.options.data && this.initData()) {
this.normalLayer.update(this.source.data);
this.normalLayer.enableSelect();
}
}
public abstract drawFinish(): void;
public setCurrentFeature(feature: Feature) {
this.currentFeature = feature as Feature;
// @ts-ignore
this.pointFeatures = feature.properties.pointFeatures;
this.source.setFeatureActive(feature);
}
public deleteCurrentFeature() {
this.deleteMode.enable();
}
public disableLayer() {
// this.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
this.drawLayer.disableSelect();
}
public enableLayer() {
this.drawLayer.enableSelect();
}
public getData(): FeatureCollection {
return this.source.getData();
}
public removeAllData(): void {
this.source.removeAllFeatures();
this.currentFeature = null;
this.drawLayer.hide();
this.drawVertexLayer.hide();
this.normalLayer.hide();
this.hideOtherLayer();
}
public clear() {
this.drawLayer.disableSelect();
this.drawLayer.disableEdit();
this.drawLayer.hide();
this.drawVertexLayer.hide();
this.hideOtherLayer();
this.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
}
public reset() {
this.drawLayer.show();
this.drawVertexLayer.show();
this.showOtherLayer();
}
public addVertex(feature: Feature): void {
throw new Error('子类未实现该方法');
}
public onRemove() {
this.destroy();
this.selectMode.destroy();
this.editMode.destroy();
this.source.destroy();
this.drawLayer.destroy();
this.drawVertexLayer.destroy();
this.normalLayer.destroy();
document.removeEventListener('keydown', this.addKeyDownEvent);
}
protected getDefaultOptions(): Partial<IDrawFeatureOption> {
return {
steps: 64,
units: 'kilometers',
cursor: 'crosshair',
editEnable: true,
selectEnable: true,
};
}
protected abstract onDragStart(e: IInteractionTarget): void;
protected abstract onDragging(e: IInteractionTarget): void;
protected abstract onDragEnd(e: IInteractionTarget): void;
protected abstract createFeature(e?: any): Feature;
protected abstract moveFeature(e: ILngLat): void;
protected abstract editFeature(e: any): void;
protected abstract hideOtherLayer(): void;
protected abstract showOtherLayer(): void;
protected initData(): boolean {
return false;
}
private addDrawPopup(lnglat: ILngLat, dis: number) {
const popup = new Popup({
anchor: 'left',
closeButton: false,
})
.setLnglat(lnglat)
.setText(`半径:${dis.toFixed(2)}千米`);
this.scene.addPopup(popup);
this.popup = popup;
}
private onModeChange = (mode: DrawModes[any]) => {
switch (mode) {
case DrawModes.DIRECT_SELECT:
if (!this.editEnable) {
return;
}
this.editMode.enable();
this.editMode.setEditFeature(this.currentFeature as Feature);
this.drawLayer.updateData(
featureCollection([this.currentFeature as Feature]),
);
this.drawVertexLayer.updateData(
featureCollection(this.currentFeature?.properties?.pointFeatures),
);
this.drawVertexLayer.show();
this.drawVertexLayer.enableEdit();
this.showOtherLayer();
this.drawStatus = 'DrawEdit';
break;
case DrawModes.SIMPLE_SELECT:
if (!this.selectEnable) {
this.drawLayer.hide();
this.drawVertexLayer.hide();
this.hideOtherLayer();
this.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
return;
}
this.selectMode.setSelectedFeature(this.currentFeature as Feature);
this.selectMode.enable();
this.drawLayer.updateData(
// TODO:导入数据不能正常使用
featureCollection([this.currentFeature as Feature]),
);
this.drawLayer.enableSelect();
this.drawVertexLayer.updateData(
featureCollection(this.currentFeature?.properties?.pointFeatures),
);
this.drawVertexLayer.disableEdit();
this.drawVertexLayer.show();
this.drawLayer.show();
this.showOtherLayer();
this.drawStatus = 'DrawSelected';
break;
case DrawModes.STATIC:
this.source.updateFeature(this.currentFeature as Feature);
this.selectMode.disable();
this.editMode.disable();
this.source.clearFeatureActive();
this.drawVertexLayer.hide();
this.drawVertexLayer.disableEdit();
this.hideOtherLayer();
this.normalLayer.update(this.source.data);
this.normalLayer.enableSelect();
this.drawStatus = 'DrawFinish';
break;
}
};
private onDrawCreate = (feature: Feature) => {
this.source.addFeature(feature);
};
private onDrawUpdate = (feature: Feature) => {
this.source.updateFeature(this.currentFeature as Feature);
this.emit(DrawEvent.UPDATE, this.currentFeature);
};
private onDrawMove = (delta: ILngLat) => {
if (this.drawStatus === 'DrawSelected') {
this.moveFeature(delta);
}
};
private onDrawEdit = (endpoint: ILngLat) => {
this.editFeature(endpoint);
};
private onDrawDelete = () => {
if (this.drawStatus === 'DrawSelected') {
this.clear();
this.source.removeFeature(this.currentFeature as Feature);
this.normalLayer.update(this.source.data);
this.drawLayer.disableSelect();
this.selectMode.disable();
this.currentFeature = null;
// this.drawStatus = 'DrawDelete';
}
};
private addKeyDownEvent = (event: KeyboardEvent) => {
// tslint:disable-next-line:no-arg
const e = event || window.event;
if (e && e.keyCode === 8) {
this.deleteMode.enable();
}
};
}

View File

@ -1,68 +0,0 @@
import { ILngLat, Scene } from '@antv/l7';
import { Feature, featureCollection } from '@turf/helpers';
import { unitsType } from '../util/constant';
import { createLine, createPoint } from '../util/create_geometry';
import moveFeatures from '../util/move_featrues';
import { IDrawFeatureOption } from './draw_feature';
import DrawPolygon from './draw_polygon';
export interface IDrawRectOption extends IDrawFeatureOption {
units: unitsType;
steps: number;
}
export default class DrawLine extends DrawPolygon {
constructor(scene: Scene, options: Partial<IDrawRectOption> = {}) {
super(scene, options);
this.type = 'line';
}
protected getDefaultOptions(): Partial<IDrawFeatureOption> {
return {
...super.getDefaultOptions(),
title: '绘制线',
};
}
protected moveFeature(delta: ILngLat): Feature {
const newFeature = moveFeatures([this.currentFeature as Feature], delta);
const newPointFeture = moveFeatures(this.pointFeatures, delta);
this.drawLayer.updateData(featureCollection(newFeature));
this.drawVertexLayer.updateData(featureCollection(newPointFeture));
this.currentFeature = newFeature[0];
this.pointFeatures = newPointFeture;
return this.currentFeature;
}
protected createFeature(
points: ILngLat[],
id?: string,
active: boolean = true,
): Feature {
const pointfeatures = createPoint(points);
this.pointFeatures = pointfeatures.features;
const feature = createLine(points, {
id: id || this.getUniqId(),
type: 'line',
active,
pointFeatures: this.pointFeatures,
});
this.setCurrentFeature(feature as Feature);
return feature;
}
protected initData(): boolean {
const features: Feature[] = [];
this.source.data.features.forEach((feature) => {
if (feature.geometry.type === 'LineString') {
// @ts-ignore
const points = feature.geometry.coordinates.map((coord) => {
return {
lng: coord[0],
lat: coord[1],
};
});
features.push(
this.createFeature(points, feature?.properties?.id, false),
);
}
});
this.source.data.features = features;
return true;
}
}

View File

@ -1,142 +0,0 @@
import { IInteractionTarget, IPopup, Scene } from '@antv/l7';
import { Feature, FeatureCollection } from '@turf/helpers';
import { EventEmitter } from 'eventemitter3';
// tslint:disable-next-line:no-submodule-imports
import merge from 'lodash/merge';
import DrawSource from '../source';
import LayerStyles from '../util/layerstyle';
export interface IDrawOption {
data: FeatureCollection;
title: string;
style: any;
}
export type DrawStatus =
| 'Drawing'
| 'DrawSelected'
| 'DrawEdit'
| 'DrawFinish'
| 'EditFinish'
| 'DrawDelete';
let DrawFeatureId = 0;
export default abstract class DrawMode extends EventEmitter {
public source: DrawSource;
public scene: Scene;
public type: string;
public title: string;
public isEnable: boolean = false;
protected options: {
[key: string]: any;
} = {
style: LayerStyles,
};
protected drawStatus: DrawStatus = 'Drawing';
protected currentFeature: Feature | null;
protected currentVertex: Feature | null;
protected popup: IPopup;
constructor(scene: Scene, options: Partial<IDrawOption> = {}) {
super();
const { data } = options;
this.scene = scene;
this.source = new DrawSource(data);
this.options = merge(this.options, this.getDefaultOptions(), options);
this.title = this.getOption('title');
}
public enable() {
if (this.isEnable) {
return;
}
// @ts-ignore
this.scene.setMapStatus({
dragEnable: false,
});
this.scene.on('dragstart', this.onDragStart);
this.scene.on('dragging', this.onDragging);
this.scene.on('dragend', this.onDragEnd);
this.scene.on('click', this.onClick);
this.setCursor(this.getOption('cursor'));
this.isEnable = true;
}
public disable() {
if (!this.isEnable) {
return;
}
this.scene.off('dragstart', this.onDragStart);
this.scene.off('dragging', this.onDragging);
this.scene.off('dragend', this.onDragEnd);
this.scene.off('click', this.onClick);
this.resetCursor();
// @ts-ignore
this.scene.setMapStatus({
dragEnable: true,
});
this.isEnable = false;
}
public setCurrentFeature(feature: Feature) {
this.currentFeature = feature;
this.source.setFeatureActive(feature);
}
public setCurrentVertex(feature: Feature) {
this.currentVertex = feature;
}
public deleteCurrentFeature() {
throw new Error('子类未实现该方法');
}
public getCurrentVertex(): Feature {
return this.currentVertex as Feature;
}
public getCurrentFeature(): Feature {
return this.currentFeature as Feature;
}
public getOption(key: string) {
return this.options[key];
}
public getStyle(id: string) {
return this.getOption('style')[id];
}
public getUniqId() {
return DrawFeatureId++;
}
public setCursor(cursor: string) {
const container = this.scene.getMapCanvasContainer();
if (container) {
container.style.cursor = cursor;
}
}
public resetCursor() {
const container = this.scene.getMapCanvasContainer();
if (container) {
container.removeAttribute('style');
}
}
public destroy() {
DrawFeatureId = 0;
this.removeAllListeners();
this.disable();
}
protected getDefaultOptions(): any {
return {};
}
protected abstract onDragStart(e: IInteractionTarget): void;
protected abstract onDragging(e: IInteractionTarget): void;
protected abstract onDragEnd(e: IInteractionTarget): void;
protected onClick(e: IInteractionTarget): any {
return null;
}
}

View File

@ -1,100 +0,0 @@
import { IInteractionTarget, ILayer, ILngLat, Scene } from '@antv/l7';
import { Feature, featureCollection, point } from '@turf/helpers';
import { DrawEvent, DrawModes, unitsType } from '../util/constant';
import moveFeatures from '../util/move_featrues';
import DrawFeature, { IDrawFeatureOption } from './draw_feature';
export default class DrawPoint extends DrawFeature {
protected pointFeatures: Feature[];
constructor(scene: Scene, options: Partial<IDrawFeatureOption> = {}) {
super(scene, options);
this.type = 'point';
}
public drawFinish() {
this.emit(DrawEvent.CREATE, this.currentFeature);
this.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_SELECT);
this.disable();
}
protected getDefaultOptions(): Partial<IDrawFeatureOption> {
return {
...super.getDefaultOptions(),
title: '绘制点',
};
}
protected onDragStart = (e: IInteractionTarget) => {
return null;
};
protected onDragging = (e: IInteractionTarget) => {
return null;
};
protected onDragEnd = () => {
return null;
};
protected onClick = (e: any) => {
if (this.drawStatus !== 'Drawing') {
this.drawLayer.emit('unclick', null);
}
const lngLat = e.lngLat || e.lnglat;
const feature = this.createFeature(lngLat);
this.drawLayer.update(featureCollection([feature]));
this.drawVertexLayer.update(featureCollection([feature]));
this.drawFinish();
};
protected moveFeature(delta: ILngLat): Feature {
const newFeature = moveFeatures([this.currentFeature as Feature], delta);
this.drawLayer.updateData(featureCollection(newFeature));
this.drawVertexLayer.updateData(featureCollection(newFeature));
this.currentFeature = newFeature[0];
this.pointFeatures = newFeature;
this.currentFeature.properties = {
...this.currentFeature.properties,
pointFeatures: newFeature,
};
return this.currentFeature;
}
protected createFeature(
p: ILngLat,
id?: string,
active: boolean = true,
): Feature {
const feature = point([p.lng, p.lat], {
id: id || this.getUniqId(),
type: 'point',
active,
pointFeatures: [point([p.lng, p.lat])],
});
this.setCurrentFeature(feature as Feature);
return feature;
}
protected initData(): boolean {
const features: Feature[] = [];
this.source.data.features.forEach((feature) => {
if (feature.geometry.type === 'Point') {
const p = {
lng: feature.geometry.coordinates[0] as number,
lat: feature.geometry.coordinates[1] as number,
};
features.push(this.createFeature(p, feature?.properties?.id, false));
}
});
this.source.data.features = features;
return true;
}
protected editFeature(endPoint: ILngLat): void {
this.createFeature(endPoint);
}
protected showOtherLayer() {
return null;
}
protected hideOtherLayer() {
return null;
}
}

View File

@ -1,282 +0,0 @@
import { IInteractionTarget, ILayer, ILngLat, Scene } from '@antv/l7';
import {
Feature,
FeatureCollection,
featureCollection,
Geometries,
point,
Position,
Properties,
} from '@turf/helpers';
import DrawMidVertex from '../render/draw_mid_vertex';
import { DrawEvent, DrawModes, unitsType } from '../util/constant';
import { createPoint, createPolygon } from '../util/create_geometry';
import moveFeatures from '../util/move_featrues';
import DrawFeature, { IDrawFeatureOption } from './draw_feature';
export interface IDrawRectOption extends IDrawFeatureOption {
units: unitsType;
steps: number;
}
export default class DrawPolygon extends DrawFeature {
protected startPoint: ILngLat;
protected endPoint: ILngLat;
protected points: ILngLat[] = [];
protected pointFeatures: Feature[];
protected drawMidVertexLayer: DrawMidVertex;
constructor(scene: Scene, options: Partial<IDrawRectOption> = {}) {
super(scene, options);
this.type = 'polygon';
this.drawMidVertexLayer = new DrawMidVertex(this);
this.on(DrawEvent.MODE_CHANGE, this.addMidLayerEvent);
}
public enable() {
super.enable();
this.scene.on('mousemove', this.onMouseMove);
this.scene.on('dblclick', this.onDblClick);
// 关闭双击放大
}
public disable() {
super.disable();
this.scene.off('mousemove', this.onMouseMove);
this.scene.off('dblclick', this.onDblClick);
}
public drawFinish() {
const feature = this.createFeature(this.points);
const properties = feature.properties as { pointFeatures: Feature[] };
this.drawLayer.update(featureCollection([feature]));
this.drawVertexLayer.update(featureCollection(properties.pointFeatures));
// @ts-ignore
this.emit(DrawEvent.CREATE, this.currentFeature);
this.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_SELECT);
this.points = [];
this.disable();
}
public addVertex(vertex: Feature<Geometries, Properties>) {
// @ts-ignore
const id = vertex.properties.id;
const coord = vertex?.geometry?.coordinates as Position;
const feature = this.currentFeature as Feature<Geometries, Properties>;
const type = feature?.geometry?.type;
const points = [];
if (type === 'Polygon') {
const coords = feature?.geometry?.coordinates as Position[][];
coords[0].splice(id + 1, 0, coord);
for (let i = 0; i < coords[0].length - 1; i++) {
points.push({
lng: coords[0][i][0],
lat: coords[0][i][1],
});
}
} else {
const coords = feature?.geometry?.coordinates as Position[];
coords.splice(id + 1, 0, coord);
for (const coor of coords) {
points.push({
lng: coor[0],
lat: coor[1],
});
}
}
const pointfeatures = createPoint(points);
this.pointFeatures = pointfeatures.features;
this.drawLayer.updateData(featureCollection([feature]));
this.drawVertexLayer.updateData(pointfeatures);
this.drawMidVertexLayer.updateData(featureCollection(this.pointFeatures));
// @ts-ignore
feature.properties.pointFeatures = pointfeatures.features;
this.setCurrentFeature(feature);
}
protected getDefaultOptions(): Partial<IDrawFeatureOption> {
return {
...super.getDefaultOptions(),
title: '绘制多边形',
};
}
protected onDragStart = (e: IInteractionTarget) => {
return null;
};
protected onDragging = (e: IInteractionTarget) => {
return null;
};
protected onDragEnd = () => {
return null;
};
protected onClick = (e: any) => {
if (this.drawStatus !== 'Drawing') {
this.drawLayer.emit('unclick', null);
}
const lngLat = e.lngLat || e.lnglat;
this.endPoint = lngLat;
this.points.push(lngLat);
const feature = this.createFeature(this.points);
const pointfeatures = createPoint([this.points[0], this.endPoint]);
this.drawLayer.update(featureCollection([feature]));
this.drawVertexLayer.update(featureCollection(pointfeatures.features));
this.onDraw();
};
protected onMouseMove = (e: any) => {
const lngLat = e.lngLat || e.lnglat;
if (this.points.length === 0) {
return;
}
const tmpPoints = this.points.slice();
tmpPoints.push(lngLat);
const feature = this.createFeature(tmpPoints);
this.drawLayer.update(featureCollection([feature]));
};
protected onDblClick = (e: any) => {
const lngLat = e.lngLat || e.lnglat;
if (this.points.length < 2) {
return;
}
this.points.push(lngLat);
this.drawFinish();
};
protected moveFeature(delta: ILngLat): void {
const newFeature = moveFeatures([this.currentFeature as Feature], delta);
const newPointFeture = moveFeatures(this.pointFeatures, delta);
this.drawLayer.updateData(featureCollection(newFeature));
this.drawVertexLayer.updateData(featureCollection(newPointFeture));
newFeature[0].properties = {
...newFeature[0].properties,
pointFeatures: newPointFeture,
};
this.setCurrentFeature(newFeature[0]);
}
protected createFeature(
points: ILngLat[],
id?: string,
active: boolean = true,
): Feature {
const pointfeatures = createPoint(points);
this.pointFeatures = pointfeatures.features;
const feature = createPolygon(points, {
id: id || this.getUniqId(),
type: 'polygon',
active,
pointFeatures: this.pointFeatures,
});
this.setCurrentFeature(feature as Feature);
return feature;
}
protected editFeature(vertex: ILngLat): void {
const selectVertexed = this.currentVertex as Feature<
Geometries,
Properties
>;
if (selectVertexed === null) {
return;
} else {
// @ts-ignore
const id = selectVertexed.properties.id * 1;
// @ts-ignore
selectVertexed.geometry.coordinates = [vertex.lng, vertex.lat];
// @ts-ignore
this.pointFeatures[id].geometry.coordinates = [vertex.lng, vertex.lat];
this.drawVertexLayer.updateData(featureCollection(this.pointFeatures));
this.drawMidVertexLayer.updateData(featureCollection(this.pointFeatures));
this.editPolygonVertex(id, vertex);
this.drawLayer.updateData(
featureCollection([this.currentFeature as Feature]),
);
const feature = this.currentFeature as Feature;
feature.properties = {
...this.currentFeature?.properties,
pointFeatures: this.pointFeatures,
};
this.setCurrentFeature(feature);
}
}
protected onDraw = () => {
this.drawVertexLayer.on('mousemove', (e: any) => {
this.setCursor('pointer');
});
this.drawVertexLayer.on('mouseout', () => {
this.setCursor('crosshair');
});
this.drawVertexLayer.on('click', () => {
this.resetCursor();
this.drawFinish();
});
};
protected showOtherLayer() {
// if (this.editMode.isEnable) {
// this.drawMidVertexLayer.update(featureCollection(this.pointFeatures));
// this.drawMidVertexLayer.show();
// }
return null;
}
protected hideOtherLayer() {
return null;
}
protected addMidLayerEvent(mode: DrawModes[any]) {
switch (mode) {
case DrawModes.DIRECT_SELECT:
this.drawMidVertexLayer.update(featureCollection(this.pointFeatures));
this.drawMidVertexLayer.show();
break;
case DrawModes.STATIC:
this.drawMidVertexLayer.hide();
break;
}
}
protected initData(): boolean {
const features: Feature[] = [];
this.source.data.features.forEach((feature) => {
if (feature.geometry.type === 'Polygon') {
const points = (feature.geometry.coordinates[0] as Position[]).map(
(coord) => {
return {
lng: coord[0],
lat: coord[1],
};
},
);
features.push(
this.createFeature(points.slice(1), feature?.properties?.id, false),
);
}
});
this.source.data.features = features;
return true;
}
private editPolygonVertex(id: number, vertex: ILngLat) {
const feature = this.currentFeature as Feature<Geometries, Properties>;
const type = feature?.geometry?.type;
if (type === 'Polygon') {
const coords = feature?.geometry?.coordinates as Position[][];
coords[0][id] = [vertex.lng, vertex.lat];
if (-id === 0) {
coords[0][coords[0].length - 1] = [vertex.lng, vertex.lat];
}
} else {
const coords = feature?.geometry?.coordinates as Position[];
coords[id] = [vertex.lng, vertex.lat];
}
this.setCurrentFeature(feature);
this.drawLayer.updateData(
featureCollection([this.currentFeature as Feature]),
);
}
}
/**
* draw
* select Polyon
* edit
*/

View File

@ -1,40 +0,0 @@
import { Scene } from '@antv/l7';
import {
Feature,
FeatureCollection,
featureCollection,
point,
} from '@turf/helpers';
import { unitsType } from '../util/constant';
import { createPoint, createRect } from '../util/create_geometry';
import DrawCircle from './draw_circle';
import { IDrawFeatureOption } from './draw_feature';
export default class DrawRect extends DrawCircle {
constructor(scene: Scene, options: Partial<IDrawFeatureOption> = {}) {
super(scene, options);
this.type = 'rect';
}
public drawFinish() {
return null;
}
protected getDefaultOptions(): Partial<IDrawFeatureOption> {
return {
...super.getDefaultOptions(),
title: '绘制矩形',
};
}
protected createFeature(id: string = '0'): Feature {
const points = createPoint([this.endPoint]);
const feature = createRect(
[this.startPoint.lng, this.startPoint.lat],
[this.endPoint.lng, this.endPoint.lat],
{
id,
pointFeatures: points.features,
},
);
this.setCurrentFeature(feature as Feature);
return feature;
}
}

View File

@ -1,63 +0,0 @@
import {
IInteractionTarget,
ILayer,
ILngLat,
IPopup,
LineLayer,
PointLayer,
PolygonLayer,
Popup,
Scene,
} from '@antv/l7';
import { Feature, featureCollection, point } from '@turf/helpers';
import { DrawEvent, DrawModes } from '../util/constant';
import moveFeatures from '../util/move_featrues';
import { IDrawFeatureOption } from './draw_feature';
import DrawFeature, { IDrawOption } from './draw_mode';
const InitFeature = {
type: 'FeatureCollection',
features: [],
};
export default class DrawSelect extends DrawFeature {
private center: ILngLat;
private dragStartPoint: ILngLat;
// 绘制完成之后显示
constructor(scene: Scene, options: Partial<IDrawFeatureOption> = {}) {
super(scene, options);
}
public setSelectedFeature(feature: Feature) {
this.currentFeature = feature;
}
protected onDragStart = (e: IInteractionTarget) => {
this.scene.setMapStatus({ dragEnable: false });
this.dragStartPoint = e.lngLat;
};
protected getDefaultOptions(): Partial<IDrawFeatureOption> {
return {
steps: 64,
units: 'kilometers',
cursor: 'move',
};
}
protected onDragging = (e: IInteractionTarget) => {
const delta = {
lng: e.lngLat.lng - this.dragStartPoint.lng,
lat: e.lngLat.lat - this.dragStartPoint.lat,
};
this.emit(DrawEvent.Move, delta);
this.dragStartPoint = e.lngLat;
return;
};
protected onDragEnd = () => {
this.emit(DrawEvent.UPDATE, this.currentFeature);
};
protected onClick = () => {
return null;
};
}

View File

@ -1,18 +0,0 @@
import DrawCircle from './draw_circle';
import DrawDelete from './draw_delete';
import DrawFeature from './draw_feature';
import DrawLine from './draw_line';
import DrawMode from './draw_mode';
import DrawPoint from './draw_point';
import DrawPolygon from './draw_polygon';
import DrawRect from './draw_rect';
export {
DrawCircle,
DrawFeature,
DrawRect,
DrawPolygon,
DrawPoint,
DrawLine,
DrawMode,
DrawDelete,
};

View File

@ -1,69 +0,0 @@
import { IInteractionTarget, ILayer, Scene } from '@antv/l7';
const InitFeature = {
type: 'FeatureCollection',
features: [],
};
type CallBack = (...args: any[]) => any;
import { FeatureCollection } from '@turf/helpers';
import Draw from '../modes/draw_feature';
import { DrawEvent, DrawModes } from '../util/constant';
import { renderFeature } from './renderFeature';
export default class BaseRenderLayer {
public drawLayers: ILayer[] = [];
protected draw: Draw;
protected isEnableDrag: boolean;
protected isEnableEdit: boolean;
constructor(draw: Draw) {
this.draw = draw;
}
public update(feature: FeatureCollection) {
if (this.drawLayers.length > 0) {
this.updateData(feature);
}
this.removeLayers();
const style = this.draw.getStyle('normal');
this.drawLayers = renderFeature(feature, style);
this.addLayers();
}
public on(type: any, handler: CallBack) {
const layer = this.drawLayers[0];
layer.on(type, handler);
}
public off(type: any, handler: CallBack) {
const layer = this.drawLayers[0];
layer.off(type, handler);
}
public emit(type: string, e: any) {
const layer = this.drawLayers[0];
layer.emit(type, e);
}
public updateData(data: any) {
if (this.drawLayers.length === 0) {
this.update(data);
}
this.drawLayers.forEach((layer) => layer.setData(data));
}
public destroy() {
this.removeLayers();
}
public removeLayers() {
if (this.drawLayers.length !== 0) {
this.drawLayers.forEach((layer) => this.draw.scene.removeLayer(layer));
}
}
public addLayers() {
this.drawLayers.forEach((layer) => this.draw.scene.addLayer(layer));
}
public show() {
this.drawLayers.forEach((layer) => layer.show());
}
public hide() {
this.drawLayers.forEach((layer) => layer.hide());
}
}

View File

@ -1,91 +0,0 @@
import { IInteractionTarget, ILayer, Scene } from '@antv/l7';
const InitFeature = {
type: 'FeatureCollection',
features: [],
};
import { Feature, FeatureCollection } from '@turf/helpers';
import Draw from '../modes/draw_feature';
import { DrawEvent, DrawModes } from '../util/constant';
import BaseRender from './base_render';
import { renderFeature } from './renderFeature';
export default class DrawLayer extends BaseRender {
public update(feature: FeatureCollection) {
this.removeLayers();
const style = this.draw.getStyle('active');
this.drawLayers = renderFeature(feature, style);
this.addLayers();
}
public enableSelect() {
this.show();
if (this.isEnableDrag) {
return;
}
const layer = this.drawLayers[0];
layer.on('mouseenter', this.onMouseMove);
layer.on('mouseout', this.onUnMouseMove);
if (this.draw.editEnable) {
layer.on('click', this.onClick);
}
layer.on('unclick', this.onUnClick);
this.isEnableDrag = true;
}
public disableSelect() {
if (!this.isEnableDrag) {
return;
}
const layer = this.drawLayers[0];
layer.off('mouseenter', this.onMouseMove);
layer.off('mouseout', this.onUnMouseMove);
layer.off('click', this.onClick);
layer.off('unclick', this.onUnClick);
this.isEnableDrag = false;
}
public enableEdit() {
if (this.isEnableEdit) {
return;
}
const layer = this.drawLayers[0];
layer.on('unclick', this.onUnClick);
this.isEnableDrag = true;
}
public disableEdit() {
if (!this.isEnableEdit) {
return;
}
const layer = this.drawLayers[0];
layer.off('unclick', this.onUnClick);
this.isEnableDrag = false;
}
private onMouseMove = (e: any) => {
this.draw.setCursor('move');
this.draw.selectMode.enable();
};
private onUnMouseMove = (e: any) => {
this.draw.resetCursor();
this.draw.selectMode.disable();
};
private onClick = (e: any) => {
this.draw.selectMode.disable();
this.draw.editMode.enable();
this.disableSelect();
this.draw.resetCursor();
this.enableEdit();
this.draw.setCurrentFeature(e.feature);
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.DIRECT_SELECT);
};
private onUnClick = (e: any) => {
this.draw.selectMode.disable();
this.draw.editMode.disable();
this.draw.source.setFeatureUnActive(
this.draw.getCurrentFeature() as Feature,
);
this.disableSelect();
this.disableEdit();
this.hide();
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
};
}

View File

@ -1,72 +0,0 @@
import {
feature,
Feature,
featureCollection,
FeatureCollection,
Point,
Properties,
} from '@turf/helpers';
import midPoint from '@turf/midpoint';
import BaseRender from './base_render';
import { renderFeature } from './renderFeature';
export default class DrawVertexLayer extends BaseRender {
public update(pointFeatures: FeatureCollection) {
this.removeLayers();
const midFeatures = this.calcMidPointData(pointFeatures);
const style = this.draw.getStyle('mid_point');
this.drawLayers = renderFeature(midFeatures, style);
this.addLayers();
this.enableEdit();
}
public updateData(data: any) {
const midFeatures = this.calcMidPointData(data);
this.drawLayers.forEach((layer) => layer.setData(midFeatures));
}
public enableEdit() {
const layer = this.drawLayers[0];
layer.on('mouseenter', this.onMouseEnter);
layer.on('mouseout', this.onMouseOut);
layer.on('click', this.onClick);
}
public disableEdit() {
const layer = this.drawLayers[0];
layer.off('mouseenter', this.onMouseEnter);
layer.off('mouseout', this.onMouseOut);
layer.off('click', this.onClick);
}
private onMouseEnter = (e: any) => {
this.draw.setCursor('pointer');
};
private onMouseOut = (e: any) => {
this.draw.resetCursor();
};
private onClick = (e: any) => {
this.draw.addVertex(e.feature);
// 添加一个顶点 1.更新顶点 2.更新重点
};
private calcMidPointData(fe: FeatureCollection) {
const midFeatures: Feature[] = [];
fe.features.forEach((item, index) => {
const preFeature = (item as unknown) as Feature<Point, Properties>;
if (this.draw.type === 'line' && index === fe.features.length - 1) {
return;
}
const nextFeature =
index !== fe.features.length - 1
? ((fe.features[index + 1] as unknown) as Feature<Point, Properties>)
: ((fe.features[0] as unknown) as Feature<Point, Properties>);
// @ts-ignore
const point = midPoint(preFeature, nextFeature) as Feature<
Point,
Properties
>;
// @ts-ignore
point.properties.id = index;
midFeatures.push(point);
});
return featureCollection(midFeatures);
}
}

View File

@ -1,67 +0,0 @@
import { Feature, FeatureCollection } from '@turf/helpers';
import { DrawEvent, DrawModes } from '../util/constant';
import BaseRender from './base_render';
import { renderFeature } from './renderFeature';
export default class DrawResultLayer extends BaseRender {
public update(feature: FeatureCollection) {
if (this.drawLayers.length > 0) {
this.updateData(feature);
return;
}
this.removeLayers();
const style = this.draw.getStyle('normal');
this.drawLayers = renderFeature(feature, style);
this.addFilter();
this.addLayers();
}
public enableSelect() {
if (this.isEnableDrag) {
return;
}
if (!this.draw.selectEnable) {
return;
}
const layer = this.drawLayers[0];
layer.on('click', this.onClick);
this.isEnableDrag = true;
}
public disableSelect() {
if (!this.isEnableDrag) {
return;
}
const layer = this.drawLayers[0];
layer.off('click', this.onClick);
this.isEnableDrag = false;
}
public enableDelete() {
this.disableSelect();
const layer = this.drawLayers[0];
layer.on('click', this.onDeleteClick);
}
public disableDelete() {
const layer = this.drawLayers[0];
layer.off('click', this.onDeleteClick);
}
public addFilter() {
this.drawLayers.forEach((layer) =>
layer.filter('active', (active) => {
return !active;
}),
);
}
private onClick = (e: any) => {
this.draw.source.setFeatureUnActive(
this.draw.getCurrentFeature() as Feature,
);
this.draw.setCurrentFeature(e.feature);
this.draw.source.setFeatureActive(e.feature as Feature);
this.updateData(this.draw.source.data);
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_SELECT);
};
private onDeleteClick = (e: any) => {
this.draw.source.removeFeature(e.feature);
this.updateData(this.draw.source.data);
};
}

View File

@ -1,53 +0,0 @@
import { FeatureCollection } from '@turf/helpers';
import BaseRender from './base_render';
import { renderFeature } from './renderFeature';
export default class DrawVertexLayer extends BaseRender {
public update(feature: FeatureCollection) {
this.removeLayers();
const style = this.draw.getStyle('active');
this.drawLayers = renderFeature(feature, style);
this.addLayers();
}
public enableSelect() {
return;
}
public disableSelect() {
return;
}
public enableEdit() {
if (this.isEnableEdit) {
return;
}
const layer = this.drawLayers[0];
layer.on('mouseenter', this.onMouseEnter);
layer.on('mouseout', this.onMouseOut);
layer.on('click', this.onClick);
this.isEnableEdit = true;
}
public disableEdit() {
if (!this.isEnableEdit) {
return;
}
const layer = this.drawLayers[0];
layer.off('mouseenter', this.onMouseEnter);
layer.off('mouseout', this.onMouseOut);
layer.off('click', this.onClick);
this.isEnableEdit = false;
}
private onMouseEnter = (e: any) => {
this.draw.setCursor('move');
this.draw.setCurrentVertex(e.feature);
this.draw.editMode.enable();
};
private onMouseOut = (e: any) => {
this.draw.resetCursor();
this.draw.editMode.disable();
};
private onClick = (e: any) => {
this.draw.setCurrentVertex(e.feature);
this.draw.editMode.enable();
};
}

View File

@ -1,82 +0,0 @@
import {
IInteractionTarget,
ILayer,
ILngLat,
IPopup,
LineLayer,
PointLayer,
PolygonLayer,
Popup,
Scene,
} from '@antv/l7';
const InitFeature = {
type: 'FeatureCollection',
features: [],
};
import Draw from '../modes/draw_mode';
import { DrawEvent, DrawModes } from '../util/constant';
export default class RenderLayer {
private polygonLayer: ILayer;
private lineLayer: ILayer;
private draw: Draw;
constructor(draw: Draw) {
this.draw = draw;
this.init();
}
public init() {
const style = this.draw.getStyle('normal_fill');
const linestyle = this.draw.getStyle('normal_line');
this.polygonLayer = new PolygonLayer({
zIndex: 0,
})
.source(InitFeature)
.filter('active', (active) => {
return !active;
})
.shape('fill')
.active(true)
.color(style.color)
.style(style.style);
this.lineLayer = new LineLayer({
zIndex: 1,
})
.source(InitFeature)
.shape('line')
.filter('active', (active) => {
return !active;
})
.size(linestyle.size)
.color(linestyle.color)
.style(linestyle.style);
this.draw.scene.addLayer(this.polygonLayer);
this.draw.scene.addLayer(this.lineLayer);
this.addLayerEvent();
}
public updateData() {
this.lineLayer.setData(this.draw.source.data);
this.polygonLayer.setData(this.draw.source.data);
}
public destroy() {
this.draw.scene.removeLayer(this.lineLayer);
this.draw.scene.removeLayer(this.polygonLayer);
}
public show() {
this.lineLayer.show();
this.polygonLayer.show();
}
public hide() {
this.lineLayer.hide();
this.polygonLayer.hide();
}
private addLayerEvent() {
this.polygonLayer.on('click', (e) => {
this.draw.setCurrentFeature(e.feature);
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_SELECT);
});
}
}

View File

@ -1,65 +0,0 @@
import { ILayer, LineLayer, PointLayer, PolygonLayer } from '@antv/l7';
import { FeatureCollection } from '@turf/helpers';
export function renderFeature(fe: FeatureCollection, style: any): ILayer[] {
const type = fe.features[0]?.geometry?.type;
let layers;
switch (type) {
case 'Point':
layers = drawPoint(fe, style.point);
break;
case 'LineString':
layers = drawLine(fe, style.line);
break;
case 'Polygon':
layers = drawPolyon(fe, style.polygon);
break;
}
return layers as ILayer[];
}
function drawPoint(fe: FeatureCollection, style: any) {
const layer = new PointLayer({
zIndex: 2,
pickingBuffer: 3,
})
.source(fe)
.shape('circle')
.color(style.color)
.size(style.size)
.style(style.style);
return [layer];
}
function drawLine(fe: FeatureCollection, style: any) {
const layer = new LineLayer({
pickingBuffer: 3,
})
.source(fe)
.shape('line')
.color(style.color)
.size(style.size)
.style(style.style);
return [layer];
}
function drawPolyon(fe: FeatureCollection, style: any) {
const fill = new PolygonLayer()
.source(fe)
.shape('fill')
.color(style.color)
.size(style.size)
.style({
opacity: style.style.opacity,
});
const line = new PolygonLayer()
.source(fe)
.shape('line')
.color(style.style.stroke)
.size(style.style.strokeWidth)
.style({
opacity: style.style.strokeOpacity,
lineType: style.style.lineType,
dashArray: style.style.dashArray,
});
return [fill, line];
}

View File

@ -1,83 +0,0 @@
import { Feature, FeatureCollection } from '@turf/helpers';
// tslint:disable-next-line:no-submodule-imports
import cloneDeep from 'lodash/cloneDeep';
export default class DrawSource {
public data: FeatureCollection;
constructor(data?: FeatureCollection) {
this.data = data || this.getDefaultData();
}
public addFeature(feature: any) {
this.data.features.push(feature);
}
public getData(): FeatureCollection {
const features = cloneDeep(this.data.features).map((feature: Feature) => {
feature.properties = {
id: feature?.properties?.id,
type: feature?.properties?.type,
};
return feature;
});
return {
type: 'FeatureCollection',
features,
};
}
public getFeature(id: string): Feature | undefined {
const result = this.data.features.find((fe: Feature) => {
return fe?.properties?.id === id;
});
return result;
}
public removeAllFeatures() {
this.data = this.getDefaultData();
}
public removeFeature(feature: Feature) {
const index = this.getFeatureIndex(feature);
if (index !== undefined) {
this.data.features.splice(index, 1);
}
}
public setFeatureActive(feature: Feature) {
const fe = this.getFeature(feature?.properties?.id);
if (fe && fe.properties) {
fe.properties.active = true;
}
}
public setFeatureUnActive(feature: Feature) {
const fe = this.getFeature(feature?.properties?.id);
if (fe && fe.properties) {
fe.properties.active = false;
}
}
public clearFeatureActive() {
this.data.features.forEach((fe: Feature) => {
if (fe && fe.properties) {
fe.properties.active = false;
}
});
}
public updateFeature(feature: Feature) {
this.removeFeature(feature);
this.addFeature(feature);
}
public destroy() {
this.data = this.getDefaultData();
}
private getDefaultData(): FeatureCollection {
return {
type: 'FeatureCollection',
features: [],
};
}
private getFeatureIndex(feature: Feature): number | undefined {
return this.data.features.findIndex((fe) => {
return fe?.properties?.id === feature?.properties?.id;
});
}
}

View File

@ -1,39 +0,0 @@
export enum DrawEvent {
CREATE = 'draw.create',
DELETE = 'draw.delete',
Move = 'draw.move',
Edit = 'draw.edit',
UPDATE = 'draw.update',
CHANGE = 'draw.change',
SELECTION_CHANGE = 'draw.selectionchange',
MODE_CHANGE = 'draw.modechange',
ACTIONABLE = 'draw.actionable',
RENDER = 'draw.render',
COMBINE_FEATURES = 'draw.combine',
UNCOMBINE_FEATURES = 'draw.uncombine',
}
export enum DrawModes {
DRAW_Circle = 'draw_circle',
DRAW_Rect = 'draw_react',
DRAW_LINE_STRING = 'draw_line_string',
DRAW_POLYGON = 'draw_polygon',
DRAW_POINT = 'draw_point',
SIMPLE_SELECT = 'simple_select',
DIRECT_SELECT = 'direct_select',
STATIC = 'static',
}
export type unitsType = 'degrees' | 'radians' | 'miles' | 'kilometers';
export enum FeatureType {
FEATURE = 'Feature',
POLYGON = 'Polygon',
LINE_STRING = 'LineString',
POINT = 'Point',
FEATURE_COLLECTION = 'FeatureCollection',
MULTI_PREFIX = 'Multi',
MULTI_POINT = 'MultiPoint',
MULTI_LINE_STRING = 'MultiLineString',
MULTI_POLYGON = 'MultiPolygon',
}

View File

@ -1,130 +0,0 @@
import turfCircle from '@turf/circle';
import turfDistance from '@turf/distance';
import {
Feature,
featureCollection,
FeatureCollection,
lineString,
point,
polygon,
} from '@turf/helpers';
import { unitsType } from './constant';
export function createCircle(
center: [number, number],
endPoint: [number, number],
options: {
units: unitsType;
steps: number;
id: string;
pointFeatures: Feature[];
},
): Feature {
const radius = turfDistance(point(center), point(endPoint), options);
const feature = turfCircle(center, radius, {
units: options.units,
steps: options.steps,
properties: {
...options,
active: true,
type: 'circle',
radius,
startPoint: {
lng: center[0],
lat: center[1],
},
endPoint: {
lng: endPoint[0],
lat: endPoint[1],
},
},
});
return feature as Feature;
}
export function createRect(
startPoint: [number, number],
endPoint: [number, number],
options: {
id: string;
pointFeatures: Feature[];
[key: string]: any;
},
): Feature {
const minX = Math.min(startPoint[0], endPoint[0]);
const minY = Math.min(startPoint[1], endPoint[1]);
const maxX = Math.max(startPoint[0], endPoint[0]);
const maxY = Math.max(startPoint[1], endPoint[1]);
const feature = {
type: 'Feature',
properties: {
type: 'rect',
active: true,
startPoint: {
lng: startPoint[0],
lat: startPoint[1],
},
endPoint: {
lng: endPoint[0],
lat: endPoint[1],
},
...options,
},
geometry: {
type: 'Polygon',
coordinates: [
[
[minX, minY],
[minX, maxY],
[maxX, maxY],
[maxX, minY],
[minX, minY],
],
],
},
};
return feature as Feature;
}
export function createPolygon(
points: Array<{ lng: number; lat: number }>,
options: {
id?: string | number;
pointFeatures: Feature[];
[key: string]: any;
},
): any {
const coords = points.map((p) => [p.lng, p.lat]);
if (points.length < 2) {
return point(coords[0], options);
} else if (points.length < 3) {
return lineString(coords, options);
} else {
coords.push(coords[0]);
return polygon([coords], options);
}
}
export function createLine(
points: Array<{ lng: number; lat: number }>,
options: any,
): any {
const coords = points.map((p) => [p.lng, p.lat]);
if (points.length < 2) {
return point(coords[0], options);
} else {
return lineString(coords, options);
}
}
export function createPoint(
points: Array<{ lng: number; lat: number }>,
): FeatureCollection {
const features = points.map((p, index) =>
point([p.lng, p.lat], {
active: true,
id: index.toString(),
}),
);
return featureCollection(features);
}

View File

@ -1,92 +0,0 @@
const LayerStyles = {
active: {
point: {
type: 'PointLayer',
shape: 'circle',
color: '#fbb03b',
size: 5,
style: {
stroke: '#fff',
strokeWidth: 2,
},
},
line: {
type: 'LineLayer',
shape: 'line',
color: '#fbb03b',
size: 1,
style: {
opacity: 1,
lineType: 'dash',
dashArray: [2, 2],
},
},
polygon: {
shape: 'fill',
color: '#fbb03b',
style: {
opacity: 0.1,
stroke: '#fbb03b',
strokeWidth: 1,
strokeOpacity: 1,
lineType: 'dash',
dashArray: [2, 2],
},
},
},
normal: {
polygon: {
type: 'PolygonLayer',
shape: 'fill',
color: '#3bb2d0',
style: {
opacity: 0.1,
stroke: '#3bb2d0',
strokeWidth: 1,
strokeOpacity: 1,
lineType: 'solid',
dashArray: [2, 2],
},
},
line: {
type: 'LineLayer',
shape: 'line',
size: 1,
color: '#3bb2d0',
style: {
opacity: 1,
},
},
point: {
type: 'PointLayer',
shape: 'circle',
color: '#3bb2d0',
size: 3,
style: {
stroke: '#fff',
strokeWidth: 2,
},
},
},
normal_point: {
type: 'PointLayer',
shape: 'circle',
color: '#3bb2d0',
size: 3,
style: {
stroke: '#fff',
strokeWidth: 2,
},
},
mid_point: {
point: {
type: 'PointLayer',
shape: 'circle',
color: '#fbb03b',
size: 3,
style: {},
},
},
};
export default LayerStyles;

View File

@ -1,52 +0,0 @@
import { Feature, Geometry, Properties } from '@turf/helpers';
import { FeatureType } from './constant';
interface IDelta {
lng: number;
lat: number;
}
type RingType = Array<[number, number]>;
export default function(features: Feature[], delta: IDelta) {
features.forEach((feature) => {
const geometry = feature.geometry as Geometry;
let nextCoord;
const { type, coordinates } = geometry;
switch (type) {
case FeatureType.POINT:
nextCoord = movePoint(coordinates as [number, number], delta);
break;
case FeatureType.LINE_STRING:
case FeatureType.MULTI_POINT:
nextCoord = moveRing(coordinates as RingType, delta);
break;
case FeatureType.POLYGON:
case FeatureType.MULTI_LINE_STRING:
nextCoord = moveMultiPolygon(coordinates as RingType[], delta);
break;
case FeatureType.MULTI_POLYGON:
nextCoord = (coordinates as RingType[][]).map((mult) =>
moveMultiPolygon(mult as RingType[], delta),
);
break;
}
if (nextCoord) {
geometry.coordinates = nextCoord;
}
});
return features;
}
export function movePoint(
coord: [number, number],
delta: IDelta,
): [number, number] {
return [coord[0] + delta.lng, coord[1] + delta.lat];
}
export function moveRing(coords: RingType, delta: IDelta) {
return coords.map((coord) => movePoint(coord, delta));
}
export function moveMultiPolygon(mult: RingType[], delta: IDelta) {
return mult.map((ring) => moveRing(ring, delta));
}

View File

@ -1,9 +0,0 @@
{
"extends": "../../tsconfig.build.json",
"compilerOptions": {
"declarationDir": "./es",
"rootDir": "./src",
"baseUrl": "./"
},
"include": ["./src"]
}

View File

@ -1,75 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.1.12](https://github.com/antvis/L7/compare/v2.1.11...v2.1.12) (2020-04-10)
**Note:** Version bump only for package @antv/l7-react
## [2.1.11](https://github.com/antvis/L7/compare/v2.1.10...v2.1.11) (2020-04-07)
**Note:** Version bump only for package @antv/l7-react
## [2.1.8](https://github.com/antvis/L7/compare/v2.1.7...v2.1.8) (2020-03-26)
**Note:** Version bump only for package @antv/l7-react
## [2.1.7](https://github.com/antvis/L7/compare/v2.1.6...v2.1.7) (2020-03-26)
**Note:** Version bump only for package @antv/l7-react
## [2.1.5](https://github.com/antvis/L7/compare/v2.1.4...v2.1.5) (2020-03-20)
**Note:** Version bump only for package @antv/l7-react
## [2.1.3](https://github.com/antvis/L7/compare/v2.0.36...v2.1.3) (2020-03-17)
**Note:** Version bump only for package @antv/l7-react
## [2.1.2](https://github.com/antvis/L7/compare/v2.0.36...v2.1.2) (2020-03-15)
**Note:** Version bump only for package @antv/l7-react
## [2.1.1](https://github.com/antvis/L7/compare/v2.0.36...v2.1.1) (2020-03-15)
**Note:** Version bump only for package @antv/l7-react
## [2.0.34](https://github.com/antvis/L7/compare/v2.0.32...v2.0.34) (2020-03-02)
### Bug Fixes
* fix map reference ([79e16f5](https://github.com/antvis/L7/commit/79e16f5393c6c31cc088e946dc865cdddfde9b73))

View File

@ -1,10 +0,0 @@
# `react`
> L7
## Usage
```
import { Scene } from '@antv/l7-react';
```

View File

@ -1,41 +0,0 @@
{
"name": "@antv/l7-react",
"version": "2.2.37",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
"types": "es/index.d.ts",
"sideEffects": true,
"files": [
"lib",
"es",
"README.md"
],
"scripts": {
"tsc": "tsc --project tsconfig.build.json",
"clean": "rimraf dist; rimraf es; rimraf lib;",
"build": "run-p build:*",
"build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"lint:ts": "run-p -c lint:ts-*",
"test": "jest",
"sync": "tnpm sync"
},
"author": "lzxue",
"license": "ISC",
"dependencies": {
"@antv/l7": "2.2.37",
"@antv/l7-maps": "2.2.37",
"@babel/runtime": "^7.7.7",
"load-styles": "^2.0.0"
},
"peerDependencies": {
"react": "^16.8.6",
"react-dom": "^16.10.2"
},
"gitHead": "20154fe30d512024b03ac5e40f77731bc0580bb0",
"publishConfig": {
"access": "public"
}
}

View File

@ -1,78 +0,0 @@
import { IMapConfig, ISceneConfig, Scene } from '@antv/l7';
// @ts-ignore
// tslint:disable-next-line:no-submodule-imports
import { GaodeMap } from '@antv/l7-maps';
import React, { createElement, createRef, useEffect, useState } from 'react';
import { SceneContext } from './SceneContext';
interface IMapSceneConig {
style?: React.CSSProperties;
className?: string;
map: Partial<IMapConfig>;
option?: Partial<ISceneConfig>;
children?: React.ReactNode;
onSceneLoaded?: (scene: Scene) => void;
}
const AMapScene = React.memo((props: IMapSceneConig) => {
const { style, className, map, option, onSceneLoaded } = props;
const container = createRef();
const [scene, setScene] = useState<Scene>();
useEffect(() => {
const sceneInstance = new Scene({
id: container.current as HTMLDivElement,
...option,
map: new GaodeMap(map),
});
sceneInstance.on('loaded', () => {
setScene(sceneInstance);
if (onSceneLoaded) {
onSceneLoaded(sceneInstance);
}
});
return () => {
sceneInstance.destroy();
};
}, []);
// 更新地图样式
useEffect(() => {
if (scene && map.style) {
scene.setMapStyle(map.style);
}
}, [JSON.stringify(map.style)]);
useEffect(() => {
if (scene && map.zoom) {
scene.setZoom(map.zoom);
}
}, [map.zoom]);
useEffect(() => {
if (scene && map.center) {
scene.setCenter(map.center);
}
}, [JSON.stringify(map.center)]);
useEffect(() => {
if (scene && map.pitch) {
scene.setPitch(map.pitch);
}
}, [map.pitch]);
useEffect(() => {
if (scene && map.rotation) {
scene.setRotation(map.rotation);
}
}, [map.rotation]);
return (
<SceneContext.Provider value={scene}>
{createElement(
'div',
{
ref: container,
style,
className,
},
scene && props.children,
)}
</SceneContext.Provider>
);
});
export default AMapScene;

View File

@ -1,39 +0,0 @@
import { IControl, Logo, PositionName, Scale, Scene, Zoom } from '@antv/l7';
import React, { useEffect, useState } from 'react';
import { useSceneValue } from './SceneContext';
interface IControlProps {
type: 'scale' | 'zoom' | 'logo';
position: PositionName;
[key: string]: any;
}
export default React.memo(function MapControl(props: IControlProps) {
const scene = (useSceneValue() as unknown) as Scene;
const [, setControl] = useState();
const { type, position } = props;
useEffect(() => {
let ctr: IControl;
switch (type) {
case 'scale':
ctr = new Scale({
position: position || 'bottomright',
});
break;
case 'zoom':
ctr = new Zoom({
position: position || 'topright',
});
break;
case 'logo':
ctr = new Logo({
position: position || 'bottomleft',
});
}
setControl(ctr);
scene.addControl(ctr);
return () => {
scene.removeControl(ctr);
};
}, [type, position]);
return null;
});

View File

@ -1,44 +0,0 @@
import { Control, PositionName, Scene } from '@antv/l7';
import * as React from 'react';
import { createPortal } from 'react-dom';
import { useSceneValue } from './SceneContext';
const { useEffect, useState } = React;
interface IColorLegendProps {
position: PositionName;
className?: string;
style?: React.CSSProperties;
children?: JSX.Element | JSX.Element[] | Array<JSX.Element | undefined>;
}
export default function CustoonConrol(props: IColorLegendProps) {
const { className, style, children, position } = props;
const mapScene = (useSceneValue() as unknown) as Scene;
const el = document.createElement('div');
useEffect(() => {
const custom = new Control({
position,
});
custom.onAdd = () => {
if (className) {
el.className = className;
}
if (style) {
const cssText = Object.keys(style)
.map((key: string) => {
// @ts-ignore
return `${key}:${style[key]}`;
})
.join(';');
el.style.cssText = cssText;
}
return el;
};
mapScene.addControl(custom);
return () => {
mapScene.removeControl(custom);
};
}, []);
return createPortal(children, el);
}

View File

@ -1,53 +0,0 @@
import * as React from 'react';
import { ILayerProps } from './LayerAttribute';
import BaseLayer from './LayerAttribute/Layer';
const PolygonLayer = React.memo(function Layer(
props: ILayerProps & { children?: any },
) {
return BaseLayer('polygonLayer', props);
});
const LineLayer = React.memo(function Layer(props: ILayerProps) {
return BaseLayer('lineLayer', props);
});
const PointLayer = React.memo(function Layer(
props: ILayerProps & { children?: any },
) {
return BaseLayer('pointLayer', props);
});
const HeatmapLayer = React.memo(function Layer(
props: ILayerProps & { children?: any },
) {
return BaseLayer('heatmapLayer', props);
});
const RasterLayer = React.memo(function Layer(
props: ILayerProps & { children?: any },
) {
return BaseLayer('rasterLayer', props);
});
const ImageLayer = React.memo(function Layer(
props: ILayerProps & { children?: any },
) {
return BaseLayer('imagelayer', props);
});
const CityBuildingLayer = React.memo(function Layer(
props: ILayerProps & { children?: any },
) {
return BaseLayer('citybuildinglayer', props);
});
export {
PolygonLayer,
LineLayer,
PointLayer,
HeatmapLayer,
RasterLayer,
ImageLayer,
CityBuildingLayer,
};

View File

@ -1,17 +0,0 @@
import { IActiveOption, ILayer } from '@antv/l7';
import * as React from 'react';
const { useEffect } = React;
interface ILayerProps {
layer: ILayer;
active: {
option: IActiveOption | boolean;
};
}
export default React.memo(function Chart(props: ILayerProps) {
const { layer, active } = props;
useEffect(() => {
layer.active(active.option);
}, [JSON.stringify(active)]);
return null;
});

View File

@ -1,16 +0,0 @@
import { IAnimateOption, ILayer } from '@antv/l7';
import * as React from 'react';
import { IStyleOptions } from './';
const { useEffect } = React;
interface ILayerProps {
layer: ILayer;
animate: Partial<IAnimateOption>;
}
export default React.memo(function Chart(props: ILayerProps) {
const { layer, animate } = props;
useEffect(() => {
layer.animate(animate);
}, [JSON.stringify(animate)]);
return null;
});

View File

@ -1,19 +0,0 @@
import { ILayer, StyleAttrField } from '@antv/l7';
import * as React from 'react';
import { IAttributeOptions } from './';
const { useEffect } = React;
interface ILayerProps {
layer: ILayer;
color: Partial<IAttributeOptions>;
}
export default React.memo(function Chart(props: ILayerProps) {
const { layer, color } = props;
useEffect(() => {
color.field
? layer.color(color.field as StyleAttrField, color.values)
: layer.color(color.values as StyleAttrField);
}, [color.field, color.scale, JSON.stringify(color.values), JSON.stringify(color.options)]);
return null;
});

View File

@ -1,18 +0,0 @@
import { ILayer, StyleAttrField } from '@antv/l7';
import * as React from 'react';
import { IAttributeOptions } from './';
const { useEffect } = React;
interface ILayerProps {
layer: ILayer;
filter: Partial<IAttributeOptions>;
}
export default React.memo(function Chart(props: ILayerProps) {
const { layer, filter } = props;
useEffect(() => {
if (filter.field) {
layer.filter(filter.field as string, filter.values as StyleAttrField);
}
}, [filter.field, filter.values, JSON.stringify(filter.values), JSON.stringify(filter.options)]);
return null;
});

View File

@ -1,132 +0,0 @@
import {
CityBuildingLayer,
HeatmapLayer,
ILayer,
ImageLayer,
LineLayer,
PointLayer,
PolygonLayer,
RasterLayer,
Scene,
} from '@antv/l7';
import * as React from 'react';
import { LayerContext } from '../LayerContext';
import { useSceneValue } from '../SceneContext';
import {
Active,
Animate,
Color,
Filter,
ILayerProps,
Scale,
Select,
Shape,
Size,
Source,
Style,
} from './';
const { useEffect, useState } = React;
export default function BaseLayer(type: string, props: ILayerProps) {
const {
source,
color,
shape,
style,
size,
scale,
active,
select,
filter,
animate,
options,
onLayerLoaded,
} = props;
const mapScene = (useSceneValue() as unknown) as Scene;
const [layer, setLayer] = useState<ILayer>();
if (!layer) {
let l: ILayer;
switch (type) {
case 'polygonLayer':
l = new PolygonLayer(options);
break;
case 'lineLayer':
l = new LineLayer(options);
break;
case 'pointLayer':
l = new PointLayer(options);
break;
case 'heatmapLayer':
l = new HeatmapLayer(options);
break;
case 'rasterLayer':
l = new RasterLayer(options);
break;
case 'imageLayer':
l = new ImageLayer(options);
break;
case 'citybuildingLayer':
l = new CityBuildingLayer(options);
break;
default:
l = new PolygonLayer(options);
}
l.on('inited', () => {
if (onLayerLoaded) {
onLayerLoaded(l, mapScene);
}
});
setLayer(l);
}
useEffect(() => {
if (layer !== undefined) {
mapScene.addLayer(layer as ILayer);
return () => {
mapScene.removeLayer(layer as ILayer);
};
}
}, []);
useEffect(() => {
// 重绘layer
if (layer) {
mapScene.render();
}
});
useEffect(() => {
if (layer && layer.inited && options) {
layer.updateLayerConfig(options);
}
}, [options?.minZoom, options?.maxZoom, options?.visible]);
useEffect(() => {
if (layer && layer.inited && options && options.zIndex) {
layer.setIndex(options.zIndex);
}
}, [options?.zIndex]);
useEffect(() => {
if (layer && layer.inited && options && options.blend) {
layer.setBlend(options.blend);
}
}, [options?.blend]);
return layer !== null && layer !== undefined ? (
<LayerContext.Provider value={layer}>
<Source layer={layer} source={source} />
{scale && <Scale layer={layer} scale={scale} />}
{color && <Color layer={layer} color={color} />}
{size && <Size layer={layer} size={size} />}
{shape && <Shape layer={layer} shape={shape} />}
{style && <Style layer={layer} style={style} />}
{active && <Active layer={layer} active={active} />}
{select && <Select layer={layer} select={select} />}
{filter && <Filter layer={layer} filter={filter} />}
{animate && <Animate layer={layer} animate={animate} />}
{/* LayerContext主要传入LayerEvent组件 */}
{props.children}
</LayerContext.Provider>
) : null;
}

View File

@ -1,16 +0,0 @@
import { ILayer, IScale, IScaleOptions } from '@antv/l7';
import * as React from 'react';
import { IScaleAttributeOptions } from './';
const { useEffect } = React;
interface ILayerProps {
layer: ILayer;
scale: Partial<IScaleAttributeOptions>;
}
export default React.memo(function Chart(props: ILayerProps) {
const { layer, scale } = props;
useEffect(() => {
layer.scale(scale.values as IScaleOptions);
}, [scale.values]);
return null;
});

View File

@ -1,17 +0,0 @@
import { IActiveOption, ILayer } from '@antv/l7';
import * as React from 'react';
const { useEffect } = React;
interface ILayerProps {
layer: ILayer;
select: {
option: IActiveOption | boolean;
};
}
export default React.memo(function Chart(props: ILayerProps) {
const { layer, select } = props;
useEffect(() => {
layer.select(select.option);
}, [JSON.stringify(select)]);
return null;
});

View File

@ -1,18 +0,0 @@
import { ILayer, StyleAttrField } from '@antv/l7';
import * as React from 'react';
import { IAttributeOptions } from './';
const { useEffect } = React;
interface ILayerProps {
layer: ILayer;
shape: Partial<IAttributeOptions>;
}
export default React.memo(function Chart(props: ILayerProps) {
const { layer, shape } = props;
useEffect(() => {
shape.field
? layer.shape(shape.field, shape.values)
: layer.shape(shape.values as StyleAttrField);
}, [shape.field, JSON.stringify(shape.values), JSON.stringify(shape.options)]);
return null;
});

View File

@ -1,18 +0,0 @@
import { ILayer, StyleAttrField } from '@antv/l7';
import * as React from 'react';
import { IAttributeOptions } from './';
const { useEffect } = React;
interface ILayerProps {
layer: ILayer;
size: Partial<IAttributeOptions>;
}
export default React.memo(function Chart(props: ILayerProps) {
const { layer, size } = props;
useEffect(() => {
size.field
? layer.size(size.field, size.values)
: layer.size(size.values as StyleAttrField);
}, [size.field, size.scale, JSON.stringify(size.values), JSON.stringify(size.options)]);
return null;
});

View File

@ -1,25 +0,0 @@
import { ILayer } from '@antv/l7';
import * as React from 'react';
import { ISourceOptions } from './';
const { useEffect } = React;
interface ISourceProps {
layer: ILayer;
source: Partial<ISourceOptions>;
}
export default React.memo(function Chart(props: ISourceProps) {
const { layer, source } = props;
const { data, ...sourceOption } = source;
useEffect(() => {
if (!layer.inited) {
layer.source(data, sourceOption);
} else {
layer.setData(data, sourceOption);
}
if (sourceOption.autoFit) {
layer.fitBounds(sourceOption && sourceOption.fitBoundsOptions);
}
}, [data, JSON.stringify(sourceOption)]);
return null;
});

View File

@ -1,19 +0,0 @@
import { ILayer } from '@antv/l7';
import * as React from 'react';
import { IStyleOptions } from './';
const { useEffect } = React;
interface ILayerProps {
layer: ILayer;
style: Partial<IStyleOptions>;
}
export default React.memo(function Chart(props: ILayerProps) {
const { layer, style } = props;
useEffect(
() => {
layer.style(style);
},
Object.keys(style).map((key) => style[key]),
);
return null;
});

View File

@ -1,97 +0,0 @@
import {
BlendType,
IActiveOption,
IAnimateOption,
ILayer,
IScale,
IScaleOptions,
ISourceCFG,
Scene,
} from '@antv/l7';
import * as React from 'react';
import Active from './Active';
import Animate from './Animate';
import Color from './Color';
import Filter from './Filter';
import Scale from './Scale';
import Select from './Select';
import Shape from './Shape';
import Size from './Size';
import Source from './Source';
import Style from './Style';
type CallBack = (...args: any[]) => any;
export interface IAttributeOptions {
field: string;
value: string | number;
values: string[] | number[] | string | number | CallBack;
scale?: string;
blend: keyof typeof BlendType;
options?: {
[key: string]: any;
};
}
export interface IScaleAttributeOptions {
field: string | IScaleOptions;
value: IScale;
values: IScaleOptions | IScale;
}
export interface ILayerOption {
name?: string;
visible: boolean;
zIndex: number;
minZoom: number;
maxZoom: number;
autoFit: boolean;
blend: keyof typeof BlendType;
[key: string]: any;
}
export interface IScaleOption {
[key: string]: IScaleAttributeOptions;
}
export interface IStyleOptions {
opacity: number;
[key: string]: any;
}
export interface ISourceOptions extends ISourceCFG {
data: any;
// 每次更新数据之后是否自适应缩放
autoFit?: boolean;
// Mapbox 自适应的参数
fitBoundsOptions?: any;
}
export interface IActiveOptions {
option: IActiveOption | boolean;
}
export interface ILayerProps {
options?: Partial<ILayerOption>;
source: ISourceOptions;
color: Partial<IAttributeOptions>;
shape: Partial<IAttributeOptions>;
scale?: Partial<IScaleAttributeOptions>;
size?: Partial<IAttributeOptions>;
style?: Partial<IStyleOptions>;
active?: IActiveOptions;
select?: IActiveOptions;
filter?: Partial<IAttributeOptions>;
animate?: Partial<IAnimateOption>;
onLayerLoaded?: (layer: ILayer, scene: Scene) => void;
children?: React.ReactNode;
}
export {
Active,
Color,
Filter,
Source,
Size,
Shape,
Style,
Scale,
Select,
Animate,
};

View File

@ -1,8 +0,0 @@
import { ILayer } from '@antv/l7';
import { createContext, useContext } from 'react';
// tslint:disable-next-line: no-object-literal-type-assertion
export const LayerContext = createContext<ILayer | undefined>({} as ILayer);
export function useLayerValue(): ILayer {
return (useContext(LayerContext) as unknown) as ILayer;
}

View File

@ -1,22 +0,0 @@
import { ILayer } from '@antv/l7';
import * as React from 'react';
import { useLayerValue } from './LayerContext';
const { useEffect } = React;
interface ILayerProps {
type: string;
handler: (...args: any[]) => void;
}
export const LayerEvent = React.memo((props: ILayerProps) => {
const { type, handler } = props;
const layer = (useLayerValue() as unknown) as ILayer;
useEffect(() => {
layer.off(type, handler);
layer.on(type, handler);
return () => {
layer.off(type, handler);
};
}, [type, handler]);
return null;
});

View File

@ -1,62 +0,0 @@
import * as React from 'react';
interface IColorLegendProps {
items?: any[];
title: string;
className?: string;
style?: React.CSSProperties;
}
import './style.css';
export const ColorComponent = React.memo((props: IColorLegendProps) => {
const { className, style, title } = props;
const items = [
{ title: '1', color: 'rgb(239,243,255)' },
{ title: '10', color: 'rgb(198,219,239)' },
{ title: '30', color: 'rgb(158,202,225)' },
{ title: '50', color: 'rgb(107,174,214)' },
{ title: '60', color: 'rgb(49,130,189)' },
{ title: '100', color: 'rgb(8,81,156)' },
];
return (
<div>
<div>
{items.map((c, i) => {
return (
<div
key={i.toString()}
style={{
background: c.color,
height: '100%',
display: 'inline-block',
cursor: 'pointer',
width: '' + (100.0 - items.length) / items.length + '%',
marginRight: '1%',
padding: 5,
}}
/>
);
})}
</div>
<div>
{items.map((c, i) => {
return (
<div
key={i.toString() + '122'}
style={{
background: '#fff',
height: '100%',
display: 'inline-block',
textAlign: 'left',
cursor: 'pointer',
width: '' + (100.0 - items.length) / items.length + '%',
marginRight: '1%',
}}
>
{c.title}
</div>
);
})}
</div>
</div>
);
});

View File

@ -1,3 +0,0 @@
.color {
color:'red';
}

View File

@ -1,17 +0,0 @@
import { IActiveOption, IImage, ILayer, Scene } from '@antv/l7';
import * as React from 'react';
import { useSceneValue } from './SceneContext';
const { useEffect } = React;
interface ILoadImageProps {
name: string;
url: IImage;
}
export default React.memo(function LoadImage(props: ILoadImageProps) {
const { name, url } = props;
const mapScene = (useSceneValue() as unknown) as Scene;
useEffect(() => {
mapScene.addImage(name, url);
}, [name, url]);
return null;
});

View File

@ -1,82 +0,0 @@
import { IMapConfig, ISceneConfig, Scene, Zoom } from '@antv/l7';
// @ts-ignore
// tslint:disable-next-line:no-submodule-imports
import { Mapbox } from '@antv/l7-maps';
import React, { createElement, createRef, useEffect, useState } from 'react';
import { SceneContext } from './SceneContext';
interface IMapSceneConig {
style?: React.CSSProperties;
className?: string;
map: Partial<IMapConfig>;
option?: Partial<ISceneConfig>;
children?: React.ReactNode;
onSceneLoaded?: (scene: Scene) => void;
}
const MapboxScene = React.memo((props: IMapSceneConig) => {
const { style, className, map, option, onSceneLoaded } = props;
const container = createRef();
const [scene, setScene] = useState<Scene>();
// 地图初始
useEffect(() => {
const sceneInstance = new Scene({
id: container.current as HTMLDivElement,
...option,
map: new Mapbox(map),
});
sceneInstance.on('loaded', () => {
setScene(sceneInstance);
if (onSceneLoaded) {
onSceneLoaded(sceneInstance);
}
});
return () => {
sceneInstance.destroy();
};
}, []);
// 更新地图样式
useEffect(() => {
if (scene && map.style) {
scene.setMapStyle(map.style);
}
}, [JSON.stringify(map.style)]);
useEffect(() => {
if (scene && map.zoom) {
scene.setZoom(map.zoom);
}
}, [map.zoom]);
useEffect(() => {
if (scene && map.center) {
scene.setCenter(map.center);
}
}, [JSON.stringify(map.center)]);
useEffect(() => {
if (scene && map.pitch) {
scene.setPitch(map.pitch);
}
}, [map.pitch]);
useEffect(() => {
if (scene && map.rotation) {
scene.setRotation(map.rotation);
}
}, [map.rotation]);
return (
<SceneContext.Provider value={scene}>
{createElement(
'div',
{
ref: container,
style,
className,
},
scene && props.children,
)}
</SceneContext.Provider>
);
});
export default MapboxScene;

View File

@ -1,73 +0,0 @@
import {
IActiveOption,
IImage,
ILayer,
ILngLat,
IMarker,
IMarkerOption,
IPoint,
Marker,
Popup,
Scene,
} from '@antv/l7';
import * as React from 'react';
import { createPortal } from 'react-dom';
import { SceneContext } from './SceneContext';
interface IMarkerProps {
option?: IMarkerOption;
lnglat: ILngLat | number[];
onMarkerLoaded?: (marker: IMarker) => void;
children?: React.ReactNode;
}
export default class MarkerComponet extends React.PureComponent<IMarkerProps> {
private el: HTMLDivElement;
private scene: Scene;
private marker: IMarker;
constructor(props: IMarkerProps) {
super(props);
this.el = document.createElement('div');
}
public componentDidMount() {
const { lnglat, children, option, onMarkerLoaded } = this.props;
const marker = new Marker(option);
if (lnglat) {
marker.setLnglat(lnglat as ILngLat | IPoint);
}
if (children) {
marker.setElement(this.el);
}
this.marker = marker;
if (onMarkerLoaded) {
onMarkerLoaded(marker);
}
this.scene.addMarker(marker);
}
public componentDidUpdate(prevProps: IMarkerProps) {
const positionChanged =
prevProps?.lnglat.toString() !== this.props?.lnglat.toString();
if (positionChanged) {
this.marker.setLnglat(this.props.lnglat as ILngLat | IPoint);
}
}
public componentWillUnmount() {
if (this.marker) {
this.marker.remove();
}
}
public render() {
return React.createElement(
SceneContext.Consumer,
// @ts-ignore
{},
(scene: Scene) => {
if (scene) {
this.scene = scene;
}
return createPortal(this.props.children, this.el);
},
);
}
}

View File

@ -1,83 +0,0 @@
import {
IActiveOption,
IImage,
ILayer,
ILngLat,
IPopupOption,
Popup,
Scene,
} from '@antv/l7';
import * as React from 'react';
import { createPortal } from 'react-dom';
import { SceneContext } from './SceneContext';
interface IPopupProps {
option?: Partial<IPopupOption>;
lnglat: number[] | { lng: number; lat: number };
children?: React.ReactNode;
}
export default class PopupComponet extends React.PureComponent<IPopupProps> {
private el: HTMLDivElement;
private scene: Scene;
private popup: Popup;
constructor(props: IPopupProps) {
super(props);
this.el = document.createElement('div');
}
public componentDidMount() {
const { lnglat, children, option } = this.props;
const p = new Popup({
...option,
stopPropagation: false,
});
if (lnglat) {
p.setLnglat(lnglat);
}
if (children) {
p.setDOMContent(this.el);
}
this.popup = p;
this.scene.addPopup(p);
}
public componentDidUpdate(prevProps: IPopupProps) {
// @ts-ignore
const preLnglat = Array.isArray(prevProps.lnglat)
? prevProps.lnglat
: [prevProps?.lnglat?.lng, prevProps?.lnglat?.lat];
const nowLnglat = Array.isArray(this.props.lnglat)
? this.props.lnglat
: [this.props?.lnglat?.lng, this.props?.lnglat?.lat];
const positionChanged = preLnglat.toString() !== nowLnglat.toString();
if (positionChanged) {
this.popup.remove();
this.popup = new Popup({
...this.props.option,
stopPropagation: false,
});
this.popup.setLnglat(this.props.lnglat);
this.popup.setDOMContent(this.el);
this.scene.addPopup(this.popup);
}
}
public componentWillUnmount() {
this.popup.remove();
}
public render() {
return React.createElement(
SceneContext.Consumer,
// @ts-ignore
{},
(scene: Scene) => {
if (scene) {
this.scene = scene;
}
return createPortal(this.props.children, this.el);
},
);
}
}

View File

@ -1,40 +0,0 @@
import { IMapWrapper, Scene } from '@antv/l7';
import React, { createElement, createRef, useEffect, useState } from 'react';
import { SceneContext } from './SceneContext';
interface IMapSceneConig {
style?: Partial<React.CSSProperties>;
className?: string;
map: IMapWrapper;
children?: React.ReactNode;
}
export default React.memo((props: IMapSceneConig) => {
const { style, className, map } = props;
const container = createRef();
const [scene, setScene] = useState<Scene>();
useEffect(() => {
const sceneInstance = new Scene({
id: container.current as HTMLDivElement,
map,
});
sceneInstance.on('loaded', () => {
setScene(sceneInstance);
});
return () => {
sceneInstance.destroy();
};
}, []);
return (
<SceneContext.Provider value={scene}>
{createElement(
'div',
{
ref: container,
style,
className,
},
scene && props.children,
)}
</SceneContext.Provider>
);
});

View File

@ -1,8 +0,0 @@
import { Scene } from '@antv/l7';
import { createContext, useContext } from 'react';
// tslint:disable-next-line: no-object-literal-type-assertion
export const SceneContext = createContext<Scene | undefined>({} as Scene);
export function useSceneValue(): Scene {
return (useContext(SceneContext) as unknown) as Scene;
}

View File

@ -1,23 +0,0 @@
import { ILayer, Scene } from '@antv/l7';
import * as React from 'react';
import { useSceneValue } from './SceneContext';
const { useEffect } = React;
interface ILayerProps {
type: string;
handler: (...args: any[]) => void;
}
const SceneEvent = React.memo((props: ILayerProps) => {
const { type, handler } = props;
const mapScene = (useSceneValue() as unknown) as Scene;
useEffect(() => {
mapScene.on(type, handler);
return () => {
mapScene.off(type, handler);
};
}, [type]);
return null;
});
export default SceneEvent;

View File

@ -1,15 +0,0 @@
export * from './component/SceneContext';
export { default as AMapScene } from './component/AMapScene';
export { default as MapboxScene } from './component/MapboxScene';
export { default as Scene } from './component/Scene';
export { default as Control } from './component/Control';
export { default as CustomControl } from './component/CustomControl';
export * from './component/Layer';
export { LayerEvent } from './component/LayerEvent';
export { useSceneValue, SceneContext } from './component/SceneContext';
export { useLayerValue, LayerContext } from './component/LayerContext';
export { ColorComponent } from './component/Legend/color';
export { default as Popup } from './component/Popup';
export { default as Marker } from './component/Marker';
export { default as SceneEvent } from './component/SceneEvent';
export { default as LoadImage } from './component/LoadImage';

View File

@ -1,9 +0,0 @@
{
"extends": "../../tsconfig.build.json",
"compilerOptions": {
"declarationDir": "./es",
"rootDir": "./src",
"baseUrl": "./",
},
"include": ["./src"]
}

13056
yarn.lock

File diff suppressed because it is too large Load Diff