mirror of https://gitee.com/antv-l7/antv-l7
feat: 新增矩形绘制方法
This commit is contained in:
parent
0452a6191e
commit
7733c7685e
|
@ -0,0 +1,79 @@
|
|||
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);
|
||||
expect(res[0].geometry.coordinates).toEqual([131, 48]);
|
||||
});
|
||||
it('move BBox', () => {
|
||||
const res = moveFeature([polyon], delta);
|
||||
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);
|
||||
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],
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -33,7 +33,7 @@
|
|||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/l7": "^2.1.3",
|
||||
"@antv/l7": "^2.1.5",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@turf/circle": "^6.0.1",
|
||||
"@turf/distance": "^6.0.1",
|
||||
|
|
|
@ -9,46 +9,90 @@ import {
|
|||
Popup,
|
||||
Scene,
|
||||
} from '@antv/l7';
|
||||
import turfCircle from '@turf/circle';
|
||||
import turfDistance from '@turf/distance';
|
||||
import { Feature, featureCollection, point } from '@turf/helpers';
|
||||
import RenderLayer from '../render/render';
|
||||
import DrawFeature, { IDrawOption } from './draw_feature';
|
||||
import DrawSelected from './draw_selected';
|
||||
let CircleFeatureId = 0;
|
||||
export type unitsType = 'degrees' | 'radians' | 'miles' | 'kilometers';
|
||||
export interface IDrawCircleOption extends IDrawOption {
|
||||
import { Feature, FeatureCollection, point } from '@turf/helpers';
|
||||
import selectRender from '../render/selected';
|
||||
import { DrawEvent, DrawModes, unitsType } from '../util/constant';
|
||||
import { createCircle } from '../util/create_geometry';
|
||||
import moveFeatures, { movePoint, moveRing } from '../util/move_featrues';
|
||||
import DrawFeature, { IDrawFeatureOption } from './draw_feature';
|
||||
export interface IDrawRectOption extends IDrawFeatureOption {
|
||||
units: unitsType;
|
||||
steps: number;
|
||||
}
|
||||
const InitFeature = {
|
||||
type: 'FeatureCollection',
|
||||
features: [],
|
||||
};
|
||||
let CircleFeatureId = 0;
|
||||
export default class DrawCircle extends DrawFeature {
|
||||
private center: ILngLat;
|
||||
private startPoint: ILngLat;
|
||||
private endPoint: ILngLat;
|
||||
private dragStartPoint: ILngLat;
|
||||
// 绘制完成之后显示
|
||||
private normalLayer: RenderLayer;
|
||||
private selectMode: DrawSelected;
|
||||
// 编辑过程中显示
|
||||
private centerLayer: ILayer;
|
||||
private circleLayer: ILayer;
|
||||
private circleLineLayer: ILayer;
|
||||
private currentFeature: Feature | null;
|
||||
private popup: IPopup;
|
||||
constructor(scene: Scene, options: Partial<IDrawCircleOption> = {}) {
|
||||
constructor(scene: Scene, options: Partial<IDrawRectOption> = {}) {
|
||||
super(scene, options);
|
||||
this.normalLayer = new RenderLayer(this);
|
||||
this.selectLayer = new selectRender(this);
|
||||
}
|
||||
protected onDragStart = (e: IInteractionTarget) => {
|
||||
// @ts-ignore
|
||||
this.dragStartPoint = e.lngLat;
|
||||
this.center = e.lngLat;
|
||||
this.startPoint = e.lngLat;
|
||||
this.setCursor('grabbing');
|
||||
this.initCenterLayer();
|
||||
this.initDrawFillLayer();
|
||||
this.centerLayer.setData([this.startPoint]);
|
||||
};
|
||||
protected onDragging = (e: IInteractionTarget) => {
|
||||
this.endPoint = e.lngLat;
|
||||
const feature = this.createFeature();
|
||||
this.updateDrawFillLayer(feature);
|
||||
};
|
||||
|
||||
protected onDragEnd = () => {
|
||||
this.emit(DrawEvent.CREATE, this.currentFeature);
|
||||
this.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_SELECT);
|
||||
this.disable();
|
||||
};
|
||||
|
||||
protected moveFeature(delta: ILngLat): Feature {
|
||||
const newFeature = moveFeatures([this.currentFeature as Feature], delta)[0];
|
||||
const properties = newFeature.properties as {
|
||||
startPoint: [number, number];
|
||||
endPoint: [number, number];
|
||||
};
|
||||
const { startPoint, endPoint } = properties;
|
||||
properties.startPoint = movePoint(startPoint, delta);
|
||||
properties.endPoint = movePoint(endPoint, delta);
|
||||
newFeature.properties = properties;
|
||||
this.startPoint = {
|
||||
lat: startPoint[1],
|
||||
lng: startPoint[0],
|
||||
};
|
||||
this.endPoint = {
|
||||
lat: endPoint[1],
|
||||
lng: endPoint[0],
|
||||
};
|
||||
return newFeature;
|
||||
}
|
||||
|
||||
protected createFeature(): FeatureCollection {
|
||||
const feature = createCircle(
|
||||
[this.startPoint.lng, this.startPoint.lat],
|
||||
[this.endPoint.lng, this.endPoint.lat],
|
||||
{
|
||||
units: this.getOption('units'),
|
||||
steps: this.getOption('steps'),
|
||||
id: `${CircleFeatureId++}`,
|
||||
},
|
||||
);
|
||||
this.setCurrentFeature(feature as Feature);
|
||||
return {
|
||||
type: 'FeatureCollection',
|
||||
features: [feature],
|
||||
};
|
||||
}
|
||||
|
||||
protected editFeature(endPoint: ILngLat): FeatureCollection {
|
||||
this.endPoint = endPoint;
|
||||
return this.createFeature();
|
||||
}
|
||||
|
||||
private initCenterLayer() {
|
||||
const centerStyle = this.getStyle('active_point');
|
||||
const layer = new PointLayer()
|
||||
.source([this.center], {
|
||||
.source([this.startPoint], {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
|
@ -61,110 +105,5 @@ export default class DrawCircle extends DrawFeature {
|
|||
.style(centerStyle.style);
|
||||
this.scene.addLayer(layer);
|
||||
this.centerLayer = layer;
|
||||
this.initDrawLayer();
|
||||
this.setCursor('grabbing');
|
||||
};
|
||||
protected getDefaultOptions() {
|
||||
return {
|
||||
steps: 64,
|
||||
units: 'kilometres',
|
||||
cursor: 'crosshair',
|
||||
};
|
||||
}
|
||||
|
||||
protected onDragging = (e: IInteractionTarget) => {
|
||||
this.endPoint = e.lngLat;
|
||||
const currentData = this.createCircleData(this.center, this.endPoint);
|
||||
this.updateDrawLayer(currentData);
|
||||
this.addDrawPopup(this.endPoint, this.currentFeature?.properties?.radius);
|
||||
return;
|
||||
};
|
||||
|
||||
protected onDragEnd = () => {
|
||||
this.source.addFeature(this.currentFeature);
|
||||
// @ts-ignore
|
||||
this.scene.map.dragPan.enable();
|
||||
this.popup.remove();
|
||||
// 绘制完成进入选中状态
|
||||
this.selectMode = new DrawSelected(this.scene, {});
|
||||
this.selectMode.setSelectedFeature(this.currentFeature as Feature);
|
||||
this.removeDrawLayer();
|
||||
this.drawStatus = 'DrawSelected';
|
||||
this.disable();
|
||||
return;
|
||||
};
|
||||
protected onClick = () => {
|
||||
return null;
|
||||
};
|
||||
protected onCircleLayerClick = () => {
|
||||
if (this.currentFeature === null) {
|
||||
return;
|
||||
}
|
||||
this.currentFeature = null;
|
||||
this.normalLayer.updateData();
|
||||
this.centerLayer.setData([]);
|
||||
this.circleLayer.setData(InitFeature);
|
||||
this.circleLineLayer.setData(InitFeature);
|
||||
return;
|
||||
};
|
||||
|
||||
private createCircleData(center: ILngLat, endPoint: ILngLat) {
|
||||
const radius = turfDistance(
|
||||
point([center.lng, center.lat]),
|
||||
point([endPoint.lng, endPoint.lat]),
|
||||
this.getOption('units'),
|
||||
);
|
||||
const feature = turfCircle([center.lng, center.lat], radius, {
|
||||
units: this.getOption('units'),
|
||||
steps: this.getOption('steps'),
|
||||
properties: {
|
||||
id: `${CircleFeatureId++}`,
|
||||
radius,
|
||||
center,
|
||||
endPoint,
|
||||
},
|
||||
});
|
||||
this.currentFeature = feature as Feature;
|
||||
return featureCollection([feature]);
|
||||
}
|
||||
|
||||
private initDrawLayer() {
|
||||
const style = this.getStyle('active_fill');
|
||||
const linestyle = this.getStyle('active_line');
|
||||
this.circleLayer = new PolygonLayer()
|
||||
.source(InitFeature)
|
||||
.color(style.color)
|
||||
.shape('fill')
|
||||
.style(style.style);
|
||||
this.circleLineLayer = new PolygonLayer()
|
||||
.source(InitFeature)
|
||||
.color(linestyle.color)
|
||||
.size(linestyle.size)
|
||||
.shape('line')
|
||||
.style(linestyle.style);
|
||||
this.scene.addLayer(this.circleLayer);
|
||||
this.scene.addLayer(this.circleLineLayer);
|
||||
}
|
||||
|
||||
private updateDrawLayer(currentData: any) {
|
||||
this.circleLayer.setData(currentData);
|
||||
this.circleLineLayer.setData(currentData);
|
||||
}
|
||||
|
||||
private removeDrawLayer() {
|
||||
this.scene.removeLayer(this.circleLayer);
|
||||
this.scene.removeLayer(this.circleLineLayer);
|
||||
this.scene.removeLayer(this.centerLayer);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,10 @@
|
|||
import {
|
||||
IInteractionTarget,
|
||||
ILayer,
|
||||
ILngLat,
|
||||
IPopup,
|
||||
LineLayer,
|
||||
PointLayer,
|
||||
PolygonLayer,
|
||||
Popup,
|
||||
Scene,
|
||||
} from '@antv/l7';
|
||||
import { IInteractionTarget, ILayer, ILngLat, Popup, Scene } from '@antv/l7';
|
||||
import turfCircle from '@turf/circle';
|
||||
import turfDistance from '@turf/distance';
|
||||
import { Feature, featureCollection, point } from '@turf/helpers';
|
||||
import EditRender from '../render/edit';
|
||||
import DrawFeature, { IDrawOption } from './draw_feature';
|
||||
let CircleFeatureId = 0;
|
||||
import { DrawEvent } from '../util/constant';
|
||||
import DrawFeature, { IDrawOption } from './draw_mode';
|
||||
export type unitsType = 'degrees' | 'radians' | 'miles' | 'kilometers';
|
||||
export interface IDrawCircleOption extends IDrawOption {
|
||||
units: unitsType;
|
||||
|
@ -29,21 +19,12 @@ export default class DrawEdit extends DrawFeature {
|
|||
private endPoint: ILngLat;
|
||||
// 绘制完成之后显示
|
||||
private editLayer: EditRender;
|
||||
// 编辑过程中显示
|
||||
private currentFeature: Feature | null;
|
||||
private popup: IPopup;
|
||||
constructor(scene: Scene, options: Partial<IDrawCircleOption> = {}) {
|
||||
super(scene, options);
|
||||
this.editLayer = new EditRender(this);
|
||||
}
|
||||
|
||||
public setEditFeature(feature: Feature) {
|
||||
this.currentFeature = feature;
|
||||
this.center = feature?.properties?.center;
|
||||
this.editLayer.updateData({
|
||||
type: 'FeatureCollection',
|
||||
features: [feature],
|
||||
});
|
||||
}
|
||||
|
||||
protected onDragStart = (e: IInteractionTarget) => {
|
||||
|
@ -59,51 +40,15 @@ export default class DrawEdit extends DrawFeature {
|
|||
|
||||
protected onDragging = (e: IInteractionTarget) => {
|
||||
this.endPoint = e.lngLat;
|
||||
const currentData = this.createCircleData(this.center, this.endPoint);
|
||||
this.editLayer.updateData(currentData);
|
||||
|
||||
this.addDrawPopup(this.endPoint, this.currentFeature?.properties?.radius);
|
||||
this.emit(DrawEvent.Edit, this.endPoint);
|
||||
return;
|
||||
};
|
||||
|
||||
protected onDragEnd = () => {
|
||||
this.popup.remove();
|
||||
this.emit(DrawEvent.UPDATE, null);
|
||||
this.disable();
|
||||
// @ts-ignore
|
||||
this.scene.map.dragPan.enable();
|
||||
};
|
||||
protected onClick = () => {
|
||||
return null;
|
||||
};
|
||||
|
||||
private createCircleData(center: ILngLat, endPoint: ILngLat) {
|
||||
const radius = turfDistance(
|
||||
point([center.lng, center.lat]),
|
||||
point([endPoint.lng, endPoint.lat]),
|
||||
this.getOption('units'),
|
||||
);
|
||||
const feature = turfCircle([center.lng, center.lat], radius, {
|
||||
units: this.getOption('units'),
|
||||
steps: this.getOption('steps'),
|
||||
properties: {
|
||||
id: `${CircleFeatureId++}`,
|
||||
radius,
|
||||
center,
|
||||
endPoint,
|
||||
},
|
||||
});
|
||||
this.currentFeature = feature as Feature;
|
||||
return featureCollection([feature]);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,93 +1,204 @@
|
|||
import { IInteractionTarget, Scene } from '@antv/l7';
|
||||
import { Feature, FeatureCollection } from '@turf/helpers';
|
||||
import { merge, throttle } from 'lodash';
|
||||
import DrawSource from '../source';
|
||||
import LayerStyles from '../util/layerstyle';
|
||||
import {
|
||||
IInteractionTarget,
|
||||
ILayer,
|
||||
ILngLat,
|
||||
IPopup,
|
||||
LineLayer,
|
||||
PointLayer,
|
||||
PolygonLayer,
|
||||
Popup,
|
||||
Scene,
|
||||
} from '@antv/l7';
|
||||
import turfCircle from '@turf/circle';
|
||||
import turfDistance from '@turf/distance';
|
||||
import {
|
||||
Feature,
|
||||
FeatureCollection,
|
||||
featureCollection,
|
||||
point,
|
||||
} from '@turf/helpers';
|
||||
import EditLayer from '../render/edit';
|
||||
import RenderLayer from '../render/render';
|
||||
import SelectLayer from '../render/selected';
|
||||
import { DrawEvent, DrawModes, unitsType } from '../util/constant';
|
||||
import DrawEdit from './draw_edit';
|
||||
import DrawMode, { IDrawOption } from './draw_mode';
|
||||
import DrawSelected from './draw_selected';
|
||||
let CircleFeatureId = 0;
|
||||
|
||||
export interface IDrawOption {
|
||||
data: FeatureCollection;
|
||||
style: any;
|
||||
export interface IDrawFeatureOption extends IDrawOption {
|
||||
units: unitsType;
|
||||
steps: number;
|
||||
}
|
||||
const InitFeature = {
|
||||
type: 'FeatureCollection',
|
||||
features: [],
|
||||
};
|
||||
export default abstract class DrawFeature extends DrawMode {
|
||||
// 绘制完成之后显示
|
||||
public selectMode: DrawSelected;
|
||||
public editMode: DrawEdit;
|
||||
protected renderLayer: RenderLayer;
|
||||
protected selectLayer: SelectLayer;
|
||||
protected editLayer: EditLayer;
|
||||
protected centerLayer: ILayer;
|
||||
|
||||
export type DrawStatus =
|
||||
| 'Drawing'
|
||||
| 'DrawSelected'
|
||||
| 'DrawEdit'
|
||||
| 'DrawFinish'
|
||||
| 'EditFinish';
|
||||
|
||||
export default abstract class DrawFeature {
|
||||
public source: DrawSource;
|
||||
public scene: Scene;
|
||||
protected options: {
|
||||
[key: string]: any;
|
||||
} = {
|
||||
style: LayerStyles,
|
||||
};
|
||||
protected drawStatus: DrawStatus = 'Drawing';
|
||||
private isEnable: boolean = false;
|
||||
constructor(scene: Scene, options: Partial<IDrawOption> = {}) {
|
||||
const { data } = options;
|
||||
this.scene = scene;
|
||||
this.source = new DrawSource(data);
|
||||
this.options = merge(this.options, this.getDefaultOptions(), options);
|
||||
// 编辑过程中显示
|
||||
protected drawLayer: ILayer;
|
||||
protected drawLineLayer: ILayer;
|
||||
constructor(scene: Scene, options: Partial<IDrawFeatureOption> = {}) {
|
||||
super(scene, options);
|
||||
this.renderLayer = new RenderLayer(this);
|
||||
this.selectLayer = new SelectLayer(this);
|
||||
this.editLayer = new EditLayer(this);
|
||||
this.selectMode = new DrawSelected(this.scene, {});
|
||||
this.editMode = new DrawEdit(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.on(DrawEvent.CREATE, this.onDrawCreate);
|
||||
this.on(DrawEvent.MODE_CHANGE, this.onModeChange);
|
||||
}
|
||||
public enable() {
|
||||
if (this.isEnable) {
|
||||
return;
|
||||
}
|
||||
// @ts-ignore
|
||||
this.scene.map.dragPan.disable();
|
||||
this.scene.on('dragstart', this.onDragStart);
|
||||
this.scene.on('dragging', this.onDragging);
|
||||
this.scene.on('dragend', this.onDragEnd);
|
||||
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.map.dragPan.enable();
|
||||
this.isEnable = false;
|
||||
}
|
||||
|
||||
public getOption(key: string) {
|
||||
return this.options[key];
|
||||
}
|
||||
public getStyle(id: string) {
|
||||
return this.getOption('style')[id];
|
||||
}
|
||||
|
||||
public setCursor(cursor: string) {
|
||||
const container = this.scene.getContainer();
|
||||
if (container) {
|
||||
container.style.cursor = cursor;
|
||||
}
|
||||
}
|
||||
public resetCursor() {
|
||||
const container = this.scene.getContainer();
|
||||
if (container) {
|
||||
container.style.cursor = 'default';
|
||||
}
|
||||
}
|
||||
|
||||
protected getDefaultOptions() {
|
||||
return {};
|
||||
return {
|
||||
steps: 64,
|
||||
units: 'kilometres',
|
||||
cursor: 'crosshair',
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract onDragStart(e: IInteractionTarget): void;
|
||||
|
||||
protected abstract onDragging(e: IInteractionTarget): void;
|
||||
|
||||
protected abstract onDragEnd(e: IInteractionTarget): void;
|
||||
|
||||
protected abstract onClick(): void;
|
||||
protected abstract createFeature(e: ILngLat): FeatureCollection;
|
||||
|
||||
protected abstract moveFeature(e: ILngLat): Feature;
|
||||
|
||||
protected abstract editFeature(e: any): FeatureCollection;
|
||||
|
||||
protected ondrawLayerClick = () => {
|
||||
if (this.currentFeature === null) {
|
||||
return;
|
||||
}
|
||||
this.currentFeature = null;
|
||||
this.renderLayer.updateData();
|
||||
this.centerLayer.setData([]);
|
||||
this.drawLayer.setData(InitFeature);
|
||||
this.drawLineLayer.setData(InitFeature);
|
||||
return;
|
||||
};
|
||||
protected initDrawFillLayer() {
|
||||
const style = this.getStyle('active_fill');
|
||||
const linestyle = this.getStyle('active_line');
|
||||
this.drawLayer = new PolygonLayer()
|
||||
.source(InitFeature)
|
||||
.color(style.color)
|
||||
.shape('fill')
|
||||
.style(style.style);
|
||||
this.drawLineLayer = new PolygonLayer()
|
||||
.source(InitFeature)
|
||||
.color(linestyle.color)
|
||||
.size(linestyle.size)
|
||||
.shape('line')
|
||||
.style(linestyle.style);
|
||||
this.scene.addLayer(this.drawLayer);
|
||||
this.scene.addLayer(this.drawLineLayer);
|
||||
}
|
||||
|
||||
protected updateDrawFillLayer(currentData: any) {
|
||||
this.drawLayer.setData(currentData);
|
||||
this.drawLineLayer.setData(currentData);
|
||||
}
|
||||
|
||||
private removeDrawLayer() {
|
||||
this.scene.removeLayer(this.drawLayer);
|
||||
this.scene.removeLayer(this.drawLineLayer);
|
||||
this.scene.removeLayer(this.centerLayer);
|
||||
}
|
||||
|
||||
private createCircleData(center: ILngLat, endPoint: ILngLat) {
|
||||
const radius = turfDistance(
|
||||
point([center.lng, center.lat]),
|
||||
point([endPoint.lng, endPoint.lat]),
|
||||
this.getOption('units'),
|
||||
);
|
||||
const feature = turfCircle([center.lng, center.lat], radius, {
|
||||
units: this.getOption('units'),
|
||||
steps: this.getOption('steps'),
|
||||
properties: {
|
||||
id: `${CircleFeatureId++}`,
|
||||
active: true,
|
||||
radius,
|
||||
center,
|
||||
endPoint,
|
||||
},
|
||||
});
|
||||
this.currentFeature = feature as Feature;
|
||||
return featureCollection([feature]);
|
||||
}
|
||||
|
||||
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:
|
||||
this.selectLayer.hide();
|
||||
this.editMode.setEditFeature(this.currentFeature as Feature);
|
||||
this.editLayer.updateData(
|
||||
featureCollection([this.currentFeature as Feature]),
|
||||
);
|
||||
this.editLayer.show();
|
||||
break;
|
||||
case DrawModes.SIMPLE_SELECT:
|
||||
this.renderLayer.updateData();
|
||||
this.selectMode.setSelectedFeature(this.currentFeature as Feature);
|
||||
this.selectLayer.updateData(
|
||||
featureCollection([this.currentFeature as Feature]),
|
||||
);
|
||||
this.selectLayer.show();
|
||||
break;
|
||||
case DrawModes.STATIC:
|
||||
this.source.setFeatureUnActive(this.currentFeature as Feature);
|
||||
this.renderLayer.updateData();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
private onDrawCreate = (feature: Feature) => {
|
||||
this.source.addFeature(feature);
|
||||
if (this.popup) {
|
||||
this.popup.remove();
|
||||
}
|
||||
this.removeDrawLayer();
|
||||
};
|
||||
|
||||
private onDrawUpdate = (feature: Feature) => {
|
||||
this.source.updateFeature(this.currentFeature as Feature);
|
||||
};
|
||||
|
||||
private onDrawMove = (delta: ILngLat) => {
|
||||
const feature = this.moveFeature(delta);
|
||||
this.currentFeature = feature;
|
||||
this.selectLayer.updateData(featureCollection([feature]));
|
||||
};
|
||||
|
||||
private onDrawEdit = (endpoint: ILngLat) => {
|
||||
const feature = this.editFeature(endpoint);
|
||||
this.currentFeature = feature.features[0];
|
||||
this.editLayer.updateData(feature);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
import { IInteractionTarget, IPopup, Scene } from '@antv/l7';
|
||||
import { Feature, FeatureCollection } from '@turf/helpers';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import { merge, throttle } from 'lodash';
|
||||
import DrawSource from '../source';
|
||||
import LayerStyles from '../util/layerstyle';
|
||||
|
||||
export interface IDrawOption {
|
||||
data: FeatureCollection;
|
||||
style: any;
|
||||
}
|
||||
|
||||
export type DrawStatus =
|
||||
| 'Drawing'
|
||||
| 'DrawSelected'
|
||||
| 'DrawEdit'
|
||||
| 'DrawFinish'
|
||||
| 'EditFinish';
|
||||
|
||||
export default abstract class DrawMode extends EventEmitter {
|
||||
public source: DrawSource;
|
||||
public scene: Scene;
|
||||
protected options: {
|
||||
[key: string]: any;
|
||||
} = {
|
||||
style: LayerStyles,
|
||||
};
|
||||
protected drawStatus: DrawStatus = 'Drawing';
|
||||
protected currentFeature: Feature | null;
|
||||
protected isEnable: boolean = false;
|
||||
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);
|
||||
}
|
||||
public enable() {
|
||||
if (this.isEnable) {
|
||||
return;
|
||||
}
|
||||
// @ts-ignore
|
||||
this.scene.map.dragPan.disable();
|
||||
this.scene.on('dragstart', this.onDragStart);
|
||||
this.scene.on('dragging', this.onDragging);
|
||||
this.scene.on('dragend', this.onDragEnd);
|
||||
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.map.dragPan.enable();
|
||||
this.isEnable = false;
|
||||
}
|
||||
public setCurrentFeature(feature: Feature) {
|
||||
this.currentFeature = feature;
|
||||
this.source.setFeatureActive(feature);
|
||||
}
|
||||
|
||||
public getOption(key: string) {
|
||||
return this.options[key];
|
||||
}
|
||||
public getStyle(id: string) {
|
||||
return this.getOption('style')[id];
|
||||
}
|
||||
|
||||
public setCursor(cursor: string) {
|
||||
const container = this.scene.getContainer();
|
||||
if (container) {
|
||||
container.style.cursor = cursor;
|
||||
}
|
||||
}
|
||||
public resetCursor() {
|
||||
const container = this.scene.getContainer();
|
||||
if (container) {
|
||||
container.style.cursor = 'default';
|
||||
}
|
||||
}
|
||||
|
||||
protected getDefaultOptions() {
|
||||
return {};
|
||||
}
|
||||
|
||||
protected abstract onDragStart(e: IInteractionTarget): void;
|
||||
|
||||
protected abstract onDragging(e: IInteractionTarget): void;
|
||||
|
||||
protected abstract onDragEnd(e: IInteractionTarget): void;
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
import {
|
||||
IInteractionTarget,
|
||||
ILayer,
|
||||
ILngLat,
|
||||
IPopup,
|
||||
LineLayer,
|
||||
PointLayer,
|
||||
PolygonLayer,
|
||||
Popup,
|
||||
Scene,
|
||||
} from '@antv/l7';
|
||||
import { Feature, FeatureCollection, point } from '@turf/helpers';
|
||||
import selectRender from '../render/selected';
|
||||
import { DrawEvent, DrawModes, unitsType } from '../util/constant';
|
||||
import { creatRect } from '../util/create_geometry';
|
||||
import moveFeatures, { movePoint, moveRing } from '../util/move_featrues';
|
||||
import DrawFeature, { IDrawFeatureOption } from './draw_feature';
|
||||
export interface IDrawRectOption extends IDrawFeatureOption {
|
||||
units: unitsType;
|
||||
steps: number;
|
||||
}
|
||||
export default class DrawRect extends DrawFeature {
|
||||
private startPoint: ILngLat;
|
||||
private endPoint: ILngLat;
|
||||
constructor(scene: Scene, options: Partial<IDrawRectOption> = {}) {
|
||||
super(scene, options);
|
||||
this.selectLayer = new selectRender(this);
|
||||
}
|
||||
protected onDragStart = (e: IInteractionTarget) => {
|
||||
this.startPoint = e.lngLat;
|
||||
this.setCursor('grabbing');
|
||||
this.initCenterLayer();
|
||||
this.initDrawFillLayer();
|
||||
this.centerLayer.setData([this.startPoint]);
|
||||
};
|
||||
protected onDragging = (e: IInteractionTarget) => {
|
||||
this.endPoint = e.lngLat;
|
||||
const feature = this.createFeature();
|
||||
this.updateDrawFillLayer(feature);
|
||||
};
|
||||
|
||||
protected onDragEnd = () => {
|
||||
this.emit(DrawEvent.CREATE, this.currentFeature);
|
||||
this.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_SELECT);
|
||||
this.disable();
|
||||
};
|
||||
|
||||
protected moveFeature(delta: ILngLat): Feature {
|
||||
const newFeature = moveFeatures([this.currentFeature as Feature], delta)[0];
|
||||
const properties = newFeature.properties as {
|
||||
startPoint: [number, number];
|
||||
endPoint: [number, number];
|
||||
};
|
||||
const { startPoint, endPoint } = properties;
|
||||
properties.startPoint = movePoint(startPoint, delta);
|
||||
properties.endPoint = movePoint(endPoint, delta);
|
||||
newFeature.properties = properties;
|
||||
this.startPoint = {
|
||||
lat: startPoint[1],
|
||||
lng: startPoint[0],
|
||||
};
|
||||
this.endPoint = {
|
||||
lat: endPoint[1],
|
||||
lng: endPoint[0],
|
||||
};
|
||||
return newFeature;
|
||||
}
|
||||
|
||||
protected createFeature(): FeatureCollection {
|
||||
const feature = creatRect(
|
||||
[this.startPoint.lng, this.startPoint.lat],
|
||||
[this.endPoint.lng, this.endPoint.lat],
|
||||
);
|
||||
this.setCurrentFeature(feature as Feature);
|
||||
return {
|
||||
type: 'FeatureCollection',
|
||||
features: [feature],
|
||||
};
|
||||
}
|
||||
|
||||
protected editFeature(endPoint: ILngLat): FeatureCollection {
|
||||
this.endPoint = endPoint;
|
||||
return this.createFeature();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -13,8 +13,9 @@ import turfCircle from '@turf/circle';
|
|||
import turfDistance from '@turf/distance';
|
||||
import { Feature, featureCollection, point } from '@turf/helpers';
|
||||
import EditRender from '../render/selected';
|
||||
import DrawFeature, { IDrawOption } from './draw_feature';
|
||||
let CircleFeatureId = 0;
|
||||
import { DrawEvent, DrawModes } from '../util/constant';
|
||||
import moveFeatures from '../util/move_featrues';
|
||||
import DrawFeature, { IDrawOption } from './draw_mode';
|
||||
export type unitsType = 'degrees' | 'radians' | 'miles' | 'kilometers';
|
||||
export interface IDrawCircleOption extends IDrawOption {
|
||||
units: unitsType;
|
||||
|
@ -29,19 +30,18 @@ export default class DrawSelect extends DrawFeature {
|
|||
private dragStartPoint: ILngLat;
|
||||
// 绘制完成之后显示
|
||||
private editLayer: EditRender;
|
||||
// 编辑过程中显示
|
||||
private currentFeature: Feature | null;
|
||||
constructor(scene: Scene, options: Partial<IDrawCircleOption> = {}) {
|
||||
super(scene, options);
|
||||
this.editLayer = new EditRender(this);
|
||||
// this.editLayer = new EditRender(this);
|
||||
}
|
||||
|
||||
public setSelectedFeature(feature: Feature) {
|
||||
this.currentFeature = feature;
|
||||
this.editLayer.updateData({
|
||||
type: 'FeatureCollection',
|
||||
features: [feature],
|
||||
});
|
||||
// this.editLayer.updateData({
|
||||
// type: 'FeatureCollection',
|
||||
// features: [feature],
|
||||
// });
|
||||
// this.editLayer.show();
|
||||
}
|
||||
|
||||
protected onDragStart = (e: IInteractionTarget) => {
|
||||
|
@ -62,14 +62,14 @@ export default class DrawSelect extends DrawFeature {
|
|||
lng: e.lngLat.lng - this.dragStartPoint.lng,
|
||||
lat: e.lngLat.lat - this.dragStartPoint.lat,
|
||||
};
|
||||
this.moveCircle(this.currentFeature as Feature, delta);
|
||||
this.emit(DrawEvent.Move, delta);
|
||||
this.dragStartPoint = e.lngLat;
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
protected onDragEnd = () => {
|
||||
return null;
|
||||
this.emit(DrawEvent.UPDATE, this.currentFeature);
|
||||
};
|
||||
protected onClick = () => {
|
||||
return null;
|
||||
|
@ -85,7 +85,8 @@ export default class DrawSelect extends DrawFeature {
|
|||
units: this.getOption('units'),
|
||||
steps: this.getOption('steps'),
|
||||
properties: {
|
||||
id: `${CircleFeatureId++}`,
|
||||
id: `${this.currentFeature?.properties?.id}`,
|
||||
active: true,
|
||||
radius,
|
||||
center,
|
||||
endPoint,
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
import DrawCircle from './draw_circle';
|
||||
export { DrawCircle };
|
||||
import DrawRect from './draw_rect';
|
||||
export { DrawCircle, DrawRect };
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
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 DrawLayer {
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ const InitFeature = {
|
|||
};
|
||||
import { Feature } from '@turf/helpers';
|
||||
import Draw from '../modes/draw_feature';
|
||||
import { DrawEvent, DrawModes } from '../util/constant';
|
||||
export default class EditRenderLayer {
|
||||
private polygonLayer: ILayer;
|
||||
private lineLayer: ILayer;
|
||||
|
@ -77,14 +78,31 @@ export default class EditRenderLayer {
|
|||
this.draw.scene.addLayer(this.lineLayer);
|
||||
this.draw.scene.addLayer(this.centerLayer);
|
||||
this.draw.scene.addLayer(this.endPointLayer);
|
||||
this.addLayerEvent();
|
||||
}
|
||||
public updateData(data: any) {
|
||||
if (this.currentFeature === undefined) {
|
||||
this.addLayerEvent();
|
||||
}
|
||||
this.currentFeature = data.features[0];
|
||||
this.lineLayer.setData(data);
|
||||
this.polygonLayer.setData(data);
|
||||
this.centerLayer.setData([data.features[0].properties.center]);
|
||||
this.endPointLayer.setData([data.features[0].properties.endPoint]);
|
||||
const properties = data.features[0].properties;
|
||||
if (properties.startPoint) {
|
||||
this.centerLayer.setData([
|
||||
{
|
||||
lng: properties.startPoint[0],
|
||||
lat: properties.startPoint[1],
|
||||
},
|
||||
]);
|
||||
}
|
||||
if (properties.endPoint) {
|
||||
this.endPointLayer.setData([
|
||||
{
|
||||
lng: properties.endPoint[0],
|
||||
lat: properties.endPoint[1],
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
|
@ -94,14 +112,34 @@ export default class EditRenderLayer {
|
|||
this.draw.scene.removeLayer(this.endPointLayer);
|
||||
}
|
||||
|
||||
public show() {
|
||||
this.lineLayer.show();
|
||||
this.polygonLayer.show();
|
||||
this.centerLayer.show();
|
||||
this.endPointLayer.show();
|
||||
}
|
||||
|
||||
public hide() {
|
||||
this.lineLayer.hide();
|
||||
this.polygonLayer.hide();
|
||||
this.centerLayer.hide();
|
||||
this.endPointLayer.hide();
|
||||
}
|
||||
|
||||
private addLayerEvent() {
|
||||
this.endPointLayer.on('mousemove', (e) => {
|
||||
this.draw.setCursor('move');
|
||||
this.draw.enable();
|
||||
this.draw.editMode.enable();
|
||||
});
|
||||
this.endPointLayer.on('unmousemove', (e) => {
|
||||
this.draw.resetCursor();
|
||||
this.draw.disable();
|
||||
this.draw.editMode.disable();
|
||||
});
|
||||
this.polygonLayer.on('unclick', (e) => {
|
||||
// 取消选中 回到初始态
|
||||
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
|
||||
this.draw.editMode.disable();
|
||||
this.hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ const InitFeature = {
|
|||
type: 'FeatureCollection',
|
||||
features: [],
|
||||
};
|
||||
import Draw from '../modes/draw_feature';
|
||||
import Draw from '../modes/draw_mode';
|
||||
import { DrawEvent, DrawModes } from '../util/constant';
|
||||
export default class RenderLayer {
|
||||
private polygonLayer: ILayer;
|
||||
private lineLayer: ILayer;
|
||||
|
@ -29,6 +30,9 @@ export default class RenderLayer {
|
|||
zIndex: 0,
|
||||
})
|
||||
.source(InitFeature)
|
||||
.filter('active', (active) => {
|
||||
return !active;
|
||||
})
|
||||
.shape('fill')
|
||||
.active(true)
|
||||
.color(style.color)
|
||||
|
@ -39,11 +43,15 @@ export default class RenderLayer {
|
|||
})
|
||||
.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);
|
||||
|
@ -54,4 +62,21 @@ export default class RenderLayer {
|
|||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ const InitFeature = {
|
|||
features: [],
|
||||
};
|
||||
import { Feature } from '@turf/helpers';
|
||||
import DrawEdit from '../modes/draw_edit';
|
||||
import Draw from '../modes/draw_feature';
|
||||
import { DrawEvent, DrawModes } from '../util/constant';
|
||||
export default class EditRenderLayer {
|
||||
private polygonLayer: ILayer;
|
||||
private lineLayer: ILayer;
|
||||
|
@ -59,41 +59,56 @@ export default class EditRenderLayer {
|
|||
.style(centerStyle.style);
|
||||
this.draw.scene.addLayer(this.polygonLayer);
|
||||
this.draw.scene.addLayer(this.lineLayer);
|
||||
this.draw.scene.addLayer(this.centerLayer);
|
||||
this.addLayerEvent();
|
||||
// this.draw.scene.addLayer(this.centerLayer);
|
||||
}
|
||||
public updateData(data: any) {
|
||||
if (this.currentFeature === undefined) {
|
||||
this.addLayerEvent();
|
||||
}
|
||||
this.currentFeature = data.features[0];
|
||||
this.lineLayer.setData(data);
|
||||
this.polygonLayer.setData(data);
|
||||
this.centerLayer.setData([data.features[0].properties.center]);
|
||||
// this.centerLayer.setData([data.features[0].properties.center]);
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.draw.scene.removeLayer(this.lineLayer);
|
||||
this.draw.scene.removeLayer(this.polygonLayer);
|
||||
this.draw.scene.removeLayer(this.centerLayer);
|
||||
// this.draw.scene.removeLayer(this.centerLayer);
|
||||
}
|
||||
|
||||
public show() {
|
||||
this.lineLayer.show();
|
||||
this.polygonLayer.show();
|
||||
// this.centerLayer.show();
|
||||
}
|
||||
|
||||
public hide() {
|
||||
this.lineLayer.hide();
|
||||
this.polygonLayer.hide();
|
||||
// this.centerLayer.hide();
|
||||
}
|
||||
private addLayerEvent() {
|
||||
this.polygonLayer.on('mousemove', (e) => {
|
||||
this.draw.setCursor('move');
|
||||
this.draw.enable();
|
||||
this.draw.selectMode.enable();
|
||||
});
|
||||
this.polygonLayer.on('unmousemove', (e) => {
|
||||
this.draw.resetCursor();
|
||||
this.draw.disable();
|
||||
this.draw.selectMode.disable();
|
||||
});
|
||||
|
||||
this.polygonLayer.on('click', (e) => {
|
||||
// 进入编辑态
|
||||
const drawEdit = new DrawEdit(this.draw.scene, {});
|
||||
drawEdit.setEditFeature(this.currentFeature);
|
||||
this.draw.disable();
|
||||
this.destroy();
|
||||
this.draw.selectMode.disable();
|
||||
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.DIRECT_SELECT);
|
||||
this.hide();
|
||||
});
|
||||
this.polygonLayer.on('unclick', (e) => {
|
||||
// 取消选中 回到初始态
|
||||
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
|
||||
this.draw.selectMode.disable();
|
||||
this.hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,18 @@ export default class DrawSource {
|
|||
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 updateFeature(feature: Feature) {
|
||||
this.removeFeature(feature);
|
||||
this.addFeature(feature);
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
export enum DrawEvent {
|
||||
CREATE = 'draw.create',
|
||||
DELETE = 'draw.delete',
|
||||
Move = 'draw.move',
|
||||
Edit = 'draw.edit',
|
||||
UPDATE = 'draw.update',
|
||||
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',
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
import turfCircle from '@turf/circle';
|
||||
import turfDistance from '@turf/distance';
|
||||
import { Feature, featureCollection, point } from '@turf/helpers';
|
||||
import { unitsType } from './constant';
|
||||
|
||||
export function createCircle(
|
||||
center: [number, number],
|
||||
endPoint: [number, number],
|
||||
options: {
|
||||
units: unitsType;
|
||||
steps: number;
|
||||
id: string;
|
||||
},
|
||||
): Feature {
|
||||
const radius = turfDistance(point(center), point(endPoint), options);
|
||||
const feature = turfCircle(center, radius, {
|
||||
units: options.units,
|
||||
steps: options.steps,
|
||||
properties: {
|
||||
id: options.id,
|
||||
active: true,
|
||||
radius,
|
||||
startPoint: center,
|
||||
endPoint,
|
||||
path: [center, endPoint],
|
||||
},
|
||||
});
|
||||
return feature as Feature;
|
||||
}
|
||||
|
||||
export function creatRect(
|
||||
startPoint: [number, number],
|
||||
endPoint: [number, number],
|
||||
): 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: {
|
||||
active: true,
|
||||
startPoint,
|
||||
endPoint,
|
||||
},
|
||||
geometry: {
|
||||
type: 'Polygon',
|
||||
coordinates: [
|
||||
[
|
||||
[minX, minY],
|
||||
[minX, maxY],
|
||||
[maxX, maxY],
|
||||
[maxX, minY],
|
||||
[minX, minY],
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
return feature as Feature;
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
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));
|
||||
}
|
|
@ -3,6 +3,6 @@ export const MapTheme: {
|
|||
} = {
|
||||
dark: 'amap://styles/2a09079c3daac9420ee53b67307a8006?isPublic=true',
|
||||
light: 'amap://styles/1fd9f8ef9751298f11f5c56968312c70?isPublic=true',
|
||||
normal: 'amap://styles/12db649ba3493333b098127ed892c0cb?isPublic=true',
|
||||
normal: 'amap://styles/normal',
|
||||
blank: 'amap://styles/07c17002b38775b32a7a76c66cf90e99?isPublic=true',
|
||||
};
|
||||
|
|
|
@ -1,43 +1,9 @@
|
|||
import { LineLayer, PointLayer, PolygonLayer, Popup, Scene } from '@antv/l7';
|
||||
import { DrawRect } from '@antv/l7-draw';
|
||||
import { GaodeMap, Mapbox } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
const createGeoJSONRect = (
|
||||
point1: [number, number],
|
||||
point2: [number, number],
|
||||
) => {
|
||||
const minX = Math.min(point1[0], point2[0]);
|
||||
const minY = Math.min(point1[1], point2[1]);
|
||||
const maxX = Math.max(point1[0], point2[0]);
|
||||
const maxY = Math.max(point1[1], point2[1]);
|
||||
|
||||
return {
|
||||
type: 'geojson',
|
||||
data: {
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'Polygon',
|
||||
coordinates: [
|
||||
[
|
||||
[minX, minY],
|
||||
[minX, maxY],
|
||||
[maxX, maxY],
|
||||
[maxX, minY],
|
||||
[minX, minY],
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
};
|
||||
export default class MultiPolygon extends React.Component {
|
||||
private gui: dat.GUI;
|
||||
private $stats: Node;
|
||||
import * as React from 'react';
|
||||
export default class Circle extends React.Component {
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
|
@ -49,63 +15,16 @@ export default class MultiPolygon extends React.Component {
|
|||
id: 'map',
|
||||
map: new Mapbox({
|
||||
pitch: 0,
|
||||
style: 'normal',
|
||||
center: [121.775374, 31.31067],
|
||||
zoom: 15,
|
||||
style: 'light',
|
||||
center: [113.775374, 28.31067],
|
||||
zoom: 12,
|
||||
}),
|
||||
});
|
||||
this.scene = scene;
|
||||
|
||||
scene.on('loaded', () => {
|
||||
let startPoint = {};
|
||||
const circleLayer = new PolygonLayer()
|
||||
.source({
|
||||
type: 'FeatureCollection',
|
||||
features: [],
|
||||
})
|
||||
.color('#fbb03b')
|
||||
.shape('fill')
|
||||
.style({
|
||||
opacity: 0.6,
|
||||
});
|
||||
scene.addLayer(circleLayer);
|
||||
scene.on('panstart', (e: any) => {
|
||||
// @ts-ignore
|
||||
scene.map.dragPan.disable();
|
||||
startPoint = e.lngLat;
|
||||
const layer = new PointLayer()
|
||||
.source([startPoint], {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
})
|
||||
.shape('circle')
|
||||
.color('#fbb03b')
|
||||
.size(5)
|
||||
.style({
|
||||
stroke: '#fff',
|
||||
strokeWidth: 2,
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
});
|
||||
scene.on('panmove', (e: any) => {
|
||||
// @ts-ignore
|
||||
const start = [startPoint.lng, startPoint.lat];
|
||||
|
||||
const circleData = createGeoJSONRect(start as [number, number], [
|
||||
e.lngLat.lng,
|
||||
e.lngLat.lat,
|
||||
]);
|
||||
circleLayer.setData(circleData.data);
|
||||
// const popup = new Popup().setText(`${dis}`).setLnglat(e.lngLat);
|
||||
// scene.addPopup(popup);
|
||||
});
|
||||
scene.on('panend', (e: any) => {
|
||||
// @ts-ignore
|
||||
scene.map.dragPan.enable();
|
||||
});
|
||||
const drawRect = new DrawRect(scene);
|
||||
drawRect.enable();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue