From f8ae7322e65ed15be22718cfc8c9087a38c0f39f Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Wed, 1 Apr 2020 15:22:53 +0800 Subject: [PATCH] improvement: add draw ui tools --- packages/component/src/control/zoom.ts | 3 +- packages/core/src/services/map/IMapService.ts | 1 + packages/draw/src/control.ts | 10 -- packages/draw/src/css/draw.less | 48 ++++++++ packages/draw/src/css/svg/combine.svg | 106 ++++++++++++++++ packages/draw/src/css/svg/line.svg | 68 ++++++++++ packages/draw/src/css/svg/point.svg | 86 +++++++++++++ packages/draw/src/css/svg/polygon.svg | 93 ++++++++++++++ packages/draw/src/css/svg/trash.svg | 73 +++++++++++ packages/draw/src/css/svg/uncombine.svg | 106 ++++++++++++++++ packages/draw/src/draw_control.ts | 116 ++++++++++++++++++ packages/draw/src/index.ts | 1 + packages/draw/src/modes/draw_circle.ts | 66 +++++++--- packages/draw/src/modes/draw_feature.ts | 35 ++++-- packages/draw/src/modes/draw_line.ts | 19 +-- packages/draw/src/modes/draw_mode.ts | 11 +- packages/draw/src/modes/draw_point.ts | 15 +-- packages/draw/src/modes/draw_polygon.ts | 60 +++++---- packages/draw/src/modes/draw_rect.ts | 10 +- packages/draw/src/modes/index.ts | 3 +- packages/draw/src/render/base_render.ts | 3 + packages/draw/src/render/draw.ts | 6 +- packages/draw/src/render/draw_result.ts | 22 +++- packages/draw/src/source.ts | 7 ++ packages/draw/src/util/create_geometry.ts | 29 ++++- packages/maps/src/amap/map.ts | 4 + packages/maps/src/mapbox/logo.css | 3 + packages/maps/src/mapbox/map.ts | 22 ++-- packages/scene/src/index.ts | 3 + stories/Draw/Components/DrawControl.tsx | 55 +++++++++ stories/Draw/Draw.stories.tsx | 2 + 31 files changed, 976 insertions(+), 110 deletions(-) delete mode 100644 packages/draw/src/control.ts create mode 100644 packages/draw/src/css/draw.less create mode 100644 packages/draw/src/css/svg/combine.svg create mode 100644 packages/draw/src/css/svg/line.svg create mode 100644 packages/draw/src/css/svg/point.svg create mode 100644 packages/draw/src/css/svg/polygon.svg create mode 100644 packages/draw/src/css/svg/trash.svg create mode 100644 packages/draw/src/css/svg/uncombine.svg create mode 100644 packages/draw/src/draw_control.ts create mode 100644 packages/maps/src/mapbox/logo.css create mode 100644 stories/Draw/Components/DrawControl.tsx diff --git a/packages/component/src/control/zoom.ts b/packages/component/src/control/zoom.ts index abe8549633..bbb285c1a0 100644 --- a/packages/component/src/control/zoom.ts +++ b/packages/component/src/control/zoom.ts @@ -27,7 +27,7 @@ export default class Zoom extends Control { }; } - public onAdd() { + public onAdd(): HTMLElement { const zoomName = 'l7-control-zoom'; const container = DOM.create('div', zoomName + ' l7-bar'); @@ -93,6 +93,7 @@ export default class Zoom extends Control { ) { const link = DOM.create('a', className, container) as HTMLLinkElement; link.innerHTML = html; + link.title = tile; link.href = 'javascript:void(0)'; link.addEventListener('click', fn); return link; diff --git a/packages/core/src/services/map/IMapService.ts b/packages/core/src/services/map/IMapService.ts index c353576c22..b4b8eb4e75 100644 --- a/packages/core/src/services/map/IMapService.ts +++ b/packages/core/src/services/map/IMapService.ts @@ -52,6 +52,7 @@ export interface IMapService { getRotation(): number; getBounds(): Bounds; getMapContainer(): HTMLElement | null; + getMapCanvasContainer(): HTMLElement; // control with raw map setRotation(rotation: number): void; diff --git a/packages/draw/src/control.ts b/packages/draw/src/control.ts deleted file mode 100644 index b74b3c7dd7..0000000000 --- a/packages/draw/src/control.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Control } from '@antv/l7-component'; -export interface IDrawControlOption { - pickBuffer: number; - controls: any; -} -export default class DrawControl extends Control { - constructor(options: IDrawControlOption) { - super(options); - } -} diff --git a/packages/draw/src/css/draw.less b/packages/draw/src/css/draw.less new file mode 100644 index 0000000000..b750bdf83c --- /dev/null +++ b/packages/draw/src/css/draw.less @@ -0,0 +1,48 @@ +.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+button { + border-top: 1px solid #ddd; + } + button:not(:disabled):hover { + background-color: rgba(255, 255, 255, 0.9); + } + button:focus:first-child { + border-radius: 4px 4px 0 0; + } + button:focus { + box-shadow: 0 0 2px 2px #0096ff; + } + .draw-point { + background-image: url('https://gw.alipayobjects.com/zos/bmw-prod/f7bf0137-7de9-411a-9a37-4880acc58d29.svg'); + } + .draw-line { + background-image: url('https://gw.alipayobjects.com/zos/bmw-prod/a784e304-afb2-4888-91b4-e0d0e8058810.svg'); + } + .draw-polygon { + background-image: url('https://gw.alipayobjects.com/zos/bmw-prod/6dd9914d-d625-4424-8db7-19953e67444f.svg'); + } + .draw-rect { + background-image: url('https://gw.alipayobjects.com/zos/bmw-prod/fe578687-693b-4c27-afb3-0e675d9431ff.svg'); + } + .draw-circle { + background-image: url('https://gw.alipayobjects.com/zos/bmw-prod/fa234d68-85aa-4628-b1b6-aad47ab093b4.svg'); + } + +} diff --git a/packages/draw/src/css/svg/combine.svg b/packages/draw/src/css/svg/combine.svg new file mode 100644 index 0000000000..febc04705d --- /dev/null +++ b/packages/draw/src/css/svg/combine.svg @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/packages/draw/src/css/svg/line.svg b/packages/draw/src/css/svg/line.svg new file mode 100644 index 0000000000..9bcec18c9c --- /dev/null +++ b/packages/draw/src/css/svg/line.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/packages/draw/src/css/svg/point.svg b/packages/draw/src/css/svg/point.svg new file mode 100644 index 0000000000..c767a55718 --- /dev/null +++ b/packages/draw/src/css/svg/point.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/packages/draw/src/css/svg/polygon.svg b/packages/draw/src/css/svg/polygon.svg new file mode 100644 index 0000000000..4c8dc9bb4e --- /dev/null +++ b/packages/draw/src/css/svg/polygon.svg @@ -0,0 +1,93 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/packages/draw/src/css/svg/trash.svg b/packages/draw/src/css/svg/trash.svg new file mode 100644 index 0000000000..8b350ad1e6 --- /dev/null +++ b/packages/draw/src/css/svg/trash.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/packages/draw/src/css/svg/uncombine.svg b/packages/draw/src/css/svg/uncombine.svg new file mode 100644 index 0000000000..3a4b3190cb --- /dev/null +++ b/packages/draw/src/css/svg/uncombine.svg @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/packages/draw/src/draw_control.ts b/packages/draw/src/draw_control.ts new file mode 100644 index 0000000000..0233a2d20f --- /dev/null +++ b/packages/draw/src/draw_control.ts @@ -0,0 +1,116 @@ +import { Control, IControlOption, PositionType, Scene } from '@antv/l7'; +import { DOM } from '@antv/l7-utils'; +import './css/draw.less'; +import { + DrawCircle, + DrawLine, + DrawMode, + DrawPoint, + DrawPolygon, + DrawRect, +} from './modes'; +export interface IControls { + [key: string]: boolean; +} + +export interface IDrawControlOption extends IControlOption { + pickBuffer: number; + controls: IControls; + layout: 'horizontal' | 'vertical'; +} +export class DrawControl extends Control { + private draw: { + [key: string]: DrawMode; + } = {}; + private scene: Scene; + constructor(scene: Scene, options: Partial) { + super(options); + this.scene = scene; + } + + public getDefault() { + return { + position: PositionType.TOPLEFT, + controls: { + point: true, + }, + name: 'draw', + }; + } + + public onAdd(): HTMLElement { + const controlClass = 'l7-control-draw'; + const { controls } = this.controlOption as IDrawControlOption; + const container = DOM.create('div', controlClass) as HTMLElement; + container.style.flexDirection = + this.controlOption.layout === 'vertical' ? 'column' : 'row'; + if (controls.point) { + this.draw.point = new DrawPoint(this.scene); + this.createButton( + '绘制点', + 'draw-point', + container, + this.onButtonClick.bind(null, 'point'), + ); + } + if (controls.line) { + this.draw.line = new DrawLine(this.scene); + this.createButton( + '绘制线', + 'draw-line', + container, + this.onButtonClick.bind(null, 'line'), + ); + } + if (controls.polygon) { + this.createButton( + '绘制面', + 'draw-polygon', + container, + this.onButtonClick.bind(null, 'polygon'), + ); + this.draw.polygon = new DrawPolygon(this.scene); + } + if (controls.rect) { + this.draw.rect = new DrawRect(this.scene); + this.createButton( + '绘制矩形', + 'draw-rect', + container, + this.onButtonClick.bind(null, 'rect'), + ); + } + if (controls.circle) { + this.draw.circle = new DrawCircle(this.scene); + this.createButton( + '绘制圆', + 'draw-circle', + container, + this.onButtonClick.bind(null, 'circle'), + ); + } + return container; + } + + private createButton( + tile: string, + className: string, + container: HTMLElement, + fn: (...arg: any[]) => any, + ) { + const link = DOM.create('button', className, container) as HTMLLinkElement; + link.title = tile; + link.addEventListener('click', fn); + return link; + } + + private onButtonClick = (type: string) => { + for (const draw in this.draw) { + if (draw === type) { + this.draw[draw].enable(); + } else { + this.draw[draw].disable(); + } + } + }; +} diff --git a/packages/draw/src/index.ts b/packages/draw/src/index.ts index b97b258fd7..5e830027f5 100644 --- a/packages/draw/src/index.ts +++ b/packages/draw/src/index.ts @@ -1 +1,2 @@ export * from './modes/index'; +export * from './draw_control'; diff --git a/packages/draw/src/modes/draw_circle.ts b/packages/draw/src/modes/draw_circle.ts index 6c539d9b43..dfe82e7250 100644 --- a/packages/draw/src/modes/draw_circle.ts +++ b/packages/draw/src/modes/draw_circle.ts @@ -1,5 +1,11 @@ import { IInteractionTarget, ILngLat, PointLayer, Scene } from '@antv/l7'; -import { Feature, FeatureCollection, featureCollection } from '@turf/helpers'; +import { + Feature, + FeatureCollection, + 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'; @@ -20,33 +26,49 @@ export default class DrawCircle extends DrawFeature { public drawFinish() { return null; } + + public setCurrentFeature(feature: Feature) { + this.currentFeature = feature as Feature; + // @ts-ignore + // @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 onDragStart = (e: IInteractionTarget) => { 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(); - const pointfeatures = createPoint([this.endPoint]); - this.pointFeatures = pointfeatures.features; - this.drawRender.update(feature); - this.drawVertexLayer.update(pointfeatures); + const feature = this.createFeature() as Feature; + const properties = feature.properties as { pointFeatures: Feature[] }; + this.drawRender.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.drawRender.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): Feature { + protected moveFeature(delta: ILngLat): void { const newFeature = moveFeatures([this.currentFeature as Feature], delta); this.drawRender.updateData(featureCollection(newFeature)); const newPointFeture = moveFeatures(this.pointFeatures, delta); this.drawVertexLayer.updateData(featureCollection(newPointFeture)); - this.currentFeature = newFeature[0]; const newStartPoint = movePoint( [this.startPoint.lng, this.startPoint.lat], delta, @@ -55,35 +77,43 @@ export default class DrawCircle extends DrawFeature { lat: newStartPoint[1], lng: newStartPoint[0], }; + newFeature[0].properties = { + ...newFeature[0].properties, + startPoint: this.startPoint, + pointFeatures: newPointFeture, + }; this.centerLayer.setData([this.startPoint]); - return this.currentFeature; + this.setCurrentFeature(newFeature[0]); } - protected createFeature(): FeatureCollection { + 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.getUniqId()}`, + id, }, ); this.setCurrentFeature(feature as Feature); - return featureCollection([feature]); + return feature; } - protected editFeature(endPoint: ILngLat): FeatureCollection { + protected editFeature(endPoint: ILngLat): void { this.endPoint = endPoint; const newFeature = this.createFeature(); - this.drawRender.updateData(newFeature); - const pointfeatures = createPoint([this.endPoint]); - this.pointFeatures = pointfeatures.features; - this.drawVertexLayer.updateData(pointfeatures); - return this.createFeature(); + const properties = newFeature.properties as { pointFeatures: Feature[] }; + this.drawRender.updateData(featureCollection([newFeature])); + this.drawVertexLayer.updateData( + featureCollection(properties.pointFeatures), + ); } protected showOtherLayer() { + this.centerLayer.setData([this.currentFeature?.properties?.startPoint]); this.centerLayer.show(); } diff --git a/packages/draw/src/modes/draw_feature.ts b/packages/draw/src/modes/draw_feature.ts index 8fb20b63b8..04422b0681 100644 --- a/packages/draw/src/modes/draw_feature.ts +++ b/packages/draw/src/modes/draw_feature.ts @@ -53,6 +53,15 @@ export default abstract class DrawFeature extends DrawMode { this.on(DrawEvent.MODE_CHANGE, this.onModeChange); } public abstract drawFinish(): void; + public setCurrentFeature(feature: Feature) { + this.currentFeature = feature as Feature; + // @ts-ignore + // @ts-ignore + this.pointFeatures = feature.properties.pointFeatures; + + this.source.setFeatureActive(feature); + } + public addVertex(feature: Feature): void { throw new Error('子类未实现该方法'); } @@ -69,11 +78,11 @@ export default abstract class DrawFeature extends DrawMode { protected abstract onDragEnd(e: IInteractionTarget): void; - protected abstract createFeature(e?: any): FeatureCollection; + protected abstract createFeature(e?: any): Feature; - protected abstract moveFeature(e: ILngLat): Feature; + protected abstract moveFeature(e: ILngLat): void; - protected abstract editFeature(e: any): FeatureCollection; + protected abstract editFeature(e: any): void; protected abstract hideOtherLayer(): void; @@ -95,20 +104,34 @@ export default abstract class DrawFeature extends DrawMode { case DrawModes.DIRECT_SELECT: this.editMode.enable(); this.editMode.setEditFeature(this.currentFeature as Feature); + this.drawRender.updateData( + featureCollection([this.currentFeature as Feature]), + ); + this.drawVertexLayer.updateData( + featureCollection(this.currentFeature?.properties?.pointFeatures), + ); this.drawVertexLayer.show(); this.drawVertexLayer.enableEdit(); + this.showOtherLayer(); break; case DrawModes.SIMPLE_SELECT: this.selectMode.setSelectedFeature(this.currentFeature as Feature); this.selectMode.enable(); this.drawRender.enableDrag(); + this.drawRender.updateData( + featureCollection([this.currentFeature as Feature]), + ); + this.drawVertexLayer.updateData( + featureCollection(this.currentFeature?.properties?.pointFeatures), + ); this.drawVertexLayer.disableEdit(); this.drawVertexLayer.show(); this.drawRender.show(); this.showOtherLayer(); break; case DrawModes.STATIC: - this.source.setFeatureUnActive(this.currentFeature as Feature); + this.source.updateFeature(this.currentFeature as Feature); + this.source.clearFeatureActive(); this.drawVertexLayer.hide(); this.drawVertexLayer.disableEdit(); this.hideOtherLayer(); @@ -120,10 +143,6 @@ export default abstract class DrawFeature extends DrawMode { private onDrawCreate = (feature: Feature) => { this.source.addFeature(feature); - if (this.popup) { - this.popup.remove(); - } - // this.removeDrawLayer(); }; private onDrawUpdate = (feature: Feature) => { diff --git a/packages/draw/src/modes/draw_line.ts b/packages/draw/src/modes/draw_line.ts index 98c3a4c74c..b41d5716ec 100644 --- a/packages/draw/src/modes/draw_line.ts +++ b/packages/draw/src/modes/draw_line.ts @@ -1,7 +1,7 @@ -import { IInteractionTarget, ILayer, ILngLat, Scene } from '@antv/l7'; -import { Feature, FeatureCollection, featureCollection } from '@turf/helpers'; -import { DrawEvent, DrawModes, unitsType } from '../util/constant'; -import { createLine } from '../util/create_geometry'; +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'; @@ -23,15 +23,16 @@ export default class DrawLine extends DrawPolygon { this.pointFeatures = newPointFeture; return this.currentFeature; } - protected createFeature(points: ILngLat[]): FeatureCollection { + protected createFeature(points: ILngLat[]): Feature { + const pointfeatures = createPoint(this.points); + this.pointFeatures = pointfeatures.features; const feature = createLine(points, { id: this.getUniqId(), type: 'line', + active: true, + pointFeatures: this.pointFeatures, }); this.setCurrentFeature(feature as Feature); - return { - type: 'FeatureCollection', - features: [feature], - }; + return feature; } } diff --git a/packages/draw/src/modes/draw_mode.ts b/packages/draw/src/modes/draw_mode.ts index d40fc62c9c..d8aa1f72c2 100644 --- a/packages/draw/src/modes/draw_mode.ts +++ b/packages/draw/src/modes/draw_mode.ts @@ -23,6 +23,7 @@ export default abstract class DrawMode extends EventEmitter { public source: DrawSource; public scene: Scene; public type: string; + public isEnable: boolean = false; protected options: { [key: string]: any; @@ -32,7 +33,6 @@ export default abstract class DrawMode extends EventEmitter { protected drawStatus: DrawStatus = 'Drawing'; protected currentFeature: Feature | null; protected currentVertex: Feature | null; - protected isEnable: boolean = false; protected popup: IPopup; constructor(scene: Scene, options: Partial = {}) { super(); @@ -80,6 +80,9 @@ export default abstract class DrawMode extends EventEmitter { public getCurrentVertex(feature: Feature) { return this.currentVertex; } + public getCurrentFeature() { + return this.currentVertex; + } public getOption(key: string) { return this.options[key]; @@ -94,15 +97,15 @@ export default abstract class DrawMode extends EventEmitter { } public setCursor(cursor: string) { - const container = this.scene.getContainer(); + const container = this.scene.getMapCanvasContainer(); if (container) { container.style.cursor = cursor; } } public resetCursor() { - const container = this.scene.getContainer(); + const container = this.scene.getMapCanvasContainer(); if (container) { - container.style.cursor = 'default'; + container.removeAttribute('style'); } } diff --git a/packages/draw/src/modes/draw_point.ts b/packages/draw/src/modes/draw_point.ts index 270aa0ac68..daacee625a 100644 --- a/packages/draw/src/modes/draw_point.ts +++ b/packages/draw/src/modes/draw_point.ts @@ -40,8 +40,8 @@ export default class DrawPoint extends DrawFeature { protected onClick = (e: any) => { const lngLat = e.lngLat; const feature = this.createFeature(lngLat); - this.drawRender.update(feature); - this.drawVertexLayer.update(feature); + this.drawRender.update(featureCollection([feature])); + this.drawVertexLayer.update(featureCollection([feature])); this.drawFinish(); }; @@ -53,19 +53,16 @@ export default class DrawPoint extends DrawFeature { this.pointFeatures = newFeature; return this.currentFeature; } - protected createFeature(p: ILngLat): FeatureCollection { + protected createFeature(p: ILngLat): Feature { const feature = point([p.lng, p.lat], { id: this.getUniqId(), }); this.setCurrentFeature(feature as Feature); - return { - type: 'FeatureCollection', - features: [feature], - }; + return feature; } - protected editFeature(endPoint: ILngLat): FeatureCollection { - return this.createFeature(endPoint); + protected editFeature(endPoint: ILngLat): void { + this.createFeature(endPoint); } protected showOtherLayer() { diff --git a/packages/draw/src/modes/draw_polygon.ts b/packages/draw/src/modes/draw_polygon.ts index 00a4a47f3a..cad20d3994 100644 --- a/packages/draw/src/modes/draw_polygon.ts +++ b/packages/draw/src/modes/draw_polygon.ts @@ -45,12 +45,15 @@ export default class DrawPolygon extends DrawFeature { public drawFinish() { const feature = this.createFeature(this.points); - this.drawRender.update(feature); - const pointfeatures = createPoint(this.points); - this.pointFeatures = pointfeatures.features; - this.drawVertexLayer.update(pointfeatures); + const properties = feature.properties as { pointFeatures: Feature[] }; + this.drawRender.update(featureCollection([feature])); + this.drawVertexLayer.update(featureCollection(properties.pointFeatures)); + // @ts-ignore + // feature.properties.pointFeatures = pointfeatures; + // console.log(feature); this.emit(DrawEvent.CREATE, this.currentFeature); this.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_SELECT); + this.points = []; this.disable(); } @@ -85,6 +88,8 @@ export default class DrawPolygon extends DrawFeature { this.drawRender.updateData(featureCollection([feature])); this.drawVertexLayer.updateData(pointfeatures); this.drawMidVertexLayer.updateData(featureCollection(this.pointFeatures)); + // @ts-ignore + feature.properties.pointFeatures = pointfeatures.features; this.setCurrentFeature(feature); } protected onDragStart = (e: IInteractionTarget) => { @@ -103,10 +108,11 @@ export default class DrawPolygon extends DrawFeature { this.endPoint = lngLat; this.points.push(lngLat); const feature = this.createFeature(this.points); - const pointfeatures = createPoint([this.points[0], this.endPoint]); - this.pointFeatures = pointfeatures.features; - this.drawRender.update(feature); - this.drawVertexLayer.update(pointfeatures); + const properties = feature.properties as { pointFeatures: Feature[] }; + // const pointfeatures = createPoint([this.points[0], this.endPoint]); + // this.pointFeatures = pointfeatures.features; + this.drawRender.update(featureCollection([feature])); + this.drawVertexLayer.update(featureCollection(properties.pointFeatures)); this.onDraw(); }; @@ -118,7 +124,7 @@ export default class DrawPolygon extends DrawFeature { const tmpPoints = this.points.slice(); tmpPoints.push(lngLat); const feature = this.createFeature(tmpPoints); - this.drawRender.update(feature); + this.drawRender.update(featureCollection([feature])); }; protected onDblClick = (e: any) => { @@ -130,29 +136,31 @@ export default class DrawPolygon extends DrawFeature { this.drawFinish(); }; - protected moveFeature(delta: ILngLat): Feature { + protected moveFeature(delta: ILngLat): void { const newFeature = moveFeatures([this.currentFeature as Feature], delta); const newPointFeture = moveFeatures(this.pointFeatures, delta); this.drawRender.updateData(featureCollection(newFeature)); this.drawVertexLayer.updateData(featureCollection(newPointFeture)); - this.currentFeature = newFeature[0]; - this.pointFeatures = newPointFeture; - return this.currentFeature; + newFeature[0].properties = { + ...newFeature[0].properties, + pointFeatures: newPointFeture, + }; + this.setCurrentFeature(newFeature[0]); } - protected createFeature(points: ILngLat[]): FeatureCollection { + protected createFeature(points: ILngLat[]): Feature { + const pointfeatures = createPoint(this.points); + this.pointFeatures = pointfeatures.features; const feature = createPolygon(points, { id: this.getUniqId(), type: 'polygon', active: true, + pointFeatures: this.pointFeatures, }); this.setCurrentFeature(feature as Feature); - return { - type: 'FeatureCollection', - features: [feature], - }; + return feature; } - protected editFeature(vertex: ILngLat): FeatureCollection { + protected editFeature(vertex: ILngLat) { const selectVertexed = this.currentVertex as Feature< Geometries, Properties @@ -161,7 +169,7 @@ export default class DrawPolygon extends DrawFeature { return featureCollection([]); } else { // @ts-ignore - const id = selectVertexed.properties.id; + const id = selectVertexed.properties.id * 1; selectVertexed.geometry.coordinates = [vertex.lng, vertex.lat]; // @ts-ignore this.pointFeatures[id].geometry.coordinates = [vertex.lng, vertex.lat]; @@ -171,9 +179,13 @@ export default class DrawPolygon extends DrawFeature { this.drawRender.updateData( featureCollection([this.currentFeature as Feature]), ); + const feature = this.currentFeature as Feature; + feature.properties = { + ...this.currentFeature?.properties, + pointFeatures: this.pointFeatures, + }; + this.setCurrentFeature(feature); } - - return featureCollection([]); } protected onDraw = () => { @@ -190,6 +202,10 @@ export default class DrawPolygon extends DrawFeature { }; protected showOtherLayer() { + // if (this.editMode.isEnable) { + // this.drawMidVertexLayer.update(featureCollection(this.pointFeatures)); + // this.drawMidVertexLayer.show(); + // } return null; } diff --git a/packages/draw/src/modes/draw_rect.ts b/packages/draw/src/modes/draw_rect.ts index 675c65e496..741f942627 100644 --- a/packages/draw/src/modes/draw_rect.ts +++ b/packages/draw/src/modes/draw_rect.ts @@ -6,7 +6,7 @@ import { point, } from '@turf/helpers'; import { unitsType } from '../util/constant'; -import { createRect } from '../util/create_geometry'; +import { createPoint, createRect } from '../util/create_geometry'; import DrawCircle from './draw_circle'; import { IDrawFeatureOption } from './draw_feature'; export interface IDrawRectOption extends IDrawFeatureOption { @@ -22,15 +22,17 @@ export default class DrawRect extends DrawCircle { return null; } - protected createFeature(): FeatureCollection { + 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: `${this.getUniqId()}`, + id, + pointFeatures: points.features, }, ); this.setCurrentFeature(feature as Feature); - return featureCollection([feature]); + return feature; } } diff --git a/packages/draw/src/modes/index.ts b/packages/draw/src/modes/index.ts index 026484d81f..3ef963b52c 100644 --- a/packages/draw/src/modes/index.ts +++ b/packages/draw/src/modes/index.ts @@ -1,6 +1,7 @@ import DrawCircle from './draw_circle'; 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, DrawRect, DrawPolygon, DrawPoint, DrawLine }; +export { DrawCircle, DrawRect, DrawPolygon, DrawPoint, DrawLine, DrawMode }; diff --git a/packages/draw/src/render/base_render.ts b/packages/draw/src/render/base_render.ts index f797d23b5d..0e5cc1a365 100644 --- a/packages/draw/src/render/base_render.ts +++ b/packages/draw/src/render/base_render.ts @@ -17,6 +17,9 @@ export default class BaseRenderLayer { 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); diff --git a/packages/draw/src/render/draw.ts b/packages/draw/src/render/draw.ts index 587aa7dd85..b251bdefe3 100644 --- a/packages/draw/src/render/draw.ts +++ b/packages/draw/src/render/draw.ts @@ -3,7 +3,7 @@ const InitFeature = { type: 'FeatureCollection', features: [], }; -import { FeatureCollection } from '@turf/helpers'; +import { Feature, FeatureCollection } from '@turf/helpers'; import Draw from '../modes/draw_feature'; import { DrawEvent, DrawModes } from '../util/constant'; import BaseRender from './base_render'; @@ -71,12 +71,16 @@ export default class DrawLayer extends BaseRender { this.disableDrag(); 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.disableDrag(); this.disableEdit(); this.hide(); diff --git a/packages/draw/src/render/draw_result.ts b/packages/draw/src/render/draw_result.ts index 9592f53cd3..a1eeb723d2 100644 --- a/packages/draw/src/render/draw_result.ts +++ b/packages/draw/src/render/draw_result.ts @@ -1,9 +1,13 @@ -import { FeatureCollection } from '@turf/helpers'; +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); @@ -11,12 +15,20 @@ export default class DrawResultLayer extends BaseRender { this.addLayers(); } public enableDrag() { + if (this.isEnableDrag) { + return; + } const layer = this.drawLayers[0]; layer.on('click', this.onClick); + this.isEnableDrag = true; } public disableDrag() { + if (!this.isEnableDrag) { + return; + } const layer = this.drawLayers[0]; layer.off('click', this.onClick); + this.isEnableDrag = false; } public addFilter() { this.drawLayers.forEach((layer) => @@ -26,9 +38,13 @@ export default class DrawResultLayer extends BaseRender { ); } private onClick = (e: any) => { + this.draw.source.setFeatureUnActive( + this.draw.getCurrentFeature() as Feature, + ); + // console.log(e.feature); this.draw.setCurrentFeature(e.feature); - this.draw.source.setFeatureActive(e.feature); - this.update(this.draw.source.data); + this.draw.source.setFeatureActive(e.feature as Feature); + this.updateData(this.draw.source.data); this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_SELECT); }; } diff --git a/packages/draw/src/source.ts b/packages/draw/src/source.ts index 88fe7ca1e9..f64268d9a7 100644 --- a/packages/draw/src/source.ts +++ b/packages/draw/src/source.ts @@ -34,6 +34,13 @@ export default class DrawSource { 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); diff --git a/packages/draw/src/util/create_geometry.ts b/packages/draw/src/util/create_geometry.ts index aeb2384be3..fca031f7e2 100644 --- a/packages/draw/src/util/create_geometry.ts +++ b/packages/draw/src/util/create_geometry.ts @@ -16,6 +16,7 @@ export function createCircle( units: unitsType; steps: number; id: string; + pointFeatures: Feature[]; }, ): Feature { const radius = turfDistance(point(center), point(endPoint), options); @@ -27,8 +28,14 @@ export function createCircle( active: true, type: 'circle', radius, - startPoint: center, - endPoint, + startPoint: { + lng: center[0], + lat: center[1], + }, + endPoint: { + lng: endPoint[0], + lat: endPoint[1], + }, path: [center, endPoint], }, }); @@ -40,6 +47,8 @@ export function createRect( endPoint: [number, number], options: { id: string; + pointFeatures: Feature[]; + [key: string]: any; }, ): Feature { const minX = Math.min(startPoint[0], endPoint[0]); @@ -51,8 +60,14 @@ export function createRect( properties: { type: 'rect', active: true, - startPoint, - endPoint, + startPoint: { + lng: startPoint[0], + lat: startPoint[1], + }, + endPoint: { + lng: endPoint[0], + lat: endPoint[1], + }, ...options, }, geometry: { @@ -73,7 +88,11 @@ export function createRect( export function createPolygon( points: Array<{ lng: number; lat: number }>, - options: any, + options: { + id?: string | number; + pointFeatures: Feature[]; + [key: string]: any; + }, ): any { const coords = points.map((p) => [p.lng, p.lat]); if (points.length < 2) { diff --git a/packages/maps/src/amap/map.ts b/packages/maps/src/amap/map.ts index 0bdfc7ef5d..caf655bcf6 100644 --- a/packages/maps/src/amap/map.ts +++ b/packages/maps/src/amap/map.ts @@ -108,6 +108,10 @@ export default class AMapService return this.map.getContainer(); } + public getMapCanvasContainer(): HTMLElement { + return this.map.getContainer() as HTMLElement; + } + public getSize(): [number, number] { const size = this.map.getSize(); return [size.getWidth(), size.getHeight()]; diff --git a/packages/maps/src/mapbox/logo.css b/packages/maps/src/mapbox/logo.css new file mode 100644 index 0000000000..f7731d89ca --- /dev/null +++ b/packages/maps/src/mapbox/logo.css @@ -0,0 +1,3 @@ +.mapboxgl-ctrl-logo { + display: none !important; +} diff --git a/packages/maps/src/mapbox/map.ts b/packages/maps/src/mapbox/map.ts index 08ec152edc..0e5cc36962 100644 --- a/packages/maps/src/mapbox/map.ts +++ b/packages/maps/src/mapbox/map.ts @@ -20,7 +20,11 @@ import { import { DOM } from '@antv/l7-utils'; import { inject, injectable } from 'inversify'; import mapboxgl, { IControl, Map } from 'mapbox-gl'; + +// tslint:disable-next-line:no-submodule-imports +import 'mapbox-gl/dist/mapbox-gl.css'; import { IMapboxInstance } from '../../typings/index'; +import './logo.css'; import Viewport from './Viewport'; const EventMap: { [key: string]: any; @@ -87,6 +91,9 @@ export default class MapboxService public getContainer(): HTMLElement | null { return this.map.getContainer(); } + public getMapCanvasContainer(): HTMLElement { + return this.map.getCanvasContainer(); + } public getSize(): [number, number] { const size = this.map.transform; @@ -293,7 +300,6 @@ export default class MapboxService if (this.map) { this.map.remove(); this.$mapContainer = null; - this.removeLogoControl(); } } public emit(name: string, ...args: any[]) { @@ -354,20 +360,6 @@ export default class MapboxService } return $wrapper; } - - private removeLogoControl(): void { - // @ts-ignore - const controls = this.map._controls as IControl[]; - const logoCtr = controls.find((ctr: IControl) => { - if (ctr.hasOwnProperty('_updateLogo')) { - return true; - } - }); - if (logoCtr) { - this.map.removeControl(logoCtr); - } - } - private getMapStyle(name: MapStyle) { if (typeof name !== 'string') { return name; diff --git a/packages/scene/src/index.ts b/packages/scene/src/index.ts index 73d97942ab..5936929499 100644 --- a/packages/scene/src/index.ts +++ b/packages/scene/src/index.ts @@ -118,6 +118,9 @@ class Scene public getMapContainer(): HTMLElement | null { return this.mapService.getMapContainer(); } + public getMapCanvasContainer(): HTMLElement { + return this.mapService.getMapCanvasContainer() as HTMLElement; + } public getMapService(): IMapService { return this.mapService; diff --git a/stories/Draw/Components/DrawControl.tsx b/stories/Draw/Components/DrawControl.tsx new file mode 100644 index 0000000000..f854d7ed9a --- /dev/null +++ b/stories/Draw/Components/DrawControl.tsx @@ -0,0 +1,55 @@ +import { Scene } from '@antv/l7'; +import { DrawControl } from '@antv/l7-draw'; +import { GaodeMap, Mapbox } from '@antv/l7-maps'; + +import * as React from 'react'; +export default class Circle extends React.Component { + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new Mapbox({ + pitch: 0, + style: 'mapbox://styles/mapbox/satellite-v9', // hosted style id + center: [-91.874, 42.76], // starting position + zoom: 12, // starting zoom + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + const drawControl = new DrawControl(scene, { + position: 'topright', + layout: 'vertical', // horizontal vertical + controls: { + point: true, + polygon: true, + line: true, + circle: true, + rect: true, + }, + }); + scene.addControl(drawControl); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/Draw/Draw.stories.tsx b/stories/Draw/Draw.stories.tsx index 1dcf0e3b75..e8740eba05 100644 --- a/stories/Draw/Draw.stories.tsx +++ b/stories/Draw/Draw.stories.tsx @@ -2,6 +2,7 @@ import { storiesOf } from '@storybook/react'; import * as React from 'react'; import Circle from './Components/Circle'; import DrawCircle from './Components/DrawCircle'; +import DrawControl from './Components/DrawControl'; import Line from './Components/DrawLine'; import Point from './Components/DrawPoint'; import DrawPolygon from './Components/DrawPolygon'; @@ -14,5 +15,6 @@ storiesOf('绘制', module) .add('多边形', () => , {}) .add('点', () => , {}) .add('路径', () => , {}) + .add('绘制组件', () => , {}) .add('绘制圆', () => , {}) .add('绘制面', () => , {});