CzRger 1 年間 前
コミット
509b268b9e

+ 3 - 4
src/components/easyMap/easy-map-style.scss

@@ -49,16 +49,15 @@
 }
 
 .tools-right-popover-measure {
-  background-color: #152584 !important;
+  background-color: #ffffff !important;
   width: auto !important;
   min-width: auto !important;
   padding: 0 !important;
   border: none !important;
-
   .tools-right-measure {
     display: flex;
     flex-direction: column;
-
+    padding: 4px;
     img {
       width: 16px;
       height: 16px;
@@ -68,7 +67,7 @@
   }
 
   .el-popper__arrow:before {
-    background-color: #152584 !important;
+    background-color: #ffffff !important;
     border: none !important;
   }
 }

+ 1 - 1
src/components/easyMap/func/draw.ts

@@ -10,7 +10,7 @@ import * as coordinate from 'ol/coordinate'
 import * as control from 'ol/control'
 import * as sphere from 'ol/sphere'
 import { unByKey } from 'ol/Observable'
-import './measure.scss'
+import './dom.scss'
 import {createBox} from "ol/interaction/Draw";
 import {Circle, LineString, Polygon} from "ol/geom";
 import {formatPosition} from '@/utils/easyMap'

+ 524 - 0
src/components/easyMap/func/mark-draw.ts

@@ -0,0 +1,524 @@
+import * as ol from 'ol'
+import * as style from 'ol/style'
+import * as layer from 'ol/layer'
+import * as source from 'ol/source'
+import * as interaction from 'ol/interaction'
+import Modify from "ol/interaction/Modify"
+import {createBox} from "ol/interaction/Draw"
+import * as sphere from "ol/sphere";
+import {unByKey} from "ol/Observable";
+import {isValue} from "@/utils/util";
+// @ts-ignore
+import PointIcon from "../images/gis-layout-tools_tool-bz_icon.png"
+import CloseIcon from "../images/close.png"
+import {v4} from "uuid";
+import store from "@/store";
+
+const globalLineDash = [
+    [0, 0], //实线
+    [15, 15], //长虚线
+    [5, 5] //虚线
+]
+const layerFlag = ['layerName', 'markDrawViewsLayer']
+const drawFlag = ['interactionName', 'markDrawInteraction']
+const modifyFlag = ['interactionName', 'markModifyInteraction']
+const baseDrawConfig = {
+    //  样式字段
+    text: null, // 要素上显示的文字,默认无文字
+    pointIcon: PointIcon, // Point的图标
+    pointScale: 1, // Point的缩放,默认1
+    pointOffset: [0, 24], // Point的偏移量,默认[0, 0]
+    rectangle: false,
+    lineColor: '#2860F1', // LineString的线段颜色,默认蓝色
+    lineWidth: 2, // LineString的线段宽度,默认1
+    lineType: 0, // LineString的线段类型索引,默认0,实线,取globalLineDash数组索引
+    lineDash: null, // LineString的线段类型,默认null,优先级比lineType高
+    polyColor: 'rgba(20, 129, 241, 0.1)', // Polygon的填充色,默认蓝色
+    polyBorderColor: '#2860F1', // Polygon的边框颜色,默认蓝色
+    polyBorderWidth: 2, // Polygon的边框宽度,默认1
+    polyBorderType: 0, // Polygon的边框类型索引,默认0,实线,取globalLineDash数组索引
+    polyBorderDash: null, // Polygon的边框类型,默认null,优先级比polyBorderType高
+    //  业务字段
+    show: false, // 标绘样式选项是否显示
+    featureType: 'Point', // 标绘的要素类型
+    isPoint: false, // 是否可以标绘点
+    isLineString: false, // 是否可以标绘线
+    isPolygon: false, // 是否可以标绘面
+    showPosition: false, // 是否显示经纬度输入框
+    refreshStyleFunc: () => {}, // 刷新标绘样式方法
+}
+export const getBaseDrawConfig = () => {
+    return JSON.parse(JSON.stringify(baseDrawConfig))
+}
+/**
+ *
+ * @param map
+ * @param arr   要标绘的数组,每个对象的数据在要素中保存的属性为 'val'
+ * @param arr > wkt:wkt格式坐标
+ * @param arr > styles:要素的样式,优先级最高
+ * @param arr > text:styles为空的时候,要素上显示的文字,默认无文字
+ * @param arr > textOffsetY:styles为空的时候,要素上显示的文字Y轴偏移量,默认Point-30,其他0
+ * @param arr > pointIcon:styles为空的时候,Point的图标,默认圆形
+ * @param arr > pointScale:styles为空的时候,Point的缩放,默认1
+ * @param arr > pointOffset:styles为空的时候,Point的偏移量,默认[0, 0]
+ * @param arr > lineColor:styles为空的时候,LineString的线段颜色,默认蓝色
+ * @param arr > lineWidth:styles为空的时候,LineString的线段宽度,默认1
+ * @param arr > lineType:styles为空的时候,LineString的线段类型索引,默认0,实线,取globalLineDash数组索引
+ * @param arr > lineDash:styles为空的时候,LineString的线段类型,默认null,优先级比lineType高
+ * @param arr > polyColor:styles为空的时候,Polygon的填充色,默认蓝色
+ * @param arr > polyBorderColor:styles为空的时候,Polygon的边框颜色,默认蓝色
+ * @param arr > polyBorderWidth:styles为空的时候,Polygon的边框宽度,默认1
+ * @param arr > polyBorderType:styles为空的时候,Polygon的边框类型索引,默认0,实线,取globalLineDash数组索引
+ * @param arr > polyBorderDash:styles为空的时候,Polygon的边框类型,默认null,优先级比polyBorderType高
+ */
+
+let toolDrawTooltipElement;
+let toolDrawHelpTooltipElement;
+let closeOverlay = <any>null
+let tempUUID = ''
+export const draw = (map, obj) => {
+    initMarkClose(map)
+    return new Promise((resolve => {
+        if (!isValue(obj.textOffsetY)) {
+            obj.textOffsetY = (obj.featureType === 'Point' ? -30 : 0)
+        }
+        let commonStyle = (showText, featureType = undefined) => {
+            if ((featureType ?? obj.featureType) === 'Point') {
+                return new style.Style({
+                    image: obj.pointIcon ? new style.Icon({
+                        src: obj.pointIcon,
+                        scale: obj.pointScale,
+                        displacement: obj.pointOffset
+                    }) : new style.Circle({
+                        radius: 10,
+                        fill: new style.Fill({
+                            color: '#e810dd',
+                        }),
+                        scale: obj.pointScale,
+                        displacement: obj.pointOffset
+                    }),
+                    text: (showText && obj.text) ? new style.Text({
+                        font: "16px bold 微软雅黑",
+                        text: obj.text,
+                        fill: new style.Fill({
+                            color: '#ffffff'
+                        }),
+                        stroke: new style.Stroke({
+                            color: '#D26CDB',
+                            width: 2
+                        }),
+                        offsetY: obj.textOffsetY,
+                    }) : undefined,
+                })
+            } else if ((featureType ?? obj.featureType) === 'LineString') {
+                return new style.Style({
+                    stroke: new style.Stroke({
+                        color: obj.lineColor,
+                        width: obj.lineWidth,
+                        lineDash: obj.lineDash ?? globalLineDash[Number(obj.lineType)]
+                    }),
+                    text: (showText && obj.text) ? new style.Text({
+                        font: "16px bold 微软雅黑",
+                        text: obj.text,
+                        fill: new style.Fill({
+                            color: '#ffffff'
+                        }),
+                        stroke: new style.Stroke({
+                            color: '#D26CDB',
+                            width: 2
+                        }),
+                        offsetY: obj.textOffsetY,
+                    }) : undefined,
+                })
+            } else if ((featureType ?? obj.featureType) === 'Polygon' || (featureType ?? obj.featureType) === 'Circle') {
+                return new style.Style({
+                    stroke: new style.Stroke({
+                        color: obj.polyBorderColor,
+                        width: obj.polyBorderWidth,
+                        lineDash: obj.polyBorderDash ?? globalLineDash[Number(obj.polyBorderType)]
+                    }),
+                    fill: new style.Fill({
+                        color: obj.polyColor,
+                    }),
+                    text: (showText && obj.text) ? new style.Text({
+                        font: "16px bold 微软雅黑",
+                        text: obj.text,
+                        fill: new style.Fill({
+                            color: '#ffffff'
+                        }),
+                        stroke: new style.Stroke({
+                            color: '#D26CDB',
+                            width: 2
+                        }),
+                        offsetY: obj.textOffsetY,
+                    }) : undefined,
+                })
+            }
+        }
+        const reset = () => {
+            const oldLayer = map.getLayers().getArray().filter(v => v.get(layerFlag[0]) === layerFlag[1])
+            if (oldLayer) {
+                map.removeLayer(oldLayer[0])
+            }
+            const oldDraw = map.getInteractions().getArray().filter(v => v.get(drawFlag[0]) === drawFlag[1])
+            if (oldDraw) {
+                map.removeInteraction(oldDraw[0])
+            }
+            const oldModify = map.getInteractions().getArray().filter(v => v.get(modifyFlag[0]) === modifyFlag[1])
+            if (oldModify) {
+                map.removeInteraction(oldModify[0])
+            }
+        }
+        // @ts-ignore
+        if (!toolDrawTooltipElement && !store.state.easyMap.isTooling) {
+            store.commit('easyMap/SET_IS_TOOLING', true)
+            // reset()
+            let _source
+            const realLayer = map.getLayers().getArray().filter(v => v.get(layerFlag[0]) === layerFlag[1])
+            if (realLayer[0]) {
+                _source = realLayer[0].getSource()
+            } else {
+                _source = new source.Vector(); //图层数据源
+                const _vector = new layer.Vector({
+                    zIndex: 9999,
+                    source: _source,
+                    style: (feat: any) => {
+                        feat.setStyle(commonStyle(true, feat.getGeometry().getType()))
+                    },
+                });
+                _vector.set(layerFlag[0], layerFlag[1])
+                map.addLayer(_vector);
+            }
+            const modifyInteraction = new Modify({
+                source: _source,
+                pixelTolerance: 1
+            });
+            modifyInteraction.set(modifyFlag[0], modifyFlag[1])
+            map.addInteraction(modifyInteraction)
+            modifyInteraction.on('modifyend', evt => {
+                try {
+                    const feat = evt.features.item(0)
+                } catch {
+                }
+            })
+            if (!obj.wkt) {
+                let sketch;
+                let helpTooltip;
+                let measureTooltip;
+                let continueMsg = '双击结束标绘';
+                const geodesicCheckbox = true;//测地学方式对象
+                const createMeasureTooltip = () => {
+                    const id = 'toolDrawTooltipElementId'
+                    if (toolDrawTooltipElement) {
+                        map.removeOverlay(map.getOverlayById(id))
+                        toolDrawTooltipElement.parentNode.removeChild(toolDrawTooltipElement);
+                    }
+                    toolDrawTooltipElement = document.createElement('div');
+                    toolDrawTooltipElement.className = 'tooltip tooltip-measure';
+                    measureTooltip = new ol.Overlay({
+                        id,
+                        element: toolDrawTooltipElement,
+                        offset: [0, -15],
+                        positioning: 'bottom-center'
+                    });
+                    map.addOverlay(measureTooltip);
+                }
+                const createHelpTooltip = () => {
+                    const id = 'toolDrawHelpTooltipElementId'
+                    if (toolDrawHelpTooltipElement) {
+                        map.removeOverlay(map.getOverlayById(id))
+                        toolDrawHelpTooltipElement.parentNode.removeChild(toolDrawHelpTooltipElement);
+                    }
+                    toolDrawHelpTooltipElement = document.createElement('div');
+                    toolDrawHelpTooltipElement.className = 'tooltip hidden';
+                    helpTooltip = new ol.Overlay({
+                        id,
+                        element: toolDrawHelpTooltipElement,
+                        offset: [15, 0],
+                        positioning: 'center-left'
+                    });
+                    map.addOverlay(helpTooltip);
+                }
+                const formatLength = (line) => {
+                    // 获取投影坐标系
+                    const sourceProj = map.getView().getProjection();
+                    // ol/sphere里有getLength()和getArea()用来测量距离和区域面积,默认的投影坐标系是EPSG:3857, 其中有个options的参数,可以设置投影坐标系
+                    const length = sphere.getLength(line, {projection: sourceProj});
+                    // const length = getLength(line);
+                    let output;
+                    if (length > 100) {
+                        const km = Math.round((length / 1000) * 100) / 100;
+                        output = `${km} 千米 <br>${parseFloat(String(km * 0.53995)).toFixed(2)} 海里`;
+                    } else {
+                        output = `${Math.round(length * 100) / 100} m`;
+                    }
+                    return output;
+                };
+                //获取圆的面积
+                const getCircleArea = (circle, projection) => {
+                    const P = 3.14
+                    const radius = getCircleRadius(circle, projection)
+                    return P * radius * radius
+                }
+                //获取圆的半径
+                const getCircleRadius = (circle, projection) => {
+                    return circle.getRadius() * projection.getMetersPerUnit()
+                }
+                const formatArea = (polygon, type= 'polygon') => {
+                    let area
+                    const sourceProj = map.getView().getProjection();
+                    // 获取投影坐标系
+                    if (type === 'polygon') {
+                        area = sphere.getArea(polygon, {
+                            projection: sourceProj,
+                        });
+                    } else if (type === 'circle') {
+                        area = getCircleArea(polygon, sourceProj)
+                    }
+                    let output;
+                    if (area > 10000) {
+                        const km = Math.round((area / 1000000) * 100) / 100;
+                        output = `${km} 平方公里<br>${parseFloat(String(km * 0.38610)).toFixed(
+                            2
+                        )} 平方英里`;
+                    } else {
+                        output = `${Math.round(area * 100) / 100} ` + " m<sup>2</sup>";
+                    }
+                    return output;
+                };
+                const addInteraction = () => {
+                    const id = 'baseDrawName'
+                    let drawLastPoint = ''
+                    let drawLastPointTimer: any = null
+                    let drawCircleDBClickTimer: any = null
+                    const draw = new interaction.Draw({
+                        stopClick: true,
+                        condition: (e) => {
+                            // 圆形单击即触发finishCondition,跳过
+                            if (obj.featureType === 'Circle') {
+                                return true
+                            }
+                            const str = e.coordinate.join(',')
+                            let flag = true
+                            // 进行延时判断,避免只要鼠标不移动,单击后间隔很久也会视为双击,
+                            if (!drawLastPointTimer && str === drawLastPoint) {
+                                flag = false
+                            } else {
+                                if (drawLastPointTimer) {
+                                    clearTimeout(drawLastPointTimer)
+                                }
+                                drawLastPoint = str
+                            }
+                            drawLastPointTimer = setTimeout(() => {
+                                drawLastPointTimer = null
+                            }, 1000)
+                            return flag
+                        },
+                        finishCondition: (e) => {
+                            if (obj.featureType !== 'Circle') {
+                                return true
+                            }
+                            let flag = true
+                            //  圆形进行双击延时监听判断
+                            if (!drawCircleDBClickTimer) {
+                                flag = false
+                            }
+                            if (drawCircleDBClickTimer) {
+                                clearTimeout(drawCircleDBClickTimer)
+                            }
+                            drawCircleDBClickTimer = setTimeout(() => {
+                                drawCircleDBClickTimer = null
+                            }, 1000)
+                            return flag
+                        },
+                        source: _source,//测量绘制层数据源
+                        type: obj.rectangle ? 'LineString' : obj.featureType,  //几何图形类型
+                        // @ts-ignore
+                        // geometryFunction: createBox(),
+                        geometryFunction: obj.rectangle ? createBox() : null,
+                        // geometryFunction: createRegularPolygon(6),
+                        style: commonStyle(obj.featureType === 'Point' ? true : false),
+                    });
+                    draw.set('showText', obj.featureType === 'Point' ? true : false)
+                    draw.set(drawFlag[0], drawFlag[1])
+                    draw.set(id, id)
+                    createMeasureTooltip(); //创建测量工具提示框
+                    createHelpTooltip(); //创建帮助提示框
+                    map.addInteraction(draw);
+                    let listener;
+                    //绑定交互绘制工具开始绘制的事件
+                    const drawstartHandle = (evt) => {
+                        store.commit('easyMap/SET_IS_DRAWING', true)
+                        sketch = evt.feature; //绘制的要素
+                        let tooltipCoord = evt.coordinate;// 绘制的坐标
+                        //绑定change事件,根据绘制几何类型得到测量长度值或面积值,并将其设置到测量工具提示框中显示
+                        listener = sketch.getGeometry().on('change', function (evt) {
+                            const geom = evt.target
+                            let output;
+                            if (geom.getType() === 'LineString') {
+                                output = formatLength(geom);//长度值
+                                tooltipCoord = geom.getLastCoordinate();//坐标
+                            } else if (geom.getType() === 'Polygon') {
+                                output = formatArea(geom);//面积值
+                                tooltipCoord = geom.getInteriorPoint().getCoordinates();//坐标
+                            } else if (geom.getType() === 'Circle') {
+                                output = formatArea(geom, 'circle');//面积值
+                                tooltipCoord = geom.getCenter()
+                            }
+                            toolDrawTooltipElement.innerHTML = output;//将测量值设置到测量工具提示框中显示
+                            measureTooltip.setPosition(tooltipCoord);//设置测量工具提示框的显示位置
+                        });
+                    }
+                    draw.on('drawstart', drawstartHandle);
+                    //绑定交互绘制工具结束绘制的事件
+                    const copy = (value) => {
+                        const str = document.createElement('input')
+                        str.setAttribute('value', value)
+                        document.body.appendChild(str)
+                        str.select()
+                        document.execCommand('copy')
+                        document.body.removeChild(str)
+                    }
+                    const drawendHandle = (evt) => {
+                        map.removeInteraction(map.getInteractions().getArray().filter(v => v.get(id) === id)[0]);
+                        // 标绘的时候不需要最终结果dom
+                        map.removeOverlay(map.getOverlayById('baseDrawHelpTooltipElementId'))
+                        toolDrawTooltipElement.parentNode.removeChild(toolDrawTooltipElement);
+                        sketch = null; //置空当前绘制的要素对象
+                        toolDrawTooltipElement = null; //置空测量工具提示框对象
+                        toolDrawHelpTooltipElement.parentNode.removeChild(toolDrawHelpTooltipElement);
+                        toolDrawHelpTooltipElement = null; //置空测量工具提示框对象
+                        unByKey(listener);
+                        draw.un('drawstart', drawstartHandle);
+                        draw.un('drawend', drawendHandle);
+                        map.removeInteraction(map.getInteractions().getArray().filter(v => v.get(id) === id)[0]);
+                        map.un('pointermove', pointerMoveHandler)
+                        const featEnd = evt.feature
+                        featEnd.set('isInit', true)
+                        featEnd.set(layerFlag[0], layerFlag[1])
+                        featEnd.setId(v4())
+                        store.commit('easyMap/SET_IS_TOOLING', false)
+                        setTimeout(() => {
+                            store.commit('easyMap/SET_IS_DRAWING', false)
+                        }, 600)
+                    }
+                    draw.on('drawend', drawendHandle);
+                }
+                addInteraction(); //调用加载绘制交互控件方法,添加绘图进行测量
+                const pointerMoveHandler = (evt) => {
+                    if (evt.dragging) {
+                        return;
+                    }
+                    let helpMsg = '单击开始标绘';//当前默认提示信息
+                    //判断绘制几何类型设置相应的帮助提示信息
+                    if (sketch) {
+                        const geom = sketch.getGeometry()
+                        helpMsg = continueMsg;
+                        // if (geom.getType() === 'Polygon') {
+                        //     helpMsg = continueMsg; //绘制多边形时提示相应内容
+                        // } else if (geom.getType() === 'LineString') {
+                        //     helpMsg = continueMsg; //绘制线时提示相应内容
+                        // }
+                    }
+                    toolDrawHelpTooltipElement.innerHTML = helpMsg; //将提示信息设置到对话框中显示
+                    helpTooltip.setPosition(evt.coordinate);//设置帮助提示框的位置
+                    toolDrawHelpTooltipElement.classList.remove('hidden');//移除帮助提示框的隐藏样式进行显示
+                };
+                map.on('pointermove', pointerMoveHandler); //地图容器绑定鼠标移动事件,动态显示帮助提示框内容
+                //地图绑定鼠标移出事件,鼠标移出时为帮助提示框设置隐藏样式
+                try {
+                    map.getViewport().on('mouseout', () => {
+                        toolDrawHelpTooltipElement.addClass('hidden');
+                    });
+                } catch (e) {
+                }
+            }
+        }
+        resolve(() => {
+            const oldLayer = map.getLayers().getArray().filter(v => v.get(layerFlag[0]) === layerFlag[1])
+            if (oldLayer) {
+                oldLayer[0].setStyle(commonStyle(true))
+            }
+            // const oldDraw = map.getInteractions().getArray().filter(v => v.get(drawFlag[0]) === drawFlag[1])
+            // if (oldDraw) {
+            //     oldDraw[0].setStyle(commonStyle(oldDraw[0].get('showText')))
+            // }
+        })
+    }))
+}
+
+export const refreshModify = (map, _source) => {
+    const oldModify = map.getInteractions().getArray().filter(v => v.get(modifyFlag[0]) === modifyFlag[1])
+    if (oldModify) {
+        map.removeInteraction(oldModify[0])
+    }
+    const modifyInteraction = new Modify({
+        source: _source,
+        pixelTolerance: 1
+    });
+    modifyInteraction.set(modifyFlag[0], modifyFlag[1])
+    map.addInteraction(modifyInteraction)
+    modifyInteraction.on('modifyend', evt => {
+        try {
+            const feat = evt.features.item(0)
+        } catch {
+        }
+    })
+}
+
+const initMarkClose = (map) => {
+    const id = 'markCloseOverlay'
+    if (map.getOverlayById(id)) {
+        closeOverlay = map.getOverlayById(id)
+    } else {
+        const dom = document.createElement('div')
+        dom.className = 'close-dom'
+        const img = document.createElement('img')
+        img.src = CloseIcon
+        img.className = '__hover'
+        dom.appendChild(img)
+        img.onclick = () => {
+            const l = map.getLayers().getArray().filter(v => v.get(layerFlag[0]) === layerFlag[1])?.[0]
+            if (l) {
+                const feat = l.getSource().getFeatureById(tempUUID)
+                if (feat) {
+                    l.getSource().removeFeature(feat)
+                    tempUUID = ''
+                    closeOverlay.getElement().style.display = 'none'
+                    closeOverlay.setPosition(undefined)
+                    refreshModify(map, l.getSource())
+                }
+            }
+        };
+        closeOverlay = new ol.Overlay({
+            id: id,
+            element: dom,
+            autoPan: false,
+            offset: [0, -10],
+            positioning: 'bottom-center',
+            stopEvent: true,
+            autoPanAnimation: {
+                duration: 250
+            }
+        })
+        map.addOverlay(closeOverlay)
+        map.on('singleclick', (e) => {
+            let flag = false
+            map.forEachFeatureAtPixel(e.pixel, (f) => {
+                if (!flag && f.get(layerFlag[0]) === layerFlag[1] && f.get('isInit')) {
+                    flag = true
+                    if (tempUUID !== f.getId()) {
+                        tempUUID = f.getId()
+                        closeOverlay.getElement().style.display = 'unset'
+                        closeOverlay.setPosition(e.coordinate)
+                    } else {
+                        tempUUID = ''
+                        closeOverlay.setPosition(undefined)
+                    }
+                }
+            }, {
+                hitTolerance: 0,
+            });
+        })
+    }
+}

+ 0 - 45
src/components/easyMap/func/measure.scss

@@ -1,45 +0,0 @@
-.tooltip {
-  position: relative;
-  background: rgba(0, 0, 0, 0.5);
-  border-radius: 4px;
-  color: white;
-  padding: 4px 8px;
-  white-space: nowrap;
-}
-
-.tooltip-measure {
-  opacity: 1;
-  font-weight: bold;
-}
-
-.tooltip-static {
-  background-color: #ffcc33;
-  color: black;
-  border: 1px solid white;
-}
-
-.tooltip-measure:before,
-.tooltip-static:before {
-  border-top: 6px solid rgba(0, 0, 0, 0.5);
-  border-right: 6px solid transparent;
-  border-left: 6px solid transparent;
-  content: "";
-  position: absolute;
-  bottom: -6px;
-  margin-left: -7px;
-  left: 50%;
-}
-
-.tooltip-static:before {
-  border-top-color: #ffcc33;
-}
-.lineDel {
-  width: 16px;
-  height: 16px;
-  display: inline-block;
-  vertical-align: middle;
-  margin-left: 10px;
-  cursor: pointer;
-  background: url('@/assets/images/map/lineDel.png') no-repeat;
-  background-size: 100% 100%;
-}

+ 40 - 4
src/components/easyMap/func/measure.ts

@@ -9,12 +9,18 @@ import * as coordinate from 'ol/coordinate'
 import * as control from 'ol/control'
 import * as sphere from 'ol/sphere'
 import { unByKey } from 'ol/Observable'
+import './dom.scss'
 import {createBox} from "ol/interaction/Draw";
 import {Circle, LineString, Polygon} from "ol/geom";
+import {v4} from "uuid";
+import store from "@/store";
 
 const layerFlag = ['layerName', 'measureLayer']
 let measureTooltipElement;
 let helpTooltipElement;
+let helpTooltipMap = new Map()
+let measureTooltipMap = new Map()
+let dom: any = []
 const typeMapper = new Map([
     ['line', 'LineString'],
     ['rectangle', 'LineString'],
@@ -27,7 +33,9 @@ const typeMapper = new Map([
  * @param typeSelect    line线,rectangle矩形,polygon多边形,circle圆形
  */
 export default function Measure (map, typeSelect) {
-    if (!measureTooltipElement) {
+    // @ts-ignore
+    if (!measureTooltipElement && !store.state.easyMap.isTooling) {
+        store.commit('easyMap/SET_IS_TOOLING', true)
         let _source
         const realLayer = map.getLayers().getArray().filter(v => v.get(layerFlag[0]) === layerFlag[1])
         if (realLayer[0]) {
@@ -57,6 +65,7 @@ export default function Measure (map, typeSelect) {
             map.addLayer(_vector);
         }
         let sketch;
+        const uuid = v4()
         let helpTooltip;
         let measureTooltip;
         let continueMsg = '双击结束测量';
@@ -76,6 +85,7 @@ export default function Measure (map, typeSelect) {
                 positioning: 'bottom-center'
             });
             map.addOverlay(measureTooltip);
+            measureTooltipMap.set(uuid, measureTooltip)
         }
         const createHelpTooltip = () => {
             const id = 'helpTooltipElementId'
@@ -92,6 +102,7 @@ export default function Measure (map, typeSelect) {
                 positioning: 'center-left'
             });
             map.addOverlay(helpTooltip);
+            helpTooltipMap.set(uuid, helpTooltip)
         }
         const formatLength = (line) => {
             // 获取投影坐标系
@@ -216,6 +227,7 @@ export default function Measure (map, typeSelect) {
             let listener;
             //绑定交互绘制工具开始绘制的事件
             const drawstartHandle = (evt) => {
+                store.commit('easyMap/SET_IS_DRAWING', true)
                 sketch = evt.feature; //绘制的要素
                 let tooltipCoord = evt.coordinate;// 绘制的坐标
                 //绑定change事件,根据绘制几何类型得到测量长度值或面积值,并将其设置到测量工具提示框中显示
@@ -251,6 +263,7 @@ export default function Measure (map, typeSelect) {
                 const del: any = document.createElement("div");
                 del.className = "lineDel";
                 measureTooltipElement.append(del);
+                dom.push(del.parentElement.parentElement)
                 del.onclick = () => {
                     _source.removeFeature(evt.feature)
                     const b = del.parentElement.parentElement
@@ -275,6 +288,10 @@ export default function Measure (map, typeSelect) {
                 draw.un('drawend', drawendHandle);
                 map.removeInteraction(map.getInteractions().getArray().filter(v => v.get(id) === id)[0]);
                 map.un('pointermove', pointerMoveHandler)
+                store.commit('easyMap/SET_IS_TOOLING', false)
+                setTimeout(() => {
+                    store.commit('easyMap/SET_IS_DRAWING', false)
+                }, 600)
             }
             draw.on('drawend', drawendHandle);
         }
@@ -300,8 +317,27 @@ export default function Measure (map, typeSelect) {
         };
         map.on('pointermove', pointerMoveHandler); //地图容器绑定鼠标移动事件,动态显示帮助提示框内容
         //地图绑定鼠标移出事件,鼠标移出时为帮助提示框设置隐藏样式
-        map.getViewport().on('mouseout', () => {
-            helpTooltipElement.addClass('hidden');
-        });
+        // map.getViewport().on('mouseout', () => {
+        //     helpTooltipElement.addClass('hidden');
+        // });
     }
 }
+export const clearMeasureDom = (map) => {
+    if (measureTooltipElement) {
+        measureTooltipElement.parentNode.removeChild(measureTooltipElement);
+        measureTooltipElement = null
+    }
+    if (helpTooltipElement) {
+        helpTooltipElement.parentNode.removeChild(helpTooltipElement);
+        helpTooltipElement = null
+    }
+    measureTooltipMap.forEach((v, k) => {
+        map.removeOverlay(v)
+    })
+    helpTooltipMap.forEach((v, k) => {
+        map.removeOverlay(v)
+    })
+    dom.forEach(v => {
+        v?.parentElement?.removeChild(v)
+    })
+}

BIN
src/components/easyMap/images/gis-layout-tools_tool-bz.png


BIN
src/components/easyMap/images/gis-layout-tools_tool-bz_icon.png


BIN
src/components/easyMap/images/gis-layout-tools_tool-cjl.png


BIN
src/components/easyMap/images/gis-layout-tools_tool-cjxmj.png


BIN
src/components/easyMap/images/gis-layout-tools_tool-cymj.png


BIN
src/components/easyMap/images/gis-layout-tools_tool-hdbx.png


BIN
src/components/easyMap/images/gis-layout-tools_tool-hjx.png


BIN
src/components/easyMap/images/gis-layout-tools_tool-hx.png


BIN
src/components/easyMap/images/gis-layout-tools_tool-hy.png


+ 73 - 130
src/components/easyMap/index.vue

@@ -8,128 +8,6 @@
       @olMapLoad="(map) => handleOlMapLoad(map)"
       :layout="layout"
     />
-    <template v-if="drawEditsConfig.show">
-      <div class="draw-edits-config">
-        <div class="draw-edits-config_feature-type">
-          <el-select v-model="drawEditsConfig.featureType" @change="drawEditsSwitchFeatureType">
-            <el-option label="点" value="Point" :disabled="!drawEditsConfig.isPoint"/>
-            <el-option label="线" value="LineString" :disabled="!drawEditsConfig.isLineString"/>
-            <el-option label="多边形" value="Polygon" :disabled="!drawEditsConfig.isPolygon"/>
-          </el-select>
-        </div>
-        <div class="draw-edits-config_position __hover">
-          <el-popover
-              width="500px"
-              placement="top"
-              title="经纬度"
-              trigger="click"
-              v-model:visible="drawEditsConfig.showPosition"
-          >
-            <div class="popover">
-              <CusForm ref="ref_drawEditsForm" labelWidth="0">
-                <CusFormColumn
-                    ref="ref_drawEditsWkt"
-                    required
-                    :span="24"
-                    type="textarea"
-                    :rows="4"
-                    v-model:param="drawEditsConfig.wkt"
-                    :placeholder="drawEditsWktPlaceholderCpt"
-                    :rules="[
-                      {
-                        handle: (val) => drawEditsConfig.featureType !== 'Point' || (drawEditsConfig.featureType === 'Point' && $easyMap.validWkt.Point(val)),
-                        message: '点位WKT坐标格式错误'
-                      },
-                      {
-                        handle: (val) => drawEditsConfig.featureType !== 'LineString' || (drawEditsConfig.featureType === 'LineString' && $easyMap.validWkt.LineString(val)),
-                        message: '线段WKT坐标格式错误'
-                      },
-                      {
-                        handle: (val) => drawEditsConfig.featureType !== 'Polygon' || (drawEditsConfig.featureType === 'Polygon' && $easyMap.validWkt.Polygon(val)),
-                        message: '区域WKT坐标格式错误'
-                      },
-                      {
-                        handle: (val) => drawEditsConfig.featureType !== 'Polygon' || (drawEditsConfig.featureType === 'Polygon' && $easyMap.validWkt.PolygonKinks(val)),
-                        message: '区域坐标不可自相交'
-                      },
-                    ]"
-                />
-              </CusForm>
-
-<!--              <el-input-->
-<!--                  v-model="drawEditsConfig.wkt"-->
-<!--                  type="textarea"-->
-<!--                  :rows="4"-->
-<!--                  placeholder="请输入经纬度"-->
-<!--              ></el-input>-->
-              <div class="footer">
-                <el-button size="small" type="primary" @click="changeWkt">保存</el-button>
-                <el-button size="small" @click="drawEditsConfig.showPosition = false">取消</el-button>
-              </div>
-            </div>
-            <template #reference>
-              <div class="reference">
-                <img src="./images/draw-edits-position.png" alt />
-                <span>经纬度</span>
-              </div>
-            </template>
-          </el-popover>
-        </div>
-        <template v-if="drawEditsConfig.featureType === 'Point'">
-          <div class="draw-edits-config_icon">
-            <img v-if="drawEditsConfig.pointIcon" class="icon" :src="drawEditsConfig.pointIcon"/>
-            <div class="text"><CusEllipsis :value="drawEditsConfig.text || '点位'"/></div>
-          </div>
-        </template>
-        <template v-if="drawEditsConfig.featureType === 'LineString'">
-          <div class="draw-edits-config_split"/>
-          <div class="draw-edits-config_line">
-            <div class="text">线段</div>
-            <el-input-number
-                class="width"
-                v-model="drawEditsConfig.lineWidth"
-                :min="1"
-                :max="100"
-                controls-position="right"
-                step-strictly
-                @change="drawEditsConfig.refreshStyleFunc()"
-            />
-            <el-color-picker v-model="drawEditsConfig.lineColor" show-alpha @change="drawEditsConfig.refreshStyleFunc()"/>
-            <el-select class="type" v-model="drawEditsConfig.lineType" @change="drawEditsConfig.refreshStyleFunc()">
-              <el-option label="—————" :value="0"/>
-              <el-option label="— — — —" :value="1"/>
-              <el-option label="- - - - - -  - -" :value="2"/>
-            </el-select>
-          </div>
-        </template>
-        <template v-if="drawEditsConfig.featureType === 'Polygon'">
-          <div class="draw-edits-config_split"/>
-          <div class="draw-edits-config_line">
-            <div class="text">边框</div>
-            <el-input-number
-                class="width"
-                v-model="drawEditsConfig.polyBorderWidth"
-                :min="1"
-                :max="100"
-                controls-position="right"
-                step-strictly
-                @change="drawEditsConfig.refreshStyleFunc()"
-            />
-            <el-color-picker v-model="drawEditsConfig.polyBorderColor" show-alpha @change="drawEditsConfig.refreshStyleFunc()"/>
-            <el-select class="type" v-model="drawEditsConfig.polyBorderType" @change="drawEditsConfig.refreshStyleFunc()">
-              <el-option label="—————" :value="0"/>
-              <el-option label="— — — —" :value="1"/>
-              <el-option label="- - - - - -  - -" :value="2"/>
-            </el-select>
-          </div>
-          <div class="draw-edits-config_split"/>
-          <div class="draw-edits-config_poly">
-            <div class="text">填充</div>
-            <el-color-picker v-model="drawEditsConfig.polyColor" show-alpha @change="drawEditsConfig.refreshStyleFunc()"/>
-          </div>
-        </template>
-      </div>
-    </template>
     <template v-if="layout === 'info'">
       <div class="easy-map_layout-info">
         <div class="location">
@@ -181,7 +59,7 @@
                     content="测距"
                     placement="right"
                 >
-                  <img class="__hover" src="./images/tools-measure-line.svg" />
+                  <img class="__hover" src="./images/gis-layout-tools_tool-cjl.png" />
                 </el-tooltip>
               </div>
               <div @click="measure('rectangle')" class="__hover">
@@ -191,7 +69,7 @@
                     content="测面积(矩形)"
                     placement="right"
                 >
-                  <img src="./images/tools-measure-rectangle.svg" />
+                  <img src="./images/gis-layout-tools_tool-cjxmj.png" />
                 </el-tooltip>
               </div>
               <div @click="measure('polygon')" class="__hover">
@@ -201,7 +79,7 @@
                     content="测面积(多边形)"
                     placement="right"
                 >
-                  <img src="./images/tools-measure-polygon.svg" />
+                  <img src="./images/gis-layout-tools_tool-cjxmj.png" />
                 </el-tooltip>
               </div>
               <div @click="measure('circle')" class="__hover">
@@ -211,7 +89,57 @@
                     content="测面积(圆形)"
                     placement="right"
                 >
-                  <img src="./images/tools-measure-circle.png" />
+                  <img src="./images/gis-layout-tools_tool-cymj.png" />
+                </el-tooltip>
+              </div>
+              <div @click="markDraw({featureType: 'Point'})" class="__hover">
+                <el-tooltip
+                    class="box-item"
+                    effect="light"
+                    content="标注"
+                    placement="right"
+                >
+                  <img src="./images/gis-layout-tools_tool-bz.png" />
+                </el-tooltip>
+              </div>
+              <div @click="markDraw({featureType: 'LineString'})" class="__hover">
+                <el-tooltip
+                    class="box-item"
+                    effect="light"
+                    content="画线"
+                    placement="right"
+                >
+                  <img src="./images/gis-layout-tools_tool-hx.png" />
+                </el-tooltip>
+              </div>
+              <div @click="markDraw({featureType: 'Polygon', rectangle: true})" class="__hover">
+                <el-tooltip
+                    class="box-item"
+                    effect="light"
+                    content="画矩形"
+                    placement="right"
+                >
+                  <img src="./images/gis-layout-tools_tool-hjx.png" />
+                </el-tooltip>
+              </div>
+              <div @click="markDraw({featureType: 'Polygon'})" class="__hover">
+                <el-tooltip
+                    class="box-item"
+                    effect="light"
+                    content="画多边形"
+                    placement="right"
+                >
+                  <img src="./images/gis-layout-tools_tool-hdbx.png" />
+                </el-tooltip>
+              </div>
+              <div @click="markDraw({featureType: 'Circle'})" class="__hover">
+                <el-tooltip
+                    class="box-item"
+                    effect="light"
+                    content="画圆"
+                    placement="right"
+                >
+                  <img src="./images/gis-layout-tools_tool-hy.png" />
                 </el-tooltip>
               </div>
             </div>
@@ -247,6 +175,8 @@ import ToolsLocationCom from './component/tools/tools-location.vue'
 import * as BaseDraw from './func/base-draw'
 import {ElMessage, ElMessageBox} from "element-plus";
 import './func/dom.scss'
+import * as MarkDraw from './func/mark-draw'
+import * as ol from 'ol'
 
 export default defineComponent({
   name: "EasyMap",
@@ -269,7 +199,7 @@ export default defineComponent({
       toolsShow: {
         location: false,
       },
-      drawEditsConfig: BaseDraw.getBaseDrawConfig()
+      drawEditsConfig: BaseDraw.getBaseDrawConfig(),
     });
 
     const ref_olMap = ref();
@@ -297,6 +227,7 @@ export default defineComponent({
         drawExit,
         zoom: ref_olMap.value.mapBasicInfo.zoom,
         mouse: ref_olMap.value.mapBasicInfo.mouse,
+        markDraw
       });
     };
     const getBBOX = () => {
@@ -400,6 +331,17 @@ export default defineComponent({
       }
       return str
     })
+    const markDraw = (obj) => {
+      const config = Object.assign(MarkDraw.getBaseDrawConfig(), obj)
+      if (config.featureType === 'Point') {
+        config.isPoint = true
+      } else if (config.featureType === 'LineString') {
+        config.isLineString = true
+      } else if (config.featureType === 'Polygon') {
+        config.isPolygon = true
+      }
+      MarkDraw.draw(easyMap.value, config)
+    }
     onMounted(() => {
       nextTick(() => {});
     });
@@ -418,7 +360,8 @@ export default defineComponent({
       drawEditsSwitchFeatureType,
       changeWkt,
       ref_drawEditsForm,
-      drawEditsWktPlaceholderCpt
+      drawEditsWktPlaceholderCpt,
+      markDraw,
     };
   },
 });
@@ -506,8 +449,8 @@ export default defineComponent({
   .easy-map_layout-info {
     position: absolute;
     z-index: 2;
-    top: 10px;
-    left: 10px;
+    bottom: 80px;
+    right: 10px;
     width: 30px;
     background-color: #ffffff;
     display: flex;