mirror of https://gitee.com/antv-l7/antv-l7
feat: add drag event
This commit is contained in:
parent
896ce3ca98
commit
c65927df50
|
@ -1,2 +1,10 @@
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export * from '@antv/l7';
|
export * from '@antv/l7';
|
||||||
|
// import * as L7 from '@antv/l7';
|
||||||
|
// export default L7;
|
||||||
|
|
||||||
|
// import { Scene } from '@antv/l7';
|
||||||
|
// // export { Scene };
|
||||||
|
// export default {
|
||||||
|
// Scene,
|
||||||
|
// };
|
||||||
|
|
|
@ -4,6 +4,7 @@ export enum InteractionEvent {
|
||||||
Click = 'click',
|
Click = 'click',
|
||||||
Select = 'select',
|
Select = 'select',
|
||||||
Active = 'active',
|
Active = 'active',
|
||||||
|
Drag = 'drag',
|
||||||
}
|
}
|
||||||
export interface IInteractionTarget {
|
export interface IInteractionTarget {
|
||||||
x: number;
|
x: number;
|
||||||
|
|
|
@ -5,6 +5,12 @@ import { TYPES } from '../../types';
|
||||||
import { ILogService } from '../log/ILogService';
|
import { ILogService } from '../log/ILogService';
|
||||||
import { ILngLat, IMapService } from '../map/IMapService';
|
import { ILngLat, IMapService } from '../map/IMapService';
|
||||||
import { IInteractionService, InteractionEvent } from './IInteractionService';
|
import { IInteractionService, InteractionEvent } from './IInteractionService';
|
||||||
|
const DragEventMap: { [key: string]: string } = {
|
||||||
|
panstart: 'dragstart',
|
||||||
|
panmove: 'dragging',
|
||||||
|
panend: 'dragend',
|
||||||
|
pancancel: 'dragcancle',
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* 由于目前 L7 与地图结合的方案为双 canvas 而非共享 WebGL Context,事件监听注册在地图底图上。
|
* 由于目前 L7 与地图结合的方案为双 canvas 而非共享 WebGL Context,事件监听注册在地图底图上。
|
||||||
* 除此之外,后续如果支持非地图场景,事件监听就需要注册在 L7 canvas 上。
|
* 除此之外,后续如果支持非地图场景,事件监听就需要注册在 L7 canvas 上。
|
||||||
|
@ -61,7 +67,7 @@ export default class InteractionService extends EventEmitter
|
||||||
// hammertime.get('pan').set({ direction: Hammer.DIRECTION_ALL });
|
// hammertime.get('pan').set({ direction: Hammer.DIRECTION_ALL });
|
||||||
// hammertime.get('pinch').set({ enable: true });
|
// hammertime.get('pinch').set({ enable: true });
|
||||||
hammertime.on('dblclick click', this.onHammer);
|
hammertime.on('dblclick click', this.onHammer);
|
||||||
// hammertime.on('panstart panmove panend', this.onHammer);
|
hammertime.on('panstart panmove panend pancancel', this.onDrag);
|
||||||
// hammertime.on('press pressup', this.onHammer);
|
// hammertime.on('press pressup', this.onHammer);
|
||||||
// $containter.addEventListener('touchstart', this.onTouch);
|
// $containter.addEventListener('touchstart', this.onTouch);
|
||||||
$containter.addEventListener('mousemove', this.onHover);
|
$containter.addEventListener('mousemove', this.onHover);
|
||||||
|
@ -81,6 +87,7 @@ export default class InteractionService extends EventEmitter
|
||||||
if ($containter) {
|
if ($containter) {
|
||||||
$containter.removeEventListener('mousemove', this.onHover);
|
$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('touchstart', this.onTouch);
|
||||||
// $containter.removeEventListener('click', this.onHover);
|
// $containter.removeEventListener('click', this.onHover);
|
||||||
$containter.removeEventListener('mousedown', this.onHover);
|
$containter.removeEventListener('mousedown', this.onHover);
|
||||||
|
@ -89,16 +96,26 @@ export default class InteractionService extends EventEmitter
|
||||||
$containter.removeEventListener('contextmenu', this.onHover);
|
$containter.removeEventListener('contextmenu', this.onHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private onDrag = (target: HammerInput) => {
|
||||||
|
const interactionTarget = this.interactionEvent(target);
|
||||||
|
interactionTarget.type = DragEventMap[interactionTarget.type];
|
||||||
|
this.emit(InteractionEvent.Drag, interactionTarget);
|
||||||
|
};
|
||||||
private onHammer = (target: HammerInput) => {
|
private onHammer = (target: HammerInput) => {
|
||||||
|
const interactionTarget = this.interactionEvent(target);
|
||||||
|
this.emit(InteractionEvent.Hover, interactionTarget);
|
||||||
|
};
|
||||||
|
|
||||||
|
private interactionEvent(target: HammerInput) {
|
||||||
const { type, pointerType } = target;
|
const { type, pointerType } = target;
|
||||||
let clientX;
|
let clientX;
|
||||||
let clientY;
|
let clientY;
|
||||||
if (pointerType === 'touch') {
|
if (pointerType === 'touch') {
|
||||||
clientY = target.pointers[0].clientY;
|
clientY = Math.floor(target.pointers[0].clientY);
|
||||||
clientX = target.pointers[0].clientX;
|
clientX = Math.floor(target.pointers[0].clientX);
|
||||||
} else {
|
} else {
|
||||||
clientY = (target.srcEvent as MouseEvent).y;
|
clientY = Math.floor((target.srcEvent as MouseEvent).y);
|
||||||
clientX = (target.srcEvent as MouseEvent).x;
|
clientX = Math.floor((target.srcEvent as MouseEvent).x);
|
||||||
}
|
}
|
||||||
|
|
||||||
const $containter = this.mapService.getMapContainer();
|
const $containter = this.mapService.getMapContainer();
|
||||||
|
@ -108,21 +125,8 @@ export default class InteractionService extends EventEmitter
|
||||||
clientY -= top;
|
clientY -= top;
|
||||||
}
|
}
|
||||||
const lngLat = this.mapService.containerToLngLat([clientX, clientY]);
|
const lngLat = this.mapService.containerToLngLat([clientX, clientY]);
|
||||||
this.emit(InteractionEvent.Hover, { x: clientX, y: clientY, lngLat, type });
|
return { x: clientX, y: clientY, lngLat, type };
|
||||||
};
|
|
||||||
private onTouch = (target: TouchEvent) => {
|
|
||||||
if (target.targetTouches.length > 1) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const touch = target.targetTouches[0];
|
|
||||||
// @ts-ignore
|
|
||||||
this.onHover({
|
|
||||||
x: touch.clientX,
|
|
||||||
y: touch.clientY,
|
|
||||||
type: 'touch',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
private onHover = ({ x, y, type }: MouseEvent) => {
|
private onHover = ({ x, y, type }: MouseEvent) => {
|
||||||
const $containter = this.mapService.getMapContainer();
|
const $containter = this.mapService.getMapContainer();
|
||||||
if ($containter) {
|
if ($containter) {
|
||||||
|
|
|
@ -110,7 +110,7 @@ export default class PickingService implements IPickingService {
|
||||||
const { enableHighlight, enableSelect } = layer.getLayerConfig();
|
const { enableHighlight, enableSelect } = layer.getLayerConfig();
|
||||||
|
|
||||||
const xInDevicePixel = x * window.devicePixelRatio;
|
const xInDevicePixel = x * window.devicePixelRatio;
|
||||||
const yInDevicePixel = y * window.devicePixelRatio;
|
const yInDevicePixel = (height - (y + 1)) * window.devicePixelRatio;
|
||||||
if (
|
if (
|
||||||
xInDevicePixel > width ||
|
xInDevicePixel > width ||
|
||||||
xInDevicePixel < 0 ||
|
xInDevicePixel < 0 ||
|
||||||
|
@ -123,7 +123,7 @@ export default class PickingService implements IPickingService {
|
||||||
pickedColors = readPixels({
|
pickedColors = readPixels({
|
||||||
x: Math.floor(xInDevicePixel / PICKSCALE),
|
x: Math.floor(xInDevicePixel / PICKSCALE),
|
||||||
// 视口坐标系原点在左上,而 WebGL 在左下,需要翻转 Y 轴
|
// 视口坐标系原点在左上,而 WebGL 在左下,需要翻转 Y 轴
|
||||||
y: Math.floor((height - (y + 1) * window.devicePixelRatio) / PICKSCALE),
|
y: Math.floor(yInDevicePixel / PICKSCALE),
|
||||||
width: 1,
|
width: 1,
|
||||||
height: 1,
|
height: 1,
|
||||||
data: new Uint8Array(1 * 1 * 4),
|
data: new Uint8Array(1 * 1 * 4),
|
||||||
|
|
|
@ -22,4 +22,8 @@ export const SceneEventList: string[] = [
|
||||||
'maploaded',
|
'maploaded',
|
||||||
'resize',
|
'resize',
|
||||||
'destroy',
|
'destroy',
|
||||||
|
'dragstart',
|
||||||
|
'dragging',
|
||||||
|
'dragend',
|
||||||
|
'dragcancel',
|
||||||
];
|
];
|
||||||
|
|
|
@ -14,7 +14,11 @@ import { IMarkerService } from '../component/IMarkerService';
|
||||||
import { IPopupService } from '../component/IPopupService';
|
import { IPopupService } from '../component/IPopupService';
|
||||||
import { IGlobalConfigService, ISceneConfig } from '../config/IConfigService';
|
import { IGlobalConfigService, ISceneConfig } from '../config/IConfigService';
|
||||||
import { ICoordinateSystemService } from '../coordinate/ICoordinateSystemService';
|
import { ICoordinateSystemService } from '../coordinate/ICoordinateSystemService';
|
||||||
import { IInteractionService } from '../interaction/IInteractionService';
|
import {
|
||||||
|
IInteractionService,
|
||||||
|
IInteractionTarget,
|
||||||
|
InteractionEvent,
|
||||||
|
} from '../interaction/IInteractionService';
|
||||||
import { IPickingService } from '../interaction/IPickingService';
|
import { IPickingService } from '../interaction/IPickingService';
|
||||||
import { ILayer, ILayerService } from '../layer/ILayerService';
|
import { ILayer, ILayerService } from '../layer/ILayerService';
|
||||||
import { ILogService } from '../log/ILogService';
|
import { ILogService } from '../log/ILogService';
|
||||||
|
@ -24,7 +28,7 @@ import { IShaderModuleService } from '../shader/IShaderModuleService';
|
||||||
import { ISceneService } from './ISceneService';
|
import { ISceneService } from './ISceneService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* will emit `loaded` `resize` `destroy` event
|
* will emit `loaded` `resize` `destroy` event panstart panmove panend
|
||||||
*/
|
*/
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class Scene extends EventEmitter implements ISceneService {
|
export default class Scene extends EventEmitter implements ISceneService {
|
||||||
|
@ -157,6 +161,10 @@ export default class Scene extends EventEmitter implements ISceneService {
|
||||||
this.popupService.initPopup();
|
this.popupService.initPopup();
|
||||||
// 地图初始化之后 才能初始化 container 上的交互
|
// 地图初始化之后 才能初始化 container 上的交互
|
||||||
this.interactionService.init();
|
this.interactionService.init();
|
||||||
|
this.interactionService.on(
|
||||||
|
InteractionEvent.Drag,
|
||||||
|
this.addSceneEvent.bind(this),
|
||||||
|
);
|
||||||
this.logger.debug(`map ${this.id} loaded`);
|
this.logger.debug(`map ${this.id} loaded`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -311,4 +319,8 @@ export default class Scene extends EventEmitter implements ISceneService {
|
||||||
this.cameraService.update(viewport);
|
this.cameraService.update(viewport);
|
||||||
this.render();
|
this.render();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private addSceneEvent(target: IInteractionTarget) {
|
||||||
|
this.emit(target.type, target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
# `draw`
|
# `draw`
|
||||||
|
|
||||||
> TODO: description
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
const draw = require('draw');
|
const draw = require('draw');
|
||||||
|
|
||||||
// TODO: DEMONSTRATE API
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import pkg from './package.json';
|
||||||
|
import typescript from 'rollup-plugin-typescript';
|
||||||
|
import resolve from 'rollup-plugin-node-resolve';
|
||||||
|
import commonjs from '@rollup/plugin-commonjs';
|
||||||
|
import buble from 'rollup-plugin-buble';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: './src/index.ts',
|
||||||
|
plugins: [
|
||||||
|
typescript({
|
||||||
|
exclude: 'node_modules/**',
|
||||||
|
typescript: require('typescript')
|
||||||
|
}),
|
||||||
|
resolve(),
|
||||||
|
commonjs(),
|
||||||
|
buble({
|
||||||
|
transforms: { generator: false }
|
||||||
|
})
|
||||||
|
],
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
format: 'cjs',
|
||||||
|
file: pkg.main,
|
||||||
|
sourcemap: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
format: 'es',
|
||||||
|
file: pkg.module,
|
||||||
|
sourcemap: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export { default as DrawSource } from './source';
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { Feature, FeatureCollection } from '@turf/helpers';
|
||||||
|
import DrawSource from '../source';
|
||||||
|
|
||||||
|
export interface IDrawOption {
|
||||||
|
data: FeatureCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default abstract class DrawFeature {
|
||||||
|
private source: DrawSource;
|
||||||
|
constructor(options: IDrawOption) {
|
||||||
|
const { data } = options;
|
||||||
|
this.source = new DrawSource(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onDragStart() {
|
||||||
|
throw new Error('not imp');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onDragging() {
|
||||||
|
throw new Error('not imp');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onDragEnd() {
|
||||||
|
throw new Error('not imp');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onClick() {
|
||||||
|
throw new Error('not imp');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { Feature, FeatureCollection } from '@turf/helpers';
|
||||||
|
export default class DrawSource {
|
||||||
|
private data: FeatureCollection;
|
||||||
|
constructor(data?: FeatureCollection) {
|
||||||
|
this.data = data || this.getDefaultData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public addFeature(feature: any) {
|
||||||
|
this.data.features.push(feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getFeature(id: string): Feature | undefined {
|
||||||
|
const result = this.data.features.find((fe: Feature) => {
|
||||||
|
return fe?.properties?.id === id;
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public removeFeature(feature: Feature) {
|
||||||
|
const index = this.getFeatureIndex(feature);
|
||||||
|
if (index !== undefined) {
|
||||||
|
this.data.features.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public updateFeature(feature: Feature) {
|
||||||
|
this.removeFeature(feature);
|
||||||
|
this.addFeature(feature);
|
||||||
|
}
|
||||||
|
private getDefaultData(): FeatureCollection {
|
||||||
|
return {
|
||||||
|
type: 'FeatureCollection',
|
||||||
|
features: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private getFeatureIndex(feature: Feature): number | undefined {
|
||||||
|
return this.data.features.findIndex((fe) => {
|
||||||
|
return fe?.properties?.id === feature?.properties?.id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
const FillStyle = {
|
||||||
|
// 正常显示样式
|
||||||
|
normal_fill: {
|
||||||
|
type: 'PolygonLayer',
|
||||||
|
shape: 'fill',
|
||||||
|
color: '#3bb2d0',
|
||||||
|
style: {
|
||||||
|
opacity: 0.1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// xai'm'z
|
||||||
|
active_fill: {
|
||||||
|
type: 'PolygonLayer',
|
||||||
|
shape: 'fill',
|
||||||
|
color: '#fbb03b',
|
||||||
|
style: {
|
||||||
|
opacity: 0.1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const PointStyle = {
|
||||||
|
normal_point: {
|
||||||
|
type: 'PointLayer',
|
||||||
|
shape: 'circle',
|
||||||
|
color: '#3bb2d0',
|
||||||
|
size: 3,
|
||||||
|
style: {
|
||||||
|
stroke: '#fff',
|
||||||
|
strokeWidth: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const LineStyle = {
|
||||||
|
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],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
|
@ -28,7 +28,7 @@
|
||||||
<!-- <script src="https://cdn.jsdelivr.net/npm/symbol-es6@0.1.2/symbol-es6.min.js"></script> -->
|
<!-- <script src="https://cdn.jsdelivr.net/npm/symbol-es6@0.1.2/symbol-es6.min.js"></script> -->
|
||||||
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.js"></script>
|
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.js"></script>
|
||||||
|
|
||||||
<script src="../dist/l7.js"></script>
|
<script src="../dist/l7-dev.js"></script>
|
||||||
<script>
|
<script>
|
||||||
const data =
|
const data =
|
||||||
{"type":"FeatureCollection","features":[
|
{"type":"FeatureCollection","features":[
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
scene.on('loaded',()=>{
|
scene.on('loaded',()=>{
|
||||||
alert('加载完成');
|
console.log(L7);
|
||||||
|
|
||||||
|
|
||||||
const color = [ 'rgb(255,255,217)', 'rgb(237,248,177)', 'rgb(199,233,180)', 'rgb(127,205,187)', 'rgb(65,182,196)', 'rgb(29,145,192)', 'rgb(34,94,168)', 'rgb(12,44,132)' ];
|
const color = [ 'rgb(255,255,217)', 'rgb(237,248,177)', 'rgb(199,233,180)', 'rgb(127,205,187)', 'rgb(65,182,196)', 'rgb(29,145,192)', 'rgb(34,94,168)', 'rgb(12,44,132)' ];
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
"inversify": "^5.0.1",
|
"inversify": "^5.0.1",
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.15",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"regl": "1.3.11"
|
"regl": "1.3.13"
|
||||||
},
|
},
|
||||||
"gitHead": "a5d354b66873f700730248d015c5e539c54b34b7",
|
"gitHead": "a5d354b66873f700730248d015c5e539c54b34b7",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
IIconFontGlyph,
|
IIconFontGlyph,
|
||||||
IIconService,
|
IIconService,
|
||||||
IImage,
|
IImage,
|
||||||
|
IInteractionService,
|
||||||
ILayer,
|
ILayer,
|
||||||
ILayerService,
|
ILayerService,
|
||||||
ILngLat,
|
ILngLat,
|
||||||
|
@ -56,6 +57,7 @@ class Scene
|
||||||
private markerService: IMarkerService;
|
private markerService: IMarkerService;
|
||||||
private popupService: IPopupService;
|
private popupService: IPopupService;
|
||||||
private fontService: IFontService;
|
private fontService: IFontService;
|
||||||
|
private interactionService: IInteractionService;
|
||||||
|
|
||||||
private container: Container;
|
private container: Container;
|
||||||
|
|
||||||
|
@ -88,7 +90,9 @@ class Scene
|
||||||
this.markerService = sceneContainer.get<IMarkerService>(
|
this.markerService = sceneContainer.get<IMarkerService>(
|
||||||
TYPES.IMarkerService,
|
TYPES.IMarkerService,
|
||||||
);
|
);
|
||||||
|
this.interactionService = sceneContainer.get<IInteractionService>(
|
||||||
|
TYPES.IInteractionService,
|
||||||
|
);
|
||||||
this.popupService = sceneContainer.get<IPopupService>(TYPES.IPopupService);
|
this.popupService = sceneContainer.get<IPopupService>(TYPES.IPopupService);
|
||||||
|
|
||||||
this.initComponent(id);
|
this.initComponent(id);
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
import { LineLayer, PointLayer, PolygonLayer, Popup, Scene } from '@antv/l7';
|
||||||
|
import { GaodeMap, Mapbox } from '@antv/l7-maps';
|
||||||
|
import { lnglatDistance } from '@antv/l7-utils';
|
||||||
|
import turfCircle from '@turf/circle';
|
||||||
|
import * as React from 'react';
|
||||||
|
const createGeoJSONCircle = (
|
||||||
|
center: [number, number],
|
||||||
|
radiusInKm: number,
|
||||||
|
points: number = 64,
|
||||||
|
) => {
|
||||||
|
const options = { steps: 64 };
|
||||||
|
const circle = turfCircle(center, radiusInKm, options);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'geojson',
|
||||||
|
data: {
|
||||||
|
type: 'FeatureCollection',
|
||||||
|
features: [circle],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default class MultiPolygon extends React.Component {
|
||||||
|
private gui: dat.GUI;
|
||||||
|
private $stats: Node;
|
||||||
|
private scene: Scene;
|
||||||
|
|
||||||
|
public componentWillUnmount() {
|
||||||
|
this.scene.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async componentDidMount() {
|
||||||
|
const scene = new Scene({
|
||||||
|
id: 'map',
|
||||||
|
map: new Mapbox({
|
||||||
|
pitch: 0,
|
||||||
|
style: 'normal',
|
||||||
|
center: [121.775374, 31.31067],
|
||||||
|
zoom: 15,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
this.scene = scene;
|
||||||
|
|
||||||
|
scene.on('loaded', () => {
|
||||||
|
let startPoint = {};
|
||||||
|
const circleLayer = new PolygonLayer()
|
||||||
|
.source({
|
||||||
|
type: 'FeatureCollection',
|
||||||
|
features: [],
|
||||||
|
})
|
||||||
|
.color('#fbb03b')
|
||||||
|
.shape('fill')
|
||||||
|
.style({
|
||||||
|
opacity: 0.6,
|
||||||
|
});
|
||||||
|
scene.addLayer(circleLayer);
|
||||||
|
scene.on('dragstart', (e: any) => {
|
||||||
|
// @ts-ignore
|
||||||
|
scene.map.dragdrag.disable();
|
||||||
|
startPoint = e.lngLat;
|
||||||
|
const layer = new PointLayer()
|
||||||
|
.source([startPoint], {
|
||||||
|
parser: {
|
||||||
|
type: 'json',
|
||||||
|
x: 'lng',
|
||||||
|
y: 'lat',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.shape('circle')
|
||||||
|
.color('#fbb03b')
|
||||||
|
.size(5)
|
||||||
|
.style({
|
||||||
|
stroke: '#fff',
|
||||||
|
strokeWidth: 2,
|
||||||
|
});
|
||||||
|
scene.addLayer(layer);
|
||||||
|
});
|
||||||
|
scene.on('drag', (e: any) => {
|
||||||
|
// @ts-ignore
|
||||||
|
const start = [startPoint.lng, startPoint.lat];
|
||||||
|
const dis = lnglatDistance(
|
||||||
|
// @ts-ignore
|
||||||
|
start,
|
||||||
|
[e.lngLat.lng, e.lngLat.lat],
|
||||||
|
);
|
||||||
|
const circleData = createGeoJSONCircle(
|
||||||
|
start as [number, number],
|
||||||
|
dis / 1000,
|
||||||
|
);
|
||||||
|
circleLayer.setData(circleData.data);
|
||||||
|
const popup = new Popup().setText(`${dis}`).setLnglat(e.lngLat);
|
||||||
|
scene.addPopup(popup);
|
||||||
|
});
|
||||||
|
scene.on('dragend', (e: any) => {
|
||||||
|
// @ts-ignore
|
||||||
|
scene.map.dragdrag.enable();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="map"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
import { LineLayer, PointLayer, PolygonLayer, Popup, Scene } from '@antv/l7';
|
||||||
|
import { GaodeMap, Mapbox } from '@antv/l7-maps';
|
||||||
|
import * as React from 'react';
|
||||||
|
const createGeoJSONRect = (
|
||||||
|
point1: [number, number],
|
||||||
|
point2: [number, number],
|
||||||
|
) => {
|
||||||
|
const minX = Math.min(point1[0], point2[0]);
|
||||||
|
const minY = Math.min(point1[1], point2[1]);
|
||||||
|
const maxX = Math.max(point1[0], point2[0]);
|
||||||
|
const maxY = Math.max(point1[1], point2[1]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'geojson',
|
||||||
|
data: {
|
||||||
|
type: 'FeatureCollection',
|
||||||
|
features: [
|
||||||
|
{
|
||||||
|
type: 'Feature',
|
||||||
|
properties: {},
|
||||||
|
geometry: {
|
||||||
|
type: 'Polygon',
|
||||||
|
coordinates: [
|
||||||
|
[
|
||||||
|
[minX, minY],
|
||||||
|
[minX, maxY],
|
||||||
|
[maxX, maxY],
|
||||||
|
[maxX, minY],
|
||||||
|
[minX, minY],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default class MultiPolygon extends React.Component {
|
||||||
|
private gui: dat.GUI;
|
||||||
|
private $stats: Node;
|
||||||
|
private scene: Scene;
|
||||||
|
|
||||||
|
public componentWillUnmount() {
|
||||||
|
this.scene.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async componentDidMount() {
|
||||||
|
const scene = new Scene({
|
||||||
|
id: 'map',
|
||||||
|
map: new Mapbox({
|
||||||
|
pitch: 0,
|
||||||
|
style: 'normal',
|
||||||
|
center: [121.775374, 31.31067],
|
||||||
|
zoom: 15,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
this.scene = scene;
|
||||||
|
|
||||||
|
scene.on('loaded', () => {
|
||||||
|
let startPoint = {};
|
||||||
|
const circleLayer = new PolygonLayer()
|
||||||
|
.source({
|
||||||
|
type: 'FeatureCollection',
|
||||||
|
features: [],
|
||||||
|
})
|
||||||
|
.color('#fbb03b')
|
||||||
|
.shape('fill')
|
||||||
|
.style({
|
||||||
|
opacity: 0.6,
|
||||||
|
});
|
||||||
|
scene.addLayer(circleLayer);
|
||||||
|
scene.on('panstart', (e: any) => {
|
||||||
|
// @ts-ignore
|
||||||
|
scene.map.dragPan.disable();
|
||||||
|
startPoint = e.lngLat;
|
||||||
|
const layer = new PointLayer()
|
||||||
|
.source([startPoint], {
|
||||||
|
parser: {
|
||||||
|
type: 'json',
|
||||||
|
x: 'lng',
|
||||||
|
y: 'lat',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.shape('circle')
|
||||||
|
.color('#fbb03b')
|
||||||
|
.size(5)
|
||||||
|
.style({
|
||||||
|
stroke: '#fff',
|
||||||
|
strokeWidth: 2,
|
||||||
|
});
|
||||||
|
scene.addLayer(layer);
|
||||||
|
});
|
||||||
|
scene.on('panmove', (e: any) => {
|
||||||
|
// @ts-ignore
|
||||||
|
const start = [startPoint.lng, startPoint.lat];
|
||||||
|
|
||||||
|
const circleData = createGeoJSONRect(start as [number, number], [
|
||||||
|
e.lngLat.lng,
|
||||||
|
e.lngLat.lat,
|
||||||
|
]);
|
||||||
|
circleLayer.setData(circleData.data);
|
||||||
|
// const popup = new Popup().setText(`${dis}`).setLnglat(e.lngLat);
|
||||||
|
// scene.addPopup(popup);
|
||||||
|
});
|
||||||
|
scene.on('panend', (e: any) => {
|
||||||
|
// @ts-ignore
|
||||||
|
scene.map.dragPan.enable();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="map"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,10 @@
|
||||||
import { storiesOf } from '@storybook/react';
|
import { storiesOf } from '@storybook/react';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import DrawCircle from './Components/DrawCircle';
|
||||||
import DrawPolygon from './Components/DrawPolygon';
|
import DrawPolygon from './Components/DrawPolygon';
|
||||||
|
import DrawRect from './Components/DrawRect';
|
||||||
|
|
||||||
storiesOf('绘制', module).add('绘制面', () => <DrawPolygon />, {});
|
storiesOf('绘制', module)
|
||||||
|
.add('绘制圆', () => <DrawCircle />, {})
|
||||||
|
.add('四边形', () => <DrawRect />, {})
|
||||||
|
.add('绘制面', () => <DrawPolygon />, {});
|
||||||
|
|
Loading…
Reference in New Issue