|
@@ -1,300 +0,0 @@
|
|
|
-import { nanoid } from 'nanoid';
|
|
|
-import { useHistory } from '@/hooks/useHistory';
|
|
|
-import { deepClone } from '@/utils';
|
|
|
-import { countCircleArea, countRectangleArea } from '@/utils/geometryUtil';
|
|
|
-import olPlot from 'ol-plot';
|
|
|
-
|
|
|
-interface DrawToolOptions {
|
|
|
- color: string;
|
|
|
- drawType: string;
|
|
|
- graphicsType: string;
|
|
|
- onDrawCompleted?: Function;
|
|
|
-}
|
|
|
-export function useDrawTool(options: DrawToolOptions) {
|
|
|
- const drawOptions = {
|
|
|
- strokeColor: options.color,
|
|
|
- strokeOpacity: 1,
|
|
|
- strokeWeight: 2,
|
|
|
- fillColor: options.color,
|
|
|
- fillOpacity: options.drawType === '1' ? 0 : 0.5,
|
|
|
- strokeStyle: 'solid'
|
|
|
- };
|
|
|
- const { currentState, commit, undo, history, future } = useHistory();
|
|
|
- const overlays = [];
|
|
|
- const overlaysData = [];
|
|
|
- let graphicsType = options.graphicsType;
|
|
|
- let mouseTool, contextMenu, map, plot, rightClickObj;
|
|
|
- const initMouseTool = (map1) => {
|
|
|
- map = map1;
|
|
|
- plot = new olPlot(map1, {
|
|
|
- zoomToExtent: true
|
|
|
- });
|
|
|
- // 绘制结束后,添加到FeatureOverlay显示。
|
|
|
- function onDrawEnd (event) {
|
|
|
- var feature = event.feature;
|
|
|
- const aa = feature.getGeometry();
|
|
|
- // 开始编辑
|
|
|
- plot.plotEdit.activate(feature);
|
|
|
- }
|
|
|
-
|
|
|
- plot.plotDraw.on('drawEnd', onDrawEnd);
|
|
|
- // 初始化绘制工具
|
|
|
- // mouseTool = new AMap.MouseTool(map);
|
|
|
- // // 绘制完成事件
|
|
|
- // initDrawMethod();
|
|
|
- // //创建右键菜单
|
|
|
- // contextMenu = new AMap.ContextMenu();
|
|
|
- // // 右键删除按钮
|
|
|
- // contextMenu.addItem(
|
|
|
- // '删除',
|
|
|
- // function (event) {
|
|
|
- // deleteGraphics();
|
|
|
- // },
|
|
|
- // 0
|
|
|
- // );
|
|
|
- };
|
|
|
- // 初始化绘制完成回调
|
|
|
- const initDrawMethod = () => {
|
|
|
- mouseTool.on('draw', function (event) {
|
|
|
- const obj = event.obj;
|
|
|
- const id = nanoid();
|
|
|
- obj._opts.extData = {
|
|
|
- id: id
|
|
|
- };
|
|
|
- const data: any = {
|
|
|
- id: id,
|
|
|
- type: getType(obj.className),
|
|
|
- color: obj._opts.strokeColor,
|
|
|
- drawType: obj._opts.fillOpacity === 0 ? '1' : '2'
|
|
|
- };
|
|
|
- if (data.type === 'circle') {
|
|
|
- data.center = [obj.getCenter().lng, obj.getCenter().lat];
|
|
|
- data.radius = obj.getRadius();
|
|
|
- } else if (data.type === 'rectangle') {
|
|
|
- const bounds = obj.getBounds();
|
|
|
- // 从bounds中获取西南角和东北角的坐标
|
|
|
- const southWest = bounds.getSouthWest();
|
|
|
- const northEast = bounds.getNorthEast();
|
|
|
- data.southWest = [southWest.lng, southWest.lat];
|
|
|
- data.northEast = [northEast.lng, northEast.lat];
|
|
|
- const pathArr = [
|
|
|
- [
|
|
|
- [southWest.lng, northEast.lat],
|
|
|
- [northEast.lng, northEast.lat],
|
|
|
- [northEast.lng, southWest.lat],
|
|
|
- [southWest.lng, southWest.lat],
|
|
|
- [southWest.lng, northEast.lat]
|
|
|
- ]
|
|
|
- ];
|
|
|
- } else if (data.type === 'polygon') {
|
|
|
- const path = obj.getPath();
|
|
|
- // 将AMap.LngLat对象数组转换为经纬度数组
|
|
|
- const pathArr = path.map((lngLat) => {
|
|
|
- // 返回经度和纬度的数组
|
|
|
- return [lngLat.lng, lngLat.lat];
|
|
|
- });
|
|
|
- data.path = pathArr;
|
|
|
- const newPathArr = deepClone(pathArr);
|
|
|
- newPathArr.push(newPathArr[0]);
|
|
|
- }
|
|
|
- overlays.push(obj);
|
|
|
- overlaysData.push(data);
|
|
|
- commit(deepClone(overlaysData));
|
|
|
- if (typeof options.onDrawCompleted === 'function') {
|
|
|
- options.onDrawCompleted(data, overlaysData, obj, event);
|
|
|
- }
|
|
|
- // 右击菜单
|
|
|
- obj.on('rightclick', handleRightClick);
|
|
|
- });
|
|
|
- };
|
|
|
- // 图形右击事件
|
|
|
- const handleRightClick = (event) => {
|
|
|
- rightClickObj = event.target;
|
|
|
- contextMenu.open(map, event.lnglat);
|
|
|
- };
|
|
|
- // 删除图形
|
|
|
- const deleteGraphics = () => {
|
|
|
- const id = rightClickObj.getExtData()?.id;
|
|
|
- if (id) {
|
|
|
- for (let i = 0; i < overlays.length; i++) {
|
|
|
- if (overlays[i].getExtData()?.id === id) {
|
|
|
- removeOverlayByIndex(i);
|
|
|
- commit(deepClone(overlaysData));
|
|
|
- rightClickObj = null;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
- // 判断图形类型
|
|
|
- const getType = (type) => {
|
|
|
- let res = '';
|
|
|
- if (type === 'Overlay.Circle') {
|
|
|
- res = 'circle';
|
|
|
- } else if (type === 'Overlay.Rectangle') {
|
|
|
- res = 'rectangle';
|
|
|
- } else if (type === 'Overlay.Polygon') {
|
|
|
- res = 'polygon';
|
|
|
- }
|
|
|
- return res;
|
|
|
- };
|
|
|
- // 绘制图形
|
|
|
- const drawGraphics = (type: string) => {
|
|
|
- if (type === 'circle') {
|
|
|
- // 绘制圆形
|
|
|
- plot.plotDraw.activate('Circle');
|
|
|
- } else if (type === 'rectangle') {
|
|
|
- // 绘制矩形
|
|
|
- plot.plotDraw.activate('RectAngle');
|
|
|
- } else if (type === 'polygon') {
|
|
|
- // 绘制多边形
|
|
|
- plot.plotDraw.activate('Polygon');
|
|
|
- } else if (type === 'freePolygon') {
|
|
|
- // 绘制索套
|
|
|
- plot.plotDraw.activate('FreePolygon');
|
|
|
- }
|
|
|
- };
|
|
|
- // 设置颜色
|
|
|
- const setColor = (color: string) => {
|
|
|
- drawOptions.strokeColor = color;
|
|
|
- drawOptions.fillColor = color;
|
|
|
- };
|
|
|
- // 设置线框面框
|
|
|
- const setDrawType = (drawType: string) => {
|
|
|
- drawOptions.fillOpacity = drawType === '1' ? 0 : 0.5;
|
|
|
- };
|
|
|
- // 设置图形类型
|
|
|
- const setGraphicsType = (type: string) => {
|
|
|
- closeDraw();
|
|
|
- graphicsType = type;
|
|
|
- drawGraphics(type);
|
|
|
- };
|
|
|
- // 关闭绘制
|
|
|
- const closeDraw = () => {
|
|
|
- mouseTool.close();
|
|
|
- };
|
|
|
- // 返回鼠标工具对象
|
|
|
- const getMouseTool = () => {
|
|
|
- return mouseTool;
|
|
|
- };
|
|
|
- // 创建图形
|
|
|
- const createGraphics = (data: any) => {
|
|
|
- if (data.type === 'circle') {
|
|
|
- // 绘制圆形
|
|
|
- createCircle(data);
|
|
|
- } else if (data.type === 'rectangle') {
|
|
|
- // 绘制矩形
|
|
|
- createRectangle(data);
|
|
|
- } else if (data.type === 'polygon') {
|
|
|
- // 绘制多边形
|
|
|
- createPolygon(data);
|
|
|
- }
|
|
|
- };
|
|
|
- // 创建圆形
|
|
|
- const createCircle = (options) => {
|
|
|
- const circle = new AMap.Circle({
|
|
|
- center: options.center,
|
|
|
- radius: options.radius, //半径
|
|
|
- strokeColor: options.color,
|
|
|
- strokeOpacity: 1,
|
|
|
- strokeWeight: 2,
|
|
|
- fillColor: options.color,
|
|
|
- fillOpacity: options.drawType === '1' ? 0 : 0.5,
|
|
|
- strokeStyle: 'solid'
|
|
|
- });
|
|
|
- overlays.push(circle);
|
|
|
- map.add(circle);
|
|
|
- };
|
|
|
- // 创建矩形
|
|
|
- const createRectangle = (options: any) => {
|
|
|
- const southWest = new AMap.LngLat(options.southWest[0], options.southWest[1]);
|
|
|
- const northEast = new AMap.LngLat(options.northEast[0], options.northEast[1]);
|
|
|
- const bounds = new AMap.Bounds(southWest, northEast);
|
|
|
- const rectangle = new AMap.Rectangle({
|
|
|
- bounds: bounds,
|
|
|
- strokeColor: options.color,
|
|
|
- strokeOpacity: 1,
|
|
|
- strokeWeight: 2,
|
|
|
- fillColor: options.color,
|
|
|
- fillOpacity: options.drawType === '1' ? 0 : 0.5,
|
|
|
- strokeStyle: 'solid'
|
|
|
- });
|
|
|
- overlays.push(rectangle);
|
|
|
- map.add(rectangle);
|
|
|
- };
|
|
|
- // 创建矩形
|
|
|
- const createPolygon = (options: any) => {
|
|
|
- // 将数组转换为AMap.LngLat对象的数组
|
|
|
- const path = options.path.map((coord) => {
|
|
|
- return new AMap.LngLat(coord[0], coord[1]);
|
|
|
- });
|
|
|
- const polygon = new AMap.Polygon({
|
|
|
- path: path,
|
|
|
- strokeColor: options.color,
|
|
|
- strokeOpacity: 1,
|
|
|
- strokeWeight: 2,
|
|
|
- fillColor: options.color,
|
|
|
- fillOpacity: options.drawType === '1' ? 0 : 0.5,
|
|
|
- strokeStyle: 'solid'
|
|
|
- });
|
|
|
- overlays.push(polygon);
|
|
|
- map.add(polygon);
|
|
|
- };
|
|
|
- // 处理撤销
|
|
|
- const handleUndo = () => {
|
|
|
- const previous = history.value[history.value.length - 2];
|
|
|
- if (history.value.length > 1) {
|
|
|
- if (currentState.value.length > previous.length) {
|
|
|
- // 撤销新增
|
|
|
- removeOverlayByIndex(currentState.value.length - 1);
|
|
|
- } else {
|
|
|
- let restoreData;
|
|
|
- for (let i = 0; i < previous.length; i++) {
|
|
|
- let index = 0;
|
|
|
- for (let k = 0; k < currentState.value.length; k++) {
|
|
|
- if (previous[i].id !== currentState.value[k].id) {
|
|
|
- index++;
|
|
|
- } else {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (index === previous.length - 1) {
|
|
|
- restoreData = previous[i];
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (restoreData) {
|
|
|
- createGraphics(restoreData);
|
|
|
- }
|
|
|
- }
|
|
|
- undo();
|
|
|
-
|
|
|
- console.log(history.value, future.value, currentState.value);
|
|
|
- }
|
|
|
- };
|
|
|
- // 根据索引移除覆盖物
|
|
|
- const removeOverlayByIndex = (index: number) => {
|
|
|
- // 移除地图上覆盖物
|
|
|
- map.remove(overlays[index]);
|
|
|
- overlays.splice(index, 1);
|
|
|
- overlaysData.splice(index, 1);
|
|
|
- };
|
|
|
- // // 图层分析显示信息
|
|
|
- // const addText = (text) => {
|
|
|
- //
|
|
|
- // }
|
|
|
- return {
|
|
|
- overlays,
|
|
|
- getMouseTool,
|
|
|
- initMouseTool,
|
|
|
- drawGraphics,
|
|
|
- closeDraw,
|
|
|
- setColor,
|
|
|
- setDrawType,
|
|
|
- setGraphicsType,
|
|
|
- createCircle,
|
|
|
- removeOverlayByIndex,
|
|
|
- handleUndo,
|
|
|
- currentState,
|
|
|
- history
|
|
|
- };
|
|
|
-}
|