Merge pull request #265 from antvis/l7-draw

feat: add draw point line polygon
This commit is contained in:
@thinkinggis 2020-04-03 10:53:58 +08:00 committed by GitHub
commit 2490013ed8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 2408 additions and 806 deletions

View File

@ -238,7 +238,7 @@ layer.color('white'); // 指定颜色
- `colors`: string | array | function
colors 的参数有以下情况:  如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定。对于颜色的分配顺序。
colors 的参数有以下情况:  如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定.
```javascript
layer.color('name'); // 使用默认的颜色

View File

@ -238,7 +238,7 @@ layer.color('white'); // 指定颜色
- `colors`: string | array | function
colors 的参数有以下情况:  如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定。对于颜色的分配顺序。
colors 的参数有以下情况:  如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定。
```javascript
layer.color('name'); // 使用默认的颜色

View File

@ -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;

View File

@ -4,8 +4,6 @@ import { merge } from 'lodash';
import { ILayerConfig } from '../layer/ILayerService';
import { IRenderConfig } from '../renderer/IRendererService';
import { IGlobalConfigService, ISceneConfig } from './IConfigService';
import mapConfigSchema from './mapConfigSchema';
import sceneConfigSchema from './sceneConfigSchema';
import WarnInfo, { IWarnInfo } from './warnInfo';
/**
@ -58,6 +56,8 @@ const defaultLayerConfig: Partial<ILayerConfig> = {
maxZoom: 24,
visible: true,
autoFit: false,
pickingBuffer: 0,
enablePropagation: false,
zIndex: 0,
blend: 'normal',
pickedFeatureID: -1,

View File

@ -1,6 +1,7 @@
import EventEmitter from 'eventemitter3';
import Hammer from 'hammerjs';
import { inject, injectable } from 'inversify';
// @ts-ignore
import { TYPES } from '../../types';
import { ILogService } from '../log/ILogService';
import { ILngLat, IMapService } from '../map/IMapService';
@ -58,10 +59,20 @@ export default class InteractionService extends EventEmitter
private addEventListenerOnMap() {
const $containter = this.mapService.getMapContainer();
Hammer.defaults.domEvents = true;
if ($containter) {
const hammertime = new Hammer.Manager($containter);
hammertime.add(new Hammer.Tap({ event: 'dblclick', taps: 2 }));
hammertime.add(new Hammer.Tap({ event: 'click' }));
hammertime.add(
new Hammer.Tap({
event: 'dblclick',
taps: 2,
}),
);
hammertime.add(
new Hammer.Tap({
event: 'click',
}),
);
hammertime.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
hammertime.add(new Hammer.Press({}));
// hammertime.get('pan').set({ direction: Hammer.DIRECTION_ALL });
@ -86,7 +97,7 @@ export default class InteractionService extends EventEmitter
const $containter = this.mapService.getMapContainer();
if ($containter) {
$containter.removeEventListener('mousemove', this.onHover);
this.hammertime.off('dblclick click', this.onHammer);
// this.hammertime.off('dblclick click', this.onHammer);
this.hammertime.off('panstart panmove panend pancancel', this.onDrag);
// $containter.removeEventListener('touchstart', this.onTouch);
// $containter.removeEventListener('click', this.onHover);
@ -102,9 +113,19 @@ export default class InteractionService extends EventEmitter
this.emit(InteractionEvent.Drag, interactionTarget);
};
private onHammer = (target: HammerInput) => {
target.srcEvent.stopPropagation();
const interactionTarget = this.interactionEvent(target);
this.emit(InteractionEvent.Hover, interactionTarget);
};
private onTouch = (target: TouchEvent) => {
const touch = target.touches[0];
// @ts-ignore
this.onHover({
x: touch.pageX,
y: touch.pageY,
type: 'touch',
});
};
private interactionEvent(target: HammerInput) {
const { type, pointerType } = target;
@ -147,7 +168,7 @@ export default class InteractionService extends EventEmitter
this.isDoubleTap(x, y, lngLat);
return;
}
if (type !== 'click' || type !== 'click') {
if (type !== 'click' && type !== 'dblclick') {
this.emit(InteractionEvent.Hover, {
x,
y,
@ -161,7 +182,7 @@ export default class InteractionService extends EventEmitter
const nowTime = new Date().getTime();
let type = 'click';
if (
nowTime - this.lastClickTime < 500 &&
nowTime - this.lastClickTime < 400 &&
Math.abs(this.lastClickXY[0] - x) < 10 &&
Math.abs(this.lastClickXY[1] - y) < 10
) {
@ -179,7 +200,7 @@ export default class InteractionService extends EventEmitter
this.clickTimer = setTimeout(() => {
type = 'click';
this.emit(InteractionEvent.Hover, { x, y, lngLat, type });
}, 500);
}, 400);
}
}
}

View File

@ -84,20 +84,21 @@ export default class PickingService implements IPickingService {
useFramebuffer(this.pickingFBO, () => {
const layers = this.layerService.getLayers();
layers
.filter((layer) => layer.needPick())
.filter((layer) => layer.needPick(target.type))
.reverse()
.forEach((layer) => {
.some((layer) => {
clear({
framebuffer: this.pickingFBO,
color: [0, 0, 0, 0],
stencil: 0,
depth: 1,
});
layer.hooks.beforePickingEncode.call();
layer.renderModels();
layer.hooks.afterPickingEncode.call();
this.pickFromPickingFBO(layer, target);
const isPicked = this.pickFromPickingFBO(layer, target);
return isPicked && !layer.getLayerConfig().enablePropagation;
// return false;
});
});
}
@ -105,6 +106,7 @@ export default class PickingService implements IPickingService {
layer: ILayer,
{ x, y, lngLat, type }: IInteractionTarget,
) => {
let isPicked = false;
const { getViewportSize, readPixels } = this.rendererService;
const { width, height } = getViewportSize();
const { enableHighlight, enableSelect } = layer.getLayerConfig();
@ -117,7 +119,7 @@ export default class PickingService implements IPickingService {
yInDevicePixel > height - 1 * window.devicePixelRatio ||
yInDevicePixel < 0
) {
return;
return false;
}
let pickedColors: Uint8Array | undefined;
pickedColors = readPixels({
@ -136,6 +138,13 @@ export default class PickingService implements IPickingService {
) {
const pickedFeatureIdx = decodePickingColor(pickedColors);
const rawFeature = layer.getSource().getFeatureById(pickedFeatureIdx);
if (
pickedFeatureIdx !== layer.getCurrentPickId() &&
type === 'mousemove'
) {
type = 'mouseenter';
}
const target = {
x,
y,
@ -150,15 +159,20 @@ export default class PickingService implements IPickingService {
// );
} else {
// trigger onHover/Click callback on layer
isPicked = true;
layer.setCurrentPickId(pickedFeatureIdx);
this.triggerHoverOnLayer(layer, target);
this.triggerHoverOnLayer(layer, target); // 触发拾取事件
}
} else {
// 未选中
const target = {
x,
y,
lngLat,
type: layer.getCurrentPickId() === null ? 'un' + type : 'mouseout',
type:
layer.getCurrentPickId() !== null && type === 'mousemove'
? 'mouseout'
: 'un' + type,
featureId: null,
feature: null,
};
@ -178,8 +192,19 @@ export default class PickingService implements IPickingService {
type === 'click' &&
pickedColors?.toString() !== [0, 0, 0, 0].toString()
) {
this.selectFeature(layer, pickedColors);
const selectedId = decodePickingColor(pickedColors);
if (
layer.getCurrentSelectedId() === null ||
selectedId !== layer.getCurrentSelectedId()
) {
this.selectFeature(layer, pickedColors);
layer.setCurrentSelectedId(selectedId);
} else {
this.selectFeature(layer, new Uint8Array([0, 0, 0, 0])); // toggle select
layer.setCurrentSelectedId(null);
}
}
return isPicked;
};
private triggerHoverOnLayer(
layer: ILayer,

View File

@ -84,7 +84,7 @@ export interface ILayer {
layerModelNeedUpdate: boolean;
layerModel: ILayerModel;
dataState: IDataState; // 数据流状态
pickedFeatureID: number;
pickedFeatureID: number | null;
hooks: {
init: SyncBailHook;
afterInit: SyncBailHook;
@ -106,12 +106,14 @@ export interface ILayer {
options?: ISourceCFG;
};
multiPassRenderer: IMultiPassRenderer;
needPick(): boolean;
needPick(type: string): boolean;
getLayerConfig(): Partial<ILayerConfig & ISceneConfig>;
getContainer(): Container;
setContainer(container: Container): void;
setCurrentPickId(id: number | null): void;
getCurrentPickId(): number | null;
setCurrentSelectedId(id: number | null): void;
getCurrentSelectedId(): number | null;
prepareBuildModel(): void;
renderModels(): void;
buildModels(): void;
@ -221,6 +223,8 @@ export interface ILayerConfig {
maxZoom: number;
visible: boolean;
zIndex: number;
pickingBuffer: number;
enablePropagation: boolean;
autoFit: boolean;
fitBoundsOptions?: unknown;
name: string; //

View File

@ -52,11 +52,12 @@ export interface IMapService<RawMap = {}> {
getRotation(): number;
getBounds(): Bounds;
getMapContainer(): HTMLElement | null;
getMapCanvasContainer(): HTMLElement;
// control with raw map
setRotation(rotation: number): void;
zoomIn(): void;
zoomOut(): void;
zoomIn(option?: any, eventData?: any): void;
zoomOut(option?: any, eventData?: any): void;
panTo(p: Point): void;
panBy(pixel: Point): void;
fitBounds(bound: Bounds, fitBoundsOptions?: unknown): void;

View File

@ -130,7 +130,7 @@ export default class PixelPickingPass<
* TODO
*/
private pickFromPickingFBO = ({ x, y, lngLat, type }: IInteractionTarget) => {
if (!this.layer.isVisible() || !this.layer.needPick()) {
if (!this.layer.isVisible() || !this.layer.needPick(type)) {
return;
}
const {

View File

@ -5,6 +5,7 @@ uniform vec3 u_PickingColor : [0, 0, 0];
uniform vec4 u_HighlightColor : [0, 0, 0, 0];
uniform float u_PickingStage : 0.0;
uniform float u_PickingThreshold : 1.0;
uniform float u_PickingBuffer: 0.0;
#define PICKING_NONE 0.0
#define PICKING_ENCODE 1.0
@ -25,3 +26,7 @@ void setPickingColor(vec3 pickingColor) {
// Stores the picking color so that the fragment shader can render it during picking
v_PickingResult.rgb = pickingColor * COLOR_SCALE;
}
float setPickingSize(float x) {
return u_PickingStage == PICKING_ENCODE ? x + u_PickingBuffer : x;
}

View File

@ -33,6 +33,8 @@
"test": "jest"
},
"dependencies": {
"@turf/midpoint": "^5.1.5",
"@antv/l7-component": "^2.1.9",
"@antv/l7": "^2.1.9",
"@babel/runtime": "^7.7.7",
"@turf/circle": "^6.0.1",

View File

@ -0,0 +1,70 @@
.l7-control-draw {
border-radius: 4px;
background: #fff;
box-shadow: 0 0 0 1px rgba(0,0,0,.1);
display: flex;
a {
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;
}
a:not(:disabled):hover {
background-color: rgba(0, 0, 0, 0.05);
}
a: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');
}
.draw-delete {
background-image: url('https://gw.alipayobjects.com/zos/bmw-prod/0c9ba44b-aba3-4007-ba4e-ab815279886b.svg');
}
}
.horizontal {
flex-direction: row;
a:focus:first-child {
border-radius: 4px 0px 0px 4px;
}
a:focus:last-child {
border-radius: 0px 4px 4px 4px;
}
a+a {
border-left: 1px solid #eee;
}
}
.vertical {
flex-direction: column;
a:focus:first-child {
border-radius: 4px 4px 0 0;
}
a:focus:last-child {
border-radius: 0px 0px 4px 4px;
}
a+a {
border-top: 1px solid #eee;
}
}

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
id="svg5738"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="combine.svg">
<defs
id="defs5740">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4103"
id="linearGradient4184"
gradientUnits="userSpaceOnUse"
x1="3003"
y1="10"
x2="3017"
y2="10"
gradientTransform="translate(1,2.6171874e-6)" />
<linearGradient
inkscape:collect="always"
id="linearGradient4103">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop4105" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop4107" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="2.423006"
inkscape:cy="12.173165"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2078"
inkscape:window-height="1054"
inkscape:window-x="900"
inkscape:window-y="296"
inkscape:window-maximized="0"
showguides="false"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:object-paths="true"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-others="false"
inkscape:snap-nodes="false">
<inkscape:grid
type="xygrid"
id="grid5746"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
spacingx="0.5px"
spacingy="0.5px"
color="#0000ff"
opacity="0.05882353" />
</sodipodi:namedview>
<metadata
id="metadata5743">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1032.3622)">
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
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 "
transform="translate(0,1032.3622)"
id="rect9198" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
viewBox="0 0 20 20"
id="svg19167"
version="1.1"
inkscape:version="0.91+devel+osxmenu r12911"
sodipodi:docname="line.svg">
<defs
id="defs19169" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="12.898775"
inkscape:cy="9.5890152"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1280"
inkscape:window-height="751"
inkscape:window-x="0"
inkscape:window-y="23"
inkscape:window-maximized="0"
inkscape:object-nodes="true">
<inkscape:grid
type="xygrid"
id="grid19715" />
</sodipodi:namedview>
<metadata
id="metadata19172">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1032.3622)">
<path
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;enable-background:accumulate"
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"
id="rect6467"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
viewBox="0 0 20 20"
id="svg19167"
version="1.1"
inkscape:version="0.91+devel+osxmenu r12911"
sodipodi:docname="marker.svg">
<defs
id="defs19169" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="14.164253"
inkscape:cy="8.88572"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1280"
inkscape:window-height="751"
inkscape:window-x="208"
inkscape:window-y="190"
inkscape:window-maximized="0"
inkscape:object-nodes="true">
<inkscape:grid
type="xygrid"
id="grid19715" />
</sodipodi:namedview>
<metadata
id="metadata19172">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1032.3622)">
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
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"
id="path12561"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccssc" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
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"
id="path12563"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccsc" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
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"
id="path12568"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsccccscsc" />
<path
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
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 "
transform="translate(0,1032.3622)"
id="path17305" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
viewBox="0 0 20 20"
id="svg19167"
version="1.1"
inkscape:version="0.91+devel+osxmenu r12911"
sodipodi:docname="square.svg">
<defs
id="defs19169" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.313708"
inkscape:cx="11.681634"
inkscape:cy="9.2857143"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1280"
inkscape:window-height="751"
inkscape:window-x="0"
inkscape:window-y="23"
inkscape:window-maximized="0"
inkscape:object-nodes="true">
<inkscape:grid
type="xygrid"
id="grid19715" />
</sodipodi:namedview>
<metadata
id="metadata19172">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1032.3622)">
<path
inkscape:connector-curvature="0"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;enable-background:accumulate"
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"
id="rect7797"
sodipodi:nodetypes="cccccccccccccccccc" />
<circle
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60000002;marker:none;enable-background:accumulate"
id="path4364"
cx="6"
cy="1046.3622"
r="2" />
<circle
id="path4368"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60000002;marker:none;enable-background:accumulate"
cx="14"
cy="1046.3622"
r="2" />
<circle
id="path4370"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60000002;marker:none;enable-background:accumulate"
cx="6"
cy="1038.3622"
r="2" />
<circle
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60000002;marker:none;enable-background:accumulate"
id="path4372"
cx="14"
cy="1038.3622"
r="2" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
id="svg5738"
version="1.1"
inkscape:version="0.91+devel+osxmenu r12911"
sodipodi:docname="trash.svg"
viewBox="0 0 20 20">
<defs
id="defs5740" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="12.128184"
inkscape:cy="8.8461307"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1033"
inkscape:window-height="751"
inkscape:window-x="20"
inkscape:window-y="23"
inkscape:window-maximized="0"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true">
<inkscape:grid
type="xygrid"
id="grid5746"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata5743">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1032.3622)">
<path
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999982;marker:none;enable-background:accumulate"
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"
id="rect2439-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccccccccccccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
id="svg5738"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="uncombine.svg">
<defs
id="defs5740">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4103"
id="linearGradient4184"
gradientUnits="userSpaceOnUse"
x1="3003"
y1="10"
x2="3017"
y2="10"
gradientTransform="translate(1,2.6171874e-6)" />
<linearGradient
inkscape:collect="always"
id="linearGradient4103">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop4105" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop4107" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.313708"
inkscape:cx="-10.273946"
inkscape:cy="6.930344"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2078"
inkscape:window-height="1054"
inkscape:window-x="900"
inkscape:window-y="296"
inkscape:window-maximized="0"
showguides="false"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:object-paths="true"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-others="false"
inkscape:snap-nodes="false">
<inkscape:grid
type="xygrid"
id="grid5746"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
spacingx="0.5px"
spacingy="0.5px"
color="#0000ff"
opacity="0.05882353" />
</sodipodi:namedview>
<metadata
id="metadata5743">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1032.3622)">
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
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 "
transform="translate(0,1032.3622)"
id="rect9198" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -0,0 +1,142 @@
import { Control, IControlOption, PositionType, Scene } from '@antv/l7';
import { DOM } from '@antv/l7-utils';
import './css/draw.less';
import {
DrawCircle,
DrawDelete,
DrawFeature,
DrawLine,
DrawPoint,
DrawPolygon,
DrawRect,
} from './modes';
import { DrawEvent, DrawModes } from './util/constant';
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]: DrawFeature;
} = {};
private drawDelete: DrawDelete;
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,
},
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;
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'),
);
}
if (controls.delete) {
this.drawDelete = new DrawDelete(this.scene);
this.createButton(
'删除',
'draw-delete',
container,
this.onDeleteMode.bind(null, 'delete'),
);
}
// 监听组件 选中, 编辑
return container;
}
private createButton(
tile: string,
className: string,
container: HTMLElement,
fn: (...arg: any[]) => any,
) {
const link = DOM.create('a', className, container) as HTMLLinkElement;
link.href = 'javascript:void(0)';
link.title = tile;
link.addEventListener('mousedown', fn, true);
return link;
}
private onButtonClick = (type: string, e: MouseEvent) => {
e.stopPropagation();
for (const draw in this.draw) {
if (draw === type) {
this.draw[draw].enable();
this.currentDraw = this.draw[draw];
} else {
this.draw[draw].disable();
}
}
};
private onDeleteMode = (type: string, e: MouseEvent) => {
e.stopPropagation();
if (!this.currentDraw) {
return;
}
this.currentDraw.deleteMode.enable();
return false;
};
}

View File

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

View File

@ -1,96 +1,130 @@
import { IInteractionTarget, ILngLat, PointLayer, Scene } from '@antv/l7';
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';
Feature,
FeatureCollection,
featureCollection,
Geometries,
Properties,
} from '@turf/helpers';
import { DrawEvent, DrawModes, unitsType } from '../util/constant';
import { createCircle } from '../util/create_geometry';
import moveFeatures, { movePoint, moveRing } from '../util/move_featrues';
import { createCircle, createPoint } from '../util/create_geometry';
import moveFeatures, { movePoint } from '../util/move_featrues';
import DrawFeature, { IDrawFeatureOption } from './draw_feature';
export interface IDrawRectOption extends IDrawFeatureOption {
units: unitsType;
steps: number;
}
let CircleFeatureId = 0;
export default class DrawCircle extends DrawFeature {
private startPoint: ILngLat;
private endPoint: ILngLat;
protected startPoint: ILngLat;
protected endPoint: ILngLat;
protected pointFeatures: Feature[];
constructor(scene: Scene, options: Partial<IDrawRectOption> = {}) {
super(scene, options);
this.selectLayer = new selectRender(this);
this.type = 'circle';
}
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.initDrawFillLayer();
this.centerLayer.setData([this.startPoint]);
};
protected onDragging = (e: IInteractionTarget) => {
this.endPoint = e.lngLat;
const feature = this.createFeature();
this.updateDrawFillLayer(feature);
const feature = this.createFeature() as Feature<Geometries, Properties>;
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 {
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;
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));
const newStartPoint = movePoint(
[this.startPoint.lng, this.startPoint.lat],
delta,
);
this.startPoint = {
lat: startPoint[1],
lng: startPoint[0],
lat: newStartPoint[1],
lng: newStartPoint[0],
};
this.endPoint = {
lat: endPoint[1],
lng: endPoint[0],
newFeature[0].properties = {
...newFeature[0].properties,
startPoint: this.startPoint,
pointFeatures: newPointFeture,
};
return newFeature;
this.centerLayer.setData([this.startPoint]);
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: `${CircleFeatureId++}`,
id,
},
);
this.setCurrentFeature(feature as Feature);
return {
type: 'FeatureCollection',
features: [feature],
};
return feature;
}
protected editFeature(endPoint: ILngLat): FeatureCollection {
protected editFeature(endPoint: ILngLat): void {
this.endPoint = endPoint;
return this.createFeature();
const newFeature = 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();
}
protected hideOtherLayer() {
if (this.currentFeature) {
this.centerLayer.hide();
}
}
private initCenterLayer() {
const centerStyle = this.getStyle('active_point');
const centerStyle = this.getStyle('active').point;
const layer = new PointLayer()
.source([this.startPoint], {
parser: {

View File

@ -0,0 +1,38 @@
import { IInteractionTarget, ILngLat, Scene } from '@antv/l7';
import { Feature } from '@turf/helpers';
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;
steps: number;
}
export default class DrawDelete extends DrawFeature {
private endPoint: ILngLat;
// 绘制完成之后显示
constructor(scene: Scene, options: Partial<IDrawCircleOption> = {}) {
super(scene, options);
}
public enable() {
this.emit(DrawEvent.DELETE, '');
}
public disable() {
return null;
}
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,8 +1,5 @@
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 { IInteractionTarget, ILngLat, Scene } from '@antv/l7';
import { Feature } from '@turf/helpers';
import { DrawEvent } from '../util/constant';
import DrawFeature, { IDrawOption } from './draw_mode';
export type unitsType = 'degrees' | 'radians' | 'miles' | 'kilometers';
@ -18,7 +15,6 @@ export default class DrawEdit extends DrawFeature {
private center: ILngLat;
private endPoint: ILngLat;
// 绘制完成之后显示
private editLayer: EditRender;
constructor(scene: Scene, options: Partial<IDrawCircleOption> = {}) {
super(scene, options);
}
@ -46,6 +42,7 @@ export default class DrawEdit extends DrawFeature {
protected onDragEnd = () => {
this.emit(DrawEvent.UPDATE, null);
this.resetCursor();
this.disable();
};
protected onClick = () => {

View File

@ -1,31 +1,18 @@
import {
IInteractionTarget,
ILayer,
ILngLat,
IPopup,
LineLayer,
PointLayer,
PolygonLayer,
Popup,
Scene,
} from '@antv/l7';
import turfCircle from '@turf/circle';
import turfDistance from '@turf/distance';
import { IInteractionTarget, ILayer, ILngLat, Popup, Scene } from '@antv/l7';
import {
Feature,
FeatureCollection,
featureCollection,
point,
} from '@turf/helpers';
import EditLayer from '../render/edit';
import RenderLayer from '../render/render';
import SelectLayer from '../render/selected';
import DrawRender from '../render/draw';
import RenderLayer from '../render/draw_result';
import DrawVertexLayer from '../render/draw_vertex';
import { DrawEvent, DrawModes, unitsType } from '../util/constant';
import DrawDelete from './draw_delete';
import DrawEdit from './draw_edit';
import DrawMode, { IDrawOption } from './draw_mode';
import DrawSelected from './draw_selected';
let CircleFeatureId = 0;
export interface IDrawFeatureOption extends IDrawOption {
units: unitsType;
steps: number;
@ -38,9 +25,11 @@ export default abstract class DrawFeature extends DrawMode {
// 绘制完成之后显示
public selectMode: DrawSelected;
public editMode: DrawEdit;
public deleteMode: DrawDelete;
protected renderLayer: RenderLayer;
protected selectLayer: SelectLayer;
protected editLayer: EditLayer;
protected drawRender: DrawRender;
protected drawVertexLayer: DrawVertexLayer;
protected centerLayer: ILayer;
// 编辑过程中显示
@ -48,20 +37,60 @@ export default abstract class DrawFeature extends DrawMode {
protected drawLineLayer: ILayer;
constructor(scene: Scene, options: Partial<IDrawFeatureOption> = {}) {
super(scene, options);
this.drawRender = new DrawRender(this);
this.drawVertexLayer = new DrawVertexLayer(this);
this.renderLayer = new RenderLayer(this);
this.selectLayer = new SelectLayer(this);
this.editLayer = new EditLayer(this);
// 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);
}
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 deleteCurrentFeature() {
this.deleteMode.enable();
}
public disableLayer() {
// this.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
this.drawRender.disableDrag();
}
public enableLayer() {
this.drawRender.enableDrag();
}
public clear() {
this.drawRender.hide();
this.drawVertexLayer.hide();
this.hideOtherLayer();
this.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
}
public reset() {
this.drawRender.show();
this.drawVertexLayer.show();
this.showOtherLayer();
}
public addVertex(feature: Feature): void {
throw new Error('子类未实现该方法');
}
protected getDefaultOptions() {
return {
steps: 64,
@ -75,72 +104,15 @@ export default abstract class DrawFeature extends DrawMode {
protected abstract onDragEnd(e: IInteractionTarget): void;
protected abstract createFeature(e: ILngLat): 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 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 abstract hideOtherLayer(): void;
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]);
}
protected abstract showOtherLayer(): void;
private addDrawPopup(lnglat: ILngLat, dis: number) {
const popup = new Popup({
@ -156,34 +128,50 @@ export default abstract class DrawFeature extends DrawMode {
private onModeChange = (mode: DrawModes[any]) => {
switch (mode) {
case DrawModes.DIRECT_SELECT:
this.selectLayer.hide();
this.editMode.enable();
this.editMode.setEditFeature(this.currentFeature as Feature);
this.editLayer.updateData(
this.drawRender.updateData(
featureCollection([this.currentFeature as Feature]),
);
this.editLayer.show();
this.drawVertexLayer.updateData(
featureCollection(this.currentFeature?.properties?.pointFeatures),
);
this.drawVertexLayer.show();
this.drawVertexLayer.enableEdit();
this.showOtherLayer();
this.drawStatus = 'DrawEdit';
break;
case DrawModes.SIMPLE_SELECT:
this.renderLayer.updateData();
this.selectMode.setSelectedFeature(this.currentFeature as Feature);
this.selectLayer.updateData(
this.selectMode.enable();
this.drawRender.enableDrag();
this.drawRender.updateData(
featureCollection([this.currentFeature as Feature]),
);
this.selectLayer.show();
this.drawVertexLayer.updateData(
featureCollection(this.currentFeature?.properties?.pointFeatures),
);
this.drawVertexLayer.disableEdit();
this.drawVertexLayer.show();
this.drawRender.show();
this.showOtherLayer();
this.drawStatus = 'DrawSelected';
break;
case DrawModes.STATIC:
this.source.setFeatureUnActive(this.currentFeature as Feature);
this.renderLayer.updateData();
this.source.updateFeature(this.currentFeature as Feature);
this.source.clearFeatureActive();
this.drawVertexLayer.hide();
this.drawVertexLayer.disableEdit();
this.hideOtherLayer();
this.renderLayer.update(this.source.data);
this.renderLayer.enableDrag();
this.drawStatus = 'DrawFinish';
break;
}
};
private onDrawCreate = (feature: Feature) => {
this.source.addFeature(feature);
if (this.popup) {
this.popup.remove();
}
this.removeDrawLayer();
};
private onDrawUpdate = (feature: Feature) => {
@ -191,14 +179,21 @@ export default abstract class DrawFeature extends DrawMode {
};
private onDrawMove = (delta: ILngLat) => {
const feature = this.moveFeature(delta);
this.currentFeature = feature;
this.selectLayer.updateData(featureCollection([feature]));
this.moveFeature(delta);
};
private onDrawEdit = (endpoint: ILngLat) => {
const feature = this.editFeature(endpoint);
this.currentFeature = feature.features[0];
this.editLayer.updateData(feature);
this.editFeature(endpoint);
};
private onDrawDelete = () => {
if (this.drawStatus === 'DrawSelected') {
this.clear();
this.source.removeFeature(this.currentFeature as Feature);
this.renderLayer.update(this.source.data);
// this.reset();
}
// this.source.removeFeature(this.currentFeature as Feature
};
}

View File

@ -0,0 +1,38 @@
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 moveFeature(delta: ILngLat): Feature {
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;
}
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 feature;
}
}

View File

@ -1,7 +1,7 @@
import { IInteractionTarget, IPopup, Scene } from '@antv/l7';
import { Feature, FeatureCollection } from '@turf/helpers';
import { EventEmitter } from 'eventemitter3';
import { merge, throttle } from 'lodash';
import { merge } from 'lodash';
import DrawSource from '../source';
import LayerStyles from '../util/layerstyle';
@ -17,9 +17,14 @@ export type DrawStatus =
| 'DrawFinish'
| 'EditFinish';
let DrawFeatureId = 0;
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;
} = {
@ -27,7 +32,7 @@ export default abstract class DrawMode extends EventEmitter {
};
protected drawStatus: DrawStatus = 'Drawing';
protected currentFeature: Feature | null;
protected isEnable: boolean = false;
protected currentVertex: Feature | null;
protected popup: IPopup;
constructor(scene: Scene, options: Partial<IDrawOption> = {}) {
super();
@ -45,6 +50,7 @@ export default abstract class DrawMode extends EventEmitter {
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;
}
@ -56,7 +62,7 @@ export default abstract class DrawMode extends EventEmitter {
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.scene.off('click', this.onClick);
this.resetCursor();
// @ts-ignore
this.scene.map.dragPan.enable();
@ -67,23 +73,42 @@ export default abstract class DrawMode extends EventEmitter {
this.source.setFeatureActive(feature);
}
public setCurrentVertex(feature: Feature) {
this.currentVertex = feature;
}
public deleteCurrentFeature() {
throw new Error('子类未实现该方法');
}
public getCurrentVertex(feature: Feature) {
return this.currentVertex;
}
public getCurrentFeature() {
return this.currentVertex;
}
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.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');
}
}
@ -96,4 +121,8 @@ export default abstract class DrawMode extends EventEmitter {
protected abstract onDragging(e: IInteractionTarget): void;
protected abstract onDragEnd(e: IInteractionTarget): void;
protected onClick(e: IInteractionTarget): any {
return null;
}
}

View File

@ -0,0 +1,80 @@
import { IInteractionTarget, ILayer, ILngLat, Scene } from '@antv/l7';
import {
Feature,
FeatureCollection,
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 interface IDrawRectOption extends IDrawFeatureOption {
units: unitsType;
steps: number;
}
export default class DrawPoint extends DrawFeature {
protected pointFeatures: Feature[];
constructor(scene: Scene, options: Partial<IDrawRectOption> = {}) {
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 onDragStart = (e: IInteractionTarget) => {
return null;
};
protected onDragging = (e: IInteractionTarget) => {
return null;
};
protected onDragEnd = () => {
return null;
};
protected onClick = (e: any) => {
const lngLat = e.lngLat;
const feature = this.createFeature(lngLat);
this.drawRender.update(featureCollection([feature]));
this.drawVertexLayer.update(featureCollection([feature]));
this.drawFinish();
};
protected moveFeature(delta: ILngLat): Feature {
const newFeature = moveFeatures([this.currentFeature as Feature], delta);
this.drawRender.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): Feature {
const feature = point([p.lng, p.lat], {
id: this.getUniqId(),
pointFeatures: [point([p.lng, p.lat])],
});
this.setCurrentFeature(feature as Feature);
return feature;
}
protected editFeature(endPoint: ILngLat): void {
this.createFeature(endPoint);
}
protected showOtherLayer() {
return null;
}
protected hideOtherLayer() {
return null;
}
}

View File

@ -0,0 +1,250 @@
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.drawRender.update(featureCollection([feature]));
this.drawVertexLayer.update(featureCollection(properties.pointFeatures));
// @ts-ignore
// feature.properties.pointFeatures = pointfeatures;
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.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) => {
return null;
};
protected onDragging = (e: IInteractionTarget) => {
return null;
};
protected onDragEnd = () => {
return null;
};
protected onClick = (e: any) => {
const lngLat = e.lngLat;
this.endPoint = lngLat;
this.points.push(lngLat);
const feature = this.createFeature(this.points);
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();
};
protected onMouseMove = (e: any) => {
const lngLat = e.lngLat;
if (this.points.length === 0) {
return;
}
const tmpPoints = this.points.slice();
tmpPoints.push(lngLat);
const feature = this.createFeature(tmpPoints);
this.drawRender.update(featureCollection([feature]));
};
protected onDblClick = (e: any) => {
const 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.drawRender.updateData(featureCollection(newFeature));
this.drawVertexLayer.updateData(featureCollection(newPointFeture));
newFeature[0].properties = {
...newFeature[0].properties,
pointFeatures: newPointFeture,
};
this.setCurrentFeature(newFeature[0]);
}
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 feature;
}
protected editFeature(vertex: ILngLat) {
const selectVertexed = this.currentVertex as Feature<
Geometries,
Properties
>;
if (selectVertexed === null) {
return featureCollection([]);
} else {
// @ts-ignore
const id = selectVertexed.properties.id * 1;
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.drawRender.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;
}
}
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.drawRender.updateData(
featureCollection([this.currentFeature as Feature]),
);
}
}
/**
* draw
* select Polyon
* edit
*/

View File

@ -1,103 +1,38 @@
import { Scene } from '@antv/l7';
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';
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 interface IDrawRectOption extends IDrawFeatureOption {
units: unitsType;
steps: number;
}
export default class DrawRect extends DrawFeature {
private startPoint: ILngLat;
private endPoint: ILngLat;
export default class DrawRect extends DrawCircle {
constructor(scene: Scene, options: Partial<IDrawRectOption> = {}) {
super(scene, options);
this.selectLayer = new selectRender(this);
this.type = 'rect';
}
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;
public drawFinish() {
return null;
}
protected createFeature(): FeatureCollection {
const feature = creatRect(
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 {
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;
return feature;
}
}

View File

@ -9,10 +9,7 @@ import {
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/selected';
import { DrawEvent, DrawModes } from '../util/constant';
import moveFeatures from '../util/move_featrues';
import DrawFeature, { IDrawOption } from './draw_mode';
@ -29,7 +26,6 @@ export default class DrawSelect extends DrawFeature {
private center: ILngLat;
private dragStartPoint: ILngLat;
// 绘制完成之后显示
private editLayer: EditRender;
constructor(scene: Scene, options: Partial<IDrawCircleOption> = {}) {
super(scene, options);
// this.editLayer = new EditRender(this);
@ -37,11 +33,6 @@ export default class DrawSelect extends DrawFeature {
public setSelectedFeature(feature: Feature) {
this.currentFeature = feature;
// this.editLayer.updateData({
// type: 'FeatureCollection',
// features: [feature],
// });
// this.editLayer.show();
}
protected onDragStart = (e: IInteractionTarget) => {
@ -74,42 +65,4 @@ export default class DrawSelect extends DrawFeature {
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: `${this.currentFeature?.properties?.id}`,
active: true,
radius,
center,
endPoint,
},
});
this.currentFeature = feature as Feature;
return featureCollection([feature]);
}
private moveCircle(feature: Feature, delta: ILngLat) {
const preCenter = feature?.properties?.center as ILngLat;
const preEndPoint = feature?.properties?.endPoint as ILngLat;
const newCenter = {
lng: preCenter.lng + delta.lng,
lat: preCenter.lat + delta.lat,
};
const newEndPoint = {
lng: preEndPoint.lng + delta.lng,
lat: preEndPoint.lat + delta.lat,
};
const newCircle = this.createCircleData(newCenter, newEndPoint);
// this.centerLayer.setData([newCenter]);
this.editLayer.updateData(newCircle);
}
}

View File

@ -1,3 +1,18 @@
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, DrawRect };
export {
DrawCircle,
DrawFeature,
DrawRect,
DrawPolygon,
DrawPoint,
DrawLine,
DrawMode,
DrawDelete,
};

View File

@ -0,0 +1,60 @@
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 updateData(data: any) {
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,82 +1,89 @@
import {
IInteractionTarget,
ILayer,
ILngLat,
IPopup,
LineLayer,
PointLayer,
PolygonLayer,
Popup,
Scene,
} from '@antv/l7';
import { IInteractionTarget, ILayer, Scene } from '@antv/l7';
const InitFeature = {
type: 'FeatureCollection',
features: [],
};
import Draw from '../modes/draw_mode';
import { Feature, FeatureCollection } from '@turf/helpers';
import Draw from '../modes/draw_feature';
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();
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 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 enableDrag() {
this.show();
if (this.isEnableDrag) {
return;
}
const layer = this.drawLayers[0];
layer.on('mouseenter', this.onMouseMove);
layer.on('mouseout', this.onUnMouseMove);
layer.on('click', this.onClick);
layer.on('unmousedown', this.onUnClick);
this.isEnableDrag = true;
}
public updateData() {
this.lineLayer.setData(this.draw.source.data);
this.polygonLayer.setData(this.draw.source.data);
public disableDrag() {
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('unmousedown', this.onUnClick);
this.isEnableDrag = false;
}
public destroy() {
this.draw.scene.removeLayer(this.lineLayer);
this.draw.scene.removeLayer(this.polygonLayer);
public enableEdit() {
if (this.isEnableEdit) {
return;
}
const layer = this.drawLayers[0];
layer.on('unclick', this.onUnClick);
this.isEnableDrag = true;
}
public show() {
this.lineLayer.show();
this.polygonLayer.show();
public disableEdit() {
if (!this.isEnableEdit) {
return;
}
const layer = this.drawLayers[0];
layer.off('unclick', this.onUnClick);
this.isEnableDrag = false;
}
public hide() {
this.lineLayer.hide();
this.polygonLayer.hide();
}
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.disableDrag();
this.draw.resetCursor();
this.enableEdit();
this.draw.setCurrentFeature(e.feature);
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.DIRECT_SELECT);
};
private addLayerEvent() {
this.polygonLayer.on('click', (e) => {
this.draw.setCurrentFeature(e.feature);
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_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();
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
};
}

View File

@ -0,0 +1,74 @@
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');
// this.draw.editMode.enable();
};
private onMouseOut = (e: any) => {
this.draw.resetCursor();
// this.draw.editMode.disable();
};
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

@ -0,0 +1,64 @@
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 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 enableDelete() {
this.disableDrag();
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

@ -0,0 +1,53 @@
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 enableDrag() {
return;
}
public disableDrag() {
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,145 +0,0 @@
import {
IInteractionTarget,
ILayer,
ILngLat,
IPopup,
LineLayer,
PointLayer,
PolygonLayer,
Popup,
Scene,
} from '@antv/l7';
const InitFeature = {
type: 'FeatureCollection',
features: [],
};
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;
private centerLayer: ILayer;
private endPointLayer: ILayer;
private draw: Draw;
private currentFeature: Feature;
constructor(draw: Draw) {
this.draw = draw;
this.init();
}
public init() {
const style = this.draw.getStyle('active_fill');
const linestyle = this.draw.getStyle('active_line');
const centerStyle = this.draw.getStyle('active_point');
this.polygonLayer = new PolygonLayer()
.source(InitFeature)
.shape('fill')
.color(style.color)
.style(style.style);
this.lineLayer = new LineLayer()
.source(InitFeature)
.shape('line')
.size(linestyle.size)
.color(linestyle.color)
.style(linestyle.style);
this.centerLayer = new PointLayer({
zIndex: 3,
blend: 'normal',
})
.source([], {
parser: {
type: 'json',
x: 'lng',
y: 'lat',
},
})
.shape('circle')
.color(centerStyle.color)
.size(centerStyle.size)
.style(centerStyle.style);
this.endPointLayer = new PointLayer({
zIndex: 4,
blend: 'normal',
})
.source([], {
parser: {
type: 'json',
x: 'lng',
y: 'lat',
},
})
.shape('circle')
.color(centerStyle.color)
.size(centerStyle.size)
.style(centerStyle.style);
this.draw.scene.addLayer(this.polygonLayer);
this.draw.scene.addLayer(this.lineLayer);
this.draw.scene.addLayer(this.centerLayer);
this.draw.scene.addLayer(this.endPointLayer);
}
public updateData(data: any) {
if (this.currentFeature === undefined) {
this.addLayerEvent();
}
this.currentFeature = data.features[0];
this.lineLayer.setData(data);
this.polygonLayer.setData(data);
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() {
this.draw.scene.removeLayer(this.lineLayer);
this.draw.scene.removeLayer(this.polygonLayer);
this.draw.scene.removeLayer(this.centerLayer);
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.editMode.enable();
});
this.endPointLayer.on('unmousemove', (e) => {
this.draw.resetCursor();
this.draw.editMode.disable();
});
this.polygonLayer.on('unclick', (e) => {
// 取消选中 回到初始态
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
this.draw.editMode.disable();
this.hide();
});
}
}

View File

@ -0,0 +1,62 @@
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()
.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,149 +0,0 @@
import {
IInteractionTarget,
ILayer,
ILngLat,
IPopup,
LineLayer,
PointLayer,
PolygonLayer,
Popup,
Scene,
} from '@antv/l7';
const InitFeature = {
type: 'FeatureCollection',
features: [],
};
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;
private centerLayer: ILayer;
private endPointLayer: ILayer;
private draw: Draw;
private currentFeature: Feature;
constructor(draw: Draw) {
this.draw = draw;
this.init();
}
public init() {
const style = this.draw.getStyle('active_fill');
const linestyle = this.draw.getStyle('active_line');
const centerStyle = this.draw.getStyle('active_point');
this.polygonLayer = new PolygonLayer()
.source(InitFeature)
.shape('fill')
.color(style.color)
.style(style.style);
this.lineLayer = new LineLayer()
.source(InitFeature)
.shape('line')
.size(linestyle.size)
.color(linestyle.color)
.style(linestyle.style);
this.centerLayer = new PointLayer({
zIndex: 3,
blend: 'normal',
})
.source([], {
parser: {
type: 'json',
x: 'lng',
y: 'lat',
},
})
.shape('circle')
.color(centerStyle.color)
.size(centerStyle.size)
.style(centerStyle.style);
this.endPointLayer = new PointLayer({
zIndex: 4,
blend: 'normal',
})
.source([], {
parser: {
type: 'json',
x: 'lng',
y: 'lat',
},
})
.shape('circle')
.color(centerStyle.color)
.size(centerStyle.size)
.style(centerStyle.style);
this.draw.scene.addLayer(this.polygonLayer);
this.draw.scene.addLayer(this.lineLayer);
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);
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() {
this.draw.scene.removeLayer(this.lineLayer);
this.draw.scene.removeLayer(this.polygonLayer);
// 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.selectMode.enable();
});
this.polygonLayer.on('unmousemove', (e) => {
this.draw.resetCursor();
this.draw.selectMode.disable();
});
this.polygonLayer.on('click', (e) => {
// 进入编辑态
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();
});
}
}

View File

@ -28,12 +28,20 @@ export default class DrawSource {
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);

View File

@ -1,6 +1,12 @@
import turfCircle from '@turf/circle';
import turfDistance from '@turf/distance';
import { Feature, featureCollection, point } from '@turf/helpers';
import {
Feature,
featureCollection,
lineString,
point,
polygon,
} from '@turf/helpers';
import { unitsType } from './constant';
export function createCircle(
@ -10,6 +16,7 @@ export function createCircle(
units: unitsType;
steps: number;
id: string;
pointFeatures: Feature[];
},
): Feature {
const radius = turfDistance(point(center), point(endPoint), options);
@ -17,20 +24,32 @@ export function createCircle(
units: options.units,
steps: options.steps,
properties: {
id: options.id,
...options,
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],
},
});
return feature as Feature;
}
export function creatRect(
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]);
@ -39,9 +58,17 @@ export function creatRect(
const feature = {
type: 'Feature',
properties: {
type: 'rect',
active: true,
startPoint,
endPoint,
startPoint: {
lng: startPoint[0],
lat: startPoint[1],
},
endPoint: {
lng: endPoint[0],
lat: endPoint[1],
},
...options,
},
geometry: {
type: 'Polygon',
@ -58,3 +85,44 @@ export function creatRect(
};
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 }>) {
const features = points.map((p, index) =>
point([p.lng, p.lat], {
active: true,
id: index.toString(),
}),
);
return featureCollection(features);
}

View File

@ -1,20 +1,71 @@
const LayerStyles = {
// 正常显示样式
normal_fill: {
type: 'PolygonLayer',
shape: 'fill',
color: '#3bb2d0',
style: {
opacity: 0.1,
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],
},
},
},
// xai'm'z
active_fill: {
type: 'PolygonLayer',
shape: 'fill',
color: '#fbb03b',
style: {
opacity: 0.1,
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: {
@ -28,40 +79,12 @@ const LayerStyles = {
},
},
mid_point: {
type: 'PointLayer',
shape: 'circle',
color: '#fbb03b',
size: 3,
style: {},
},
active_point: {
type: 'PointLayer',
shape: 'circle',
color: '#fbb03b',
size: 5,
style: {
stroke: '#fff',
strokeWidth: 2,
},
},
normal_line: {
type: 'LineLayer',
shape: 'line',
size: 1,
color: '#3bb2d0',
style: {
opacity: 1,
},
},
active_line: {
type: 'LineLayer',
shape: 'line',
color: '#fbb03b',
size: 1,
style: {
opacity: 1,
lineType: 'dash',
dashArray: [2, 2],
point: {
type: 'PointLayer',
shape: 'circle',
color: '#fbb03b',
size: 3,
style: {},
},
},
};

View File

@ -66,7 +66,8 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
public maxZoom: number;
public inited: boolean = false;
public layerModelNeedUpdate: boolean = false;
public pickedFeatureID: number = -1;
public pickedFeatureID: number | null = null;
public selectedFeatureID: number | null = null;
public dataState: IDataState = {
dataSourceNeedUpdate: false,
@ -612,6 +613,14 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
public getCurrentPickId(): number | null {
return this.currentPickId;
}
public setCurrentSelectedId(id: number) {
this.selectedFeatureID = id;
}
public getCurrentSelectedId(): number | null {
return this.selectedFeatureID;
}
public isVisible(): boolean {
const zoom = this.mapService.getZoom();
const {
@ -834,18 +843,28 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
return this.layerService.clock.getElapsedTime() - this.animateStartTime;
}
public needPick(): boolean {
public needPick(type: string): boolean {
const {
enableHighlight = true,
enableSelect = true,
} = this.getLayerConfig();
const eventNames = this.eventNames().filter((name) => {
return (
name !== 'inited' && name !== 'add' && name !== 'remove' && 'dataupdate' // 非拾取事件排除
);
});
const flag = eventNames.length > 0 || enableHighlight || enableSelect;
return this.isVisible() && flag;
// 判断layer是否监听事件;
let isPick =
this.eventNames().indexOf(type) !== -1 ||
this.eventNames().indexOf('un' + type) !== -1;
if ((type === 'click' || type === 'dblclick') && enableSelect) {
isPick = true;
}
if (
type === 'mousemove' &&
(enableHighlight ||
this.eventNames().indexOf('mouseenter') !== -1 ||
this.eventNames().indexOf('unmousemove') !== -1 ||
this.eventNames().indexOf('mouseout') !== -1)
) {
isPick = true;
}
return this.isVisible() && isPick;
}
public buildModels() {

View File

@ -49,7 +49,7 @@ vec2 getExtrusionOffset(vec2 line_clipspace, float offset_direction) {
vec2 dir_screenspace = normalize(line_clipspace);
// rotate by 90 degrees
dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x);
vec2 offset = dir_screenspace * offset_direction * a_Size / 2.0;
vec2 offset = dir_screenspace * offset_direction * setPickingSize(a_Size) / 2.0;
return offset * vec2(1.0, -1.0);
}
vec2 getNormal(vec2 line_clipspace, float offset_direction) {

View File

@ -51,7 +51,7 @@ vec2 getExtrusionOffset(vec2 line_clipspace, float offset_direction) {
// rotate by 90 degrees
dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x);
vec2 offset = dir_screenspace * offset_direction * a_Size / 2.0;
vec2 offset = dir_screenspace * offset_direction * setPickingSize(a_Size) / 2.0;
return offset;
}

View File

@ -49,7 +49,7 @@ vec2 getExtrusionOffset(vec2 line_clipspace, float offset_direction) {
vec2 dir_screenspace = normalize(line_clipspace);
// rotate by 90 degrees
dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x);
vec2 offset = dir_screenspace * offset_direction * a_Size / 2.0;
vec2 offset = dir_screenspace * offset_direction * setPickingSize(a_Size)/ 2.0;
return offset;
}
vec2 getNormal(vec2 line_clipspace, float offset_direction) {

View File

@ -48,7 +48,7 @@ vec2 getExtrusionOffset(vec2 line_clipspace, float offset_direction) {
vec2 dir_screenspace = normalize(line_clipspace);
// rotate by 90 degrees
dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x);
vec2 offset = dir_screenspace * offset_direction * a_Size / 2.0;
vec2 offset = dir_screenspace * offset_direction * setPickingSize(a_Size) / 2.0;
return offset * vec2(1.0, -1.0);
}
vec2 getNormal(vec2 line_clipspace, float offset_direction) {

View File

@ -29,7 +29,7 @@ void main() {
v_normal = vec2(reverse_offset_normal(a_Normal) * sign(a_Miter));
v_color = a_Color;
vec3 size = a_Miter * a_Size * reverse_offset_normal(a_Normal); //v_normal * vec3(1., -1., 1.0);
vec3 size = a_Miter * setPickingSize(a_Size) * reverse_offset_normal(a_Normal); //v_normal * vec3(1., -1., 1.0);
vec2 offset = project_pixel(size.xy);
vec4 project_pos = project_position(vec4(a_Position.xy, 0, 1.0));
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, 0, 1.0));

View File

@ -38,7 +38,7 @@ void main() {
}
v_normal = vec2(reverse_offset_normal(a_Normal) * sign(a_Miter));
v_color = a_Color;
vec3 size = a_Miter * a_Size.x * reverse_offset_normal(a_Normal);
vec3 size = a_Miter * setPickingSize(a_Size.x) * reverse_offset_normal(a_Normal);
vec2 offset = project_pixel(size.xy);
v_side = a_Miter * a_Size.x;
vec4 project_pos = project_position(vec4(a_Position.xy, 0, 1.0));

View File

@ -55,6 +55,7 @@ export default class ShaderUniformPlugin implements ILayerPlugin {
u_ViewportSize: [width, height],
u_DevicePixelRatio: window.devicePixelRatio,
u_ModelMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
u_PickingBuffer: layer.getLayerConfig().pickingBuffer || 0,
}),
);

View File

@ -55,12 +55,6 @@ void main() {
}
float opacity_t = smoothstep(0.0, antialiased_blur, outer_df);
if(u_stroke_width <0.01 ) {
gl_FragColor = v_color * opacity_t;
gl_FragColor.a = gl_FragColor.a * u_opacity;
gl_FragColor = filterColor(gl_FragColor);
return;
}
float color_t = u_stroke_width < 0.01 ? 0.0 : smoothstep(
antialiased_blur,
0.0,
@ -73,8 +67,8 @@ void main() {
// gl_FragColor = v_color * color_t;
// gl_FragColor = mix(vec4(v_color.rgb, v_color.a * u_opacity), strokeColor * u_stroke_opacity, color_t);
gl_FragColor = opacity_t * mix(vec4(v_color.rgb, v_color.a * u_opacity), strokeColor * u_stroke_opacity, color_t);
gl_FragColor = mix(vec4(v_color.rgb, v_color.a * u_opacity), strokeColor * u_stroke_opacity, color_t);
gl_FragColor.a = gl_FragColor.a * opacity_t;
if(u_aimate.x == Animate) {
float d = length(v_data.xy);
float intensity = clamp(cos(d * PI), 0.0, 1.0) * clamp(cos(2.0 * PI * (d * 2.0 * u_aimate.z - u_aimate.y * u_time)), 0.0, 1.0);

View File

@ -21,17 +21,19 @@ void main() {
float shape_type = a_Shape;
// radius(16-bit)
v_radius = a_Size;
float newSize = setPickingSize(a_Size);
vec2 offset = project_pixel(extrude * (a_Size + u_stroke_width));
// radius(16-bit)
v_radius = newSize;
vec2 offset = project_pixel(extrude * (newSize + u_stroke_width));
vec4 project_pos = project_position(vec4(a_Position.xy, 0.0, 1.0));
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, 0.0, 1.0));
// TODO: billboard
// anti-alias
float antialiasblur = 1.0 / (a_Size + u_stroke_width);
float antialiasblur = 1.0 / u_DevicePixelRatio / (newSize + u_stroke_width);
// construct point coords
v_data = vec4(extrude, antialiasblur,shape_type);

View File

@ -25,5 +25,6 @@ float r = 1.0 - smoothstep(radius-(radius*0.01),
}else {
gl_FragColor= step(0.01, textureColor.z) * v_color;
}
gl_FragColor.a =gl_FragColor.a * u_opacity;
gl_FragColor = filterColor(gl_FragColor);
}

View File

@ -29,6 +29,7 @@ void main() {
highp float gamma_scaled = gamma * v_gamma_scale;
highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist);
gl_FragColor = mix(vec4(v_color.rgb, v_color.a * u_opacity), vec4(u_stroke.rgb, u_stroke.a * u_opacity), smoothstep(0., 0.5, 1. - dist)) * alpha;
gl_FragColor = mix(vec4(v_color.rgb, v_color.a * u_opacity), vec4(u_stroke.rgb, u_stroke.a * u_opacity), smoothstep(0., 0.5, 1. - dist));
gl_FragColor.a= gl_FragColor.a * alpha;
gl_FragColor = filterColor(gl_FragColor);
}

View File

@ -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()];

View File

@ -0,0 +1,3 @@
.mapboxgl-ctrl-logo {
display: none !important;
}

View File

@ -20,14 +20,18 @@ 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;
} = {
mapmove: 'move',
camerachange: 'move',
zoomChange: 'zoom',
zoomchange: 'zoom',
dragging: 'drag',
};
import { MapTheme } from './theme';
@ -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;
@ -138,18 +145,16 @@ export default class MapboxService
this.map.setBearing(rotation);
}
public zoomIn(): void {
this.map.zoomIn();
public zoomIn(option?: any, eventData?: any): void {
this.map.zoomIn(option, eventData);
}
public zoomOut(option?: any, eventData?: any): void {
this.map.zoomOut(option, eventData);
}
public setPitch(pitch: number) {
return this.map.setPitch(pitch);
}
public zoomOut(): void {
this.map.zoomOut();
}
public panTo(p: [number, number]): void {
this.map.panTo(p);
}
@ -295,7 +300,6 @@ export default class MapboxService
if (this.map) {
this.map.remove();
this.$mapContainer = null;
this.removeLogoControl();
}
}
public emit(name: string, ...args: any[]) {
@ -356,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;

View File

@ -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<unknown> {
return this.mapService;

View File

@ -19,8 +19,8 @@ export function aggregatorToGrid(data: IParserData, option: ITransform) {
const { gridHash, gridOffset } = _pointsGridHash(dataArray, size);
const layerData = _getGridLayerDataFromGridHash(gridHash, gridOffset, option);
return {
yOffset: gridOffset.yOffset / 1.8,
xOffset: gridOffset.xOffset / 1.8,
yOffset: gridOffset.yOffset / 2,
xOffset: gridOffset.xOffset / 2,
radius: gridOffset.xOffset,
type: 'grid',
dataArray: layerData,
@ -31,6 +31,7 @@ function _pointsGridHash(dataArray: any[], size: number) {
let latMin = Infinity;
let latMax = -Infinity;
let pLat;
for (const point of dataArray) {
pLat = point.coordinates[1];
if (Number.isFinite(pLat)) {
@ -38,8 +39,8 @@ function _pointsGridHash(dataArray: any[], size: number) {
latMax = pLat > latMax ? pLat : latMax;
}
}
// const centerLat = (latMin + latMax) / 2;
const centerLat = 34.54083;
const centerLat = (latMin + latMax) / 2;
// const centerLat = 34.54083;
const gridOffset = _calculateGridLatLonOffset(size, centerLat);
if (gridOffset.xOffset <= 0 || gridOffset.yOffset <= 0) {
return { gridHash: {}, gridOffset };
@ -95,8 +96,8 @@ function _getGridLayerDataFromGridHash(
Object.assign(item, {
_id: i,
coordinates: [
-180 + gridOffset.xOffset * lonIdx,
-90 + gridOffset.yOffset * latIdx,
-180 + gridOffset.xOffset * (lonIdx + 0.5),
-90 + gridOffset.yOffset * (latIdx + 0.5),
],
rawData: gridHash[key].points,
count: gridHash[key].count,

View File

@ -24,7 +24,6 @@ export default class MarkerComponent extends React.Component {
zoom: 18,
}),
});
this.scene = scene;
const popup = new Popup({
offsets: [0, 20],
@ -90,6 +89,7 @@ export default class MarkerComponent extends React.Component {
// console.log(this.scene.getZoom());
// console.log('选中的点', 1111);
// });
this.scene = scene;
});
}

View File

@ -46,13 +46,14 @@ export default class ScaleComponent extends React.Component {
'#CF1D49',
])
.shape('fill')
// .select(true)
.select(true)
.style({
opacity: 1.0,
});
scene.addLayer(layer);
const pointLayer = new PointLayer({
name: '02',
enablePropagation: true,
})
.source(pointsData, {
cluster: true,
@ -63,7 +64,7 @@ export default class ScaleComponent extends React.Component {
})
.size('point_count', [5, 10, 15, 20, 25])
.animate(false)
.active(true)
.active(false)
.color('yellow')
.style({
opacity: 0.5,
@ -71,7 +72,14 @@ export default class ScaleComponent extends React.Component {
});
scene.addLayer(pointLayer);
layer.on('click', (e) => {
layer.setSelect(e.featureId);
console.log(1, e);
// layer.setSelect(e.featureId);
});
pointLayer.on('click', (e) => {
console.log(2, e);
});
pointLayer.on('mouseout', (e) => {
console.log(2, e);
});
const scaleControl = new Scale();
const layers = {

View File

@ -0,0 +1,57 @@
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: 'horizontal', // horizontal vertical
controls: {
point: true,
polygon: true,
line: true,
circle: true,
rect: true,
delete: true,
},
});
scene.on('click', () => {});
scene.addControl(drawControl);
});
}
public render() {
return (
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
);
}
}

View File

@ -0,0 +1,45 @@
import { LineLayer, PointLayer, PolygonLayer, Popup, Scene } from '@antv/l7';
import { DrawLine } 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: 'light',
center: [113.775374, 28.31067],
zoom: 12,
}),
});
this.scene = scene;
scene.on('loaded', () => {
const drawLine = new DrawLine(scene);
drawLine.enable();
});
}
public render() {
return (
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
);
}
}

View File

@ -0,0 +1,45 @@
import { LineLayer, PointLayer, PolygonLayer, Popup, Scene } from '@antv/l7';
import { DrawPoint } 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: 'light',
center: [113.775374, 28.31067],
zoom: 12,
}),
});
this.scene = scene;
scene.on('loaded', () => {
const drawPoint = new DrawPoint(scene);
drawPoint.enable();
});
}
public render() {
return (
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
);
}
}

View File

@ -0,0 +1,45 @@
import { LineLayer, PointLayer, PolygonLayer, Popup, Scene } from '@antv/l7';
import { DrawPolygon } 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: 'light',
center: [113.775374, 28.31067],
zoom: 12,
}),
});
this.scene = scene;
scene.on('loaded', () => {
const drawPolygon = new DrawPolygon(scene);
drawPolygon.enable();
});
}
public render() {
return (
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
);
}
}

View File

@ -2,11 +2,19 @@ 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';
import DrawRect from './Components/DrawRect';
import Polygon from './Components/Polygon';
storiesOf('绘制', module)
.add('圆', () => <Circle />, {})
.add('矩形', () => <DrawRect />, {})
.add('多边形', () => <Polygon />, {})
.add('点', () => <Point />, {})
.add('路径', () => <Line />, {})
.add('绘制组件', () => <DrawControl />, {})
.add('绘制圆', () => <DrawCircle />, {})
.add('四边形', () => <DrawRect />, {})
.add('绘制面', () => <DrawPolygon />, {});

View File

@ -21,6 +21,7 @@ import WorldDemo from './components/polygon_line';
import ImageLayerDemo from './components/RasterImage';
import RasterLayerDemo from './components/RasterLayer';
import TextLayerDemo from './components/Text';
import GridTest from './components/gridtest';
// @ts-ignore
storiesOf('图层', module)
@ -44,4 +45,5 @@ storiesOf('图层', module)
.add('网格热力图', () => <HexagonLayerDemo />)
.add('栅格', () => <RasterLayerDemo />)
.add('图片', () => <ImageLayerDemo />)
.add('网格测试', () => <GridTest />)
.add('世界地图', () => <WorldDemo />);

View File

@ -18,7 +18,7 @@ export default class Point3D extends React.Component {
style: 'light',
center: [-121.24357, 37.58264],
pitch: 0,
zoom: 6.45,
zoom: 10.45,
}),
});
scene.on('loaded', () => {
@ -53,6 +53,7 @@ export default class Point3D extends React.Component {
.style({
opacity: 1,
strokeWidth: 0,
stroke: '#fff',
});
scene.addLayer(pointLayer);

View File

@ -23,7 +23,7 @@ export default class TextLayerDemo extends React.Component {
const scene = new Scene({
id: 'map',
map: new Mapbox({
map: new GaodeMap({
center: [120.19382669582967, 30.258134],
pitch: 0,
style: 'dark',
@ -41,7 +41,7 @@ export default class TextLayerDemo extends React.Component {
})
.shape('s', 'text')
// .shape('circle')
.size(8)
.size(18)
.filter('t', (t) => {
return t < 5;
})
@ -54,7 +54,7 @@ export default class TextLayerDemo extends React.Component {
// spacing: 2, // 字符间距
// padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
stroke: '#fff', // 描边颜色
strokeWidth: 0, // 描边宽度
strokeWidth: 1, // 描边宽度
// strokeOpacity: 1.0,
});
scene.addLayer(pointLayer);

View File

@ -23,7 +23,9 @@ export default class DashLineDemo extends React.Component {
zoom: 14,
}),
});
const lineLayer = new LineLayer()
const lineLayer = new LineLayer({
pickingBuffer: 5,
})
.source(await response.json())
.size(1)
.shape('line')

View File

@ -0,0 +1,76 @@
import { HeatmapLayer, Marker, PointLayer, Scene, IPoint } from '@antv/l7';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import * as dat from 'dat.gui';
import * as React from 'react';
export default class HexagonLayerDemo extends React.Component {
// @ts-ignore
private scene: Scene;
private gui: dat.GUI;
public componentWillUnmount() {
this.scene.destroy();
if (this.gui) {
this.gui.destroy();
}
}
public async componentDidMount() {
const testPoint: [number, number] = [113.868222, 22.506306];
const scene = new Scene({
id: 'map',
map: new GaodeMap({
center: testPoint,
pitch: 0,
zoom: 17,
token: '8e2254ff173dbf7ff5029e9c9df20bc3',
}),
});
scene.on('loaded', () => {
// 网格热力图
const testList = [{ lng: testPoint[0], lat: testPoint[1], lev: 1 }];
const layer = new HeatmapLayer({})
.source(testList, {
parser: {
type: 'json',
x: 'lng',
y: 'lat',
},
transforms: [
{
type: 'grid',
size: 100,
field: 'lev',
method: 'sum',
},
],
})
.shape('circle')
.style({
coverage: 1,
})
.color('count', ['#0B0030', '#6BD5A0'].reverse());
scene.addLayer(layer);
// marker
// @ts-ignore
const marker = new Marker().setLnglat(testPoint);
scene.addMarker(marker);
});
}
public render() {
return (
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
);
}
}

View File

@ -22,7 +22,7 @@ export default class HeatMapLayerDemo extends React.Component {
pitch: 58.5,
center: [111.8759, 30.6942],
rotation: 0.519,
zoom: 3.6116,
zoom: 14,
}),
});
scene.on('loaded', () => {

View File

@ -36,14 +36,14 @@ export default class HexagonLayerDemo extends React.Component {
.source(data, {
transforms: [
{
type: 'hexagon',
type: 'grid',
size: 500000,
field: 'name',
method: 'mode',
},
],
})
.shape('hexagon') // 支持 circle, hexagon,triangle
.shape('square') // 支持 circle, hexagon,triangle
.color('mode', [
'#ffffe5',
'#fff7bc',

View File

@ -34,12 +34,13 @@ export default class World extends React.Component {
style: 'blank',
center: [110.19382669582967, 30.258134],
pitch: 0,
zoom: 0,
zoom: 5,
}),
});
this.scene = scene;
const layer = new PolygonLayer({
name: '01',
autoFit: true,
});
layer