Newer
Older
KaiFengH5 / public / static / libs / mapbox / extend / MeatureTool.js
@zhangdeliang zhangdeliang on 24 May 65 KB 项目初始化
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ?
        module.exports = factory() :
        typeof define === 'function' && define.amd ? define(factory) :
            (global = typeof globalThis !== 'undefined' ? globalThis :
                global || self, global.mapboxgl1.MeatureTool = factory(global.mapboxgl1));
}(window, (function (mapboxgl) {

    const css = `
    /* Override default control style */
.mapbox-gl-draw_ctrl-bottom-left,
.mapbox-gl-draw_ctrl-top-left {
  margin-left:0;
  border-radius:0 4px 4px 0;
}
.mapbox-gl-draw_ctrl-top-right,
.mapbox-gl-draw_ctrl-bottom-right {
  margin-right:0;
  border-radius:4px 0 0 4px;
}

.mapbox-gl-draw_ctrl-draw-btn {
  border-color:rgba(0,0,0,0.9);
  color:rgba(255,255,255,0.5);
  width:30px;
  height:30px;
}

.mapbox-gl-draw_ctrl-draw-btn.active,
.mapbox-gl-draw_ctrl-draw-btn.active:hover {
  background-color:rgb(0 0 0/5%);
}
.mapbox-gl-draw_ctrl-draw-btn {
  background-repeat: no-repeat;
  background-position: center;
}

.mapbox-gl-draw_point {
  background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20">%3Cpath d="m10 2c-3.3 0-6 2.7-6 6s6 9 6 9 6-5.7 6-9-2.7-6-6-6zm0 2c2.1 0 3.8 1.7 3.8 3.8 0 1.5-1.8 3.9-2.9 5.2h-1.7c-1.1-1.4-2.9-3.8-2.9-5.2-.1-2.1 1.6-3.8 3.7-3.8z"/>%3C/svg>');
}
.mapbox-gl-draw_polygon {
  background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20">%3Cpath d="m15 12.3v-4.6c.6-.3 1-1 1-1.7 0-1.1-.9-2-2-2-.7 0-1.4.4-1.7 1h-4.6c-.3-.6-1-1-1.7-1-1.1 0-2 .9-2 2 0 .7.4 1.4 1 1.7v4.6c-.6.3-1 1-1 1.7 0 1.1.9 2 2 2 .7 0 1.4-.4 1.7-1h4.6c.3.6 1 1 1.7 1 1.1 0 2-.9 2-2 0-.7-.4-1.4-1-1.7zm-8-.3v-4l1-1h4l1 1v4l-1 1h-4z"/>%3C/svg>');
}
.mapbox-gl-draw_line {
  background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20">%3Cpath d="m13.5 3.5c-1.4 0-2.5 1.1-2.5 2.5 0 .3 0 .6.2.9l-3.8 3.8c-.3-.1-.6-.2-.9-.2-1.4 0-2.5 1.1-2.5 2.5s1.1 2.5 2.5 2.5 2.5-1.1 2.5-2.5c0-.3 0-.6-.2-.9l3.8-3.8c.3.1.6.2.9.2 1.4 0 2.5-1.1 2.5-2.5s-1.1-2.5-2.5-2.5z"/>%3C/svg>');
}
.mapbox-gl-draw_trash {
  background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20">%3Cpath d="M10,3.4 c-0.8,0-1.5,0.5-1.8,1.2H5l-1,1v1h12v-1l-1-1h-3.2C11.5,3.9,10.8,3.4,10,3.4z M5,8v7c0,1,1,2,2,2h6c1,0,2-1,2-2V8h-2v5.5h-1.5V8h-3 v5.5H7V8H5z"/>%3C/svg>');
}
.mapbox-gl-draw_uncombine {
  background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20">%3Cpath d="m12 2c-.3 0-.5.1-.7.3l-1 1c-.4.4-.4 1 0 1.4l1 1c.4.4 1 .4 1.4 0l1-1c.4-.4.4-1 0-1.4l-1-1c-.2-.2-.4-.3-.7-.3zm4 4c-.3 0-.5.1-.7.3l-1 1c-.4.4-.4 1 0 1.4l1 1c.4.4 1 .4 1.4 0l1-1c.4-.4.4-1 0-1.4l-1-1c-.2-.2-.4-.3-.7-.3zm-7 1c-1 0-1 1-.5 1.5.3.3 1 1 1 1l-1 1s-.5.5 0 1 1 0 1 0l1-1 1 1c.5.5 1.5.5 1.5-.5v-4zm-5 3c-.3 0-.5.1-.7.3l-1 1c-.4.4-.4 1 0 1.4l4.9 4.9c.4.4 1 .4 1.4 0l1-1c.4-.4.4-1 0-1.4l-4.9-4.9c-.1-.2-.4-.3-.7-.3z"/>%3C/svg>');
}
.mapbox-gl-draw_combine {
  background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20">%3Cpath d="M12.1,2c-0.3,0-0.5,0.1-0.7,0.3l-1,1c-0.4,0.4-0.4,1,0,1.4l4.9,4.9c0.4,0.4,1,0.4,1.4,0l1-1 c0.4-0.4,0.4-1,0-1.4l-4.9-4.9C12.6,2.1,12.3,2,12.1,2z M8,8C7,8,7,9,7.5,9.5c0.3,0.3,1,1,1,1l-1,1c0,0-0.5,0.5,0,1s1,0,1,0l1-1l1,1 C11,13,12,13,12,12V8H8z M4,10c-0.3,0-0.5,0.1-0.7,0.3l-1,1c-0.4,0.4-0.4,1,0,1.4l1,1c0.4,0.4,1,0.4,1.4,0l1-1c0.4-0.4,0.4-1,0-1.4 l-1-1C4.5,10.1,4.3,10,4,10z M8,14c-0.3,0-0.5,0.1-0.7,0.3l-1,1c-0.4,0.4-0.4,1,0,1.4l1,1c0.4,0.4,1,0.4,1.4,0l1-1 c0.4-0.4,0.4-1,0-1.4l-1-1C8.5,14.1,8.3,14,8,14z"/>%3C/svg>');
}

.mapboxgl-map.mouse-pointer .mapboxgl-canvas-container.mapboxgl-interactive {
  cursor: pointer;
}
.mapboxgl-map.mouse-move .mapboxgl-canvas-container.mapboxgl-interactive {
  cursor: move;
}
.mapboxgl-map.mouse-add .mapboxgl-canvas-container.mapboxgl-interactive {
  cursor: crosshair;
}
.mapboxgl-map.mouse-move.mode-direct_select .mapboxgl-canvas-container.mapboxgl-interactive {
  cursor: grab;
  cursor: -moz-grab;
  cursor: -webkit-grab;
}
.mapboxgl-map.mode-direct_select.feature-vertex.mouse-move .mapboxgl-canvas-container.mapboxgl-interactive {
  cursor: move;
}
.mapboxgl-map.mode-direct_select.feature-midpoint.mouse-pointer .mapboxgl-canvas-container.mapboxgl-interactive {
  cursor: cell;
}
.mapboxgl-map.mode-direct_select.feature-feature.mouse-move .mapboxgl-canvas-container.mapboxgl-interactive {
  cursor: move;
}
.mapboxgl-map.mode-static.mouse-pointer  .mapboxgl-canvas-container.mapboxgl-interactive {
  cursor: grab;
  cursor: -moz-grab;
  cursor: -webkit-grab;
}

.mapbox-gl-draw_boxselect {
    pointer-events: none;
    position: absolute;
    top: 0;
    left: 0;
    width: 0;
    height: 0;
    background: rgba(0,0,0,.1);
    border: 2px dotted #fff;
    opacity: 0.5;
}
    .measure-move {
    border-radius: 3px;
    height: 16px;
    line-height: 16px;
    padding: 0 3px;
    font-size: 12px;
    box-shadow: 0 0 0 1px #ccc;
    float: right;
    cursor: default;
}

.measure-result {
    border-radius: 3px;
    height: 16px;
    line-height: 16px;
    padding: 0 3px;
    font-size: 12px;
    box-shadow: 0 0 0 1px #ccc;
    float: right;
    cursor: default;
    z-index: 10;
}

.close {
    width: 3px;
    height: 14px;
    text-align: center;
    border-radius: 3px;
    padding-top: 0px;
    padding-right: 10px;
    box-shadow: 0 0 0 0px #ccc;
    cursor: pointer;
    background: url(../measureicon/close.png) no-repeat center;
    border: 1px solid rgba(100, 100, 100, 0)
}

.clear {
    width: 3px;
    height: 14px;
    text-align: center;
    border-radius: 3px;
    padding-right: 10px;
    box-shadow: 0 0 0 0px #ccc;
    cursor: pointer;
    float: right;
    background: url(../measureicon/delete.png) no-repeat center;
    border: 1px solid rgba(100, 100, 100, 0)
}

.edit {
    width: 3px;
    height: 14px;
    text-align: center;
    border-radius: 3px;
    padding-right: 10px;
    box-shadow: 0 0 0 0px #ccc;
    cursor: pointer;
    float: right;
    background: url(../measureicon/edit.png) no-repeat center;
    border: 1px solid rgba(100, 100, 100, 0)
}

.close:hover {
    border: 1px solid rgba(52, 98, 152, 1);
}

.clear:hover {
    border: 1px solid rgba(52, 98, 152, 1);
}

.edit:hover {
    border: 1px solid rgba(52, 98, 152, 1);
}
`;
    document.write(`<style type='text/css'>${css}</style>`);

    return class {
        constructor(map) {
            this.map = map;
        }

        layerDistanceList = []
        layerAreaList = []
        layerPointList = []
        setDistance = () => {}
        setArea = () => { }

        /**
         * 测量距离
         * @param {*} layerId
         */
        measureDistance(layerId,isP=true,callback = ()=>{}) {
            this.layerDistanceList.push(layerId)
            var isMeasure = true
            const map = this.map
            map.doubleClickZoom.disable()
            let catchMark = null
            let isEdit = false
            let Geolist = []
            let dragPointOrder = 0
            let pointOnLine = [0, 0]

            const jsonPoint = {
                type: 'FeatureCollection',
                features: [],
            }
            const jsonLine = {
                type: 'FeatureCollection',
                features: [],
            }

            // 添加测量结果弹窗
            const ele = document.createElement('div')
            ele.setAttribute('class', 'measure-move')
            const option = {
                element: ele,
                anchor: 'left',
                offset: [8, 0],
            }
            const tooltip = new mapboxgl.Marker(option).setLngLat([0, 0]);
            if(isP) tooltip.addTo(map);

            // 添加测量图层
            map.addSource('points' + layerId, {
                type: 'geojson',
                data: jsonPoint,
            })
            map.addSource('point-move' + layerId, {
                type: 'geojson',
                data: jsonPoint,
            })
            map.addSource('line' + layerId, {
                type: 'geojson',
                data: jsonLine,
            })
            map.addSource('line-move' + layerId, {
                type: 'geojson',
                data: jsonLine,
            })
            map.addSource('point-follow' + layerId, {
                type: 'geojson',
                data: jsonPoint,
            })
            map.addLayer({
                id: 'line' + layerId,
                type: 'line',
                source: 'line' + layerId,
                paint: {
                    'line-color': '#ff0000',
                    'line-width': 2,
                    'line-opacity': 0.65,
                },
            })
            map.addLayer({
                id: 'line-move' + layerId,
                type: 'line',
                source: 'line-move' + layerId,
                paint: {
                    'line-color': '#ff0000',
                    'line-width': 2,
                    'line-opacity': 0.65,
                    'line-dasharray': [5, 2],
                },
            })
            map.addLayer({
                id: 'points' + layerId,
                type: 'circle',
                source: 'points' + layerId,
                paint: {
                    'circle-color': '#ffffff',
                    'circle-radius': 3.5,
                    'circle-stroke-width': 1.5,
                    'circle-stroke-color': '#ff0000',
                },
            })
            map.addLayer({
                id: 'point-move' + layerId,
                type: 'circle',
                source: 'point-move' + layerId,
                paint: {
                    'circle-color': '#ffffff',
                    'circle-radius': 3.5,
                    'circle-stroke-width': 1.5,
                    'circle-stroke-color': '#ff0000',
                },
            })
            // 活动点可以选择用图层,也可以选择用Mark
            map.addLayer({
                id: 'point-follow' + layerId,
                type: 'circle',
                source: 'point-follow' + layerId,
                paint: {
                    'circle-color': '#199afc',
                    'circle-radius': 5.5,
                    'circle-stroke-width': 1.5,
                    'circle-stroke-color': '#ffffff',
                },
            })

            // 清除面积测量
            this.setArea = () => {
                isMeasure = false
               if(map.getLayer('point-move' + layerId)) map.removeLayer('point-move' + layerId)
                if(map.getLayer('line-move' + layerId)) map.removeLayer('line-move' + layerId)

                return isMeasure
            }

            /**
             * 添加点
             * @param {*} _e
             */
            function addPointforJSON(_e) {
                if (isMeasure) {
                    const point = {
                        type: 'Feature',
                        geometry: {
                            type: 'Point',
                            coordinates: [_e.lngLat.lng, _e.lngLat.lat],
                        },
                        properties: {
                            id: String(new Date().getTime()),
                        },
                    }
                    jsonPoint.features.push(point)
                    map.getSource('points' + layerId).setData(jsonPoint)
                    drawLine(jsonPoint)
                    addMeasureRes(jsonPoint)
                }
            }

            /**
             * 绘制线
             * @param {*} jsonPoint
             */
            function drawLine(jsonPoint) {
                if (jsonPoint.features.length > 1) {
                    jsonLine.features = []
                    for (let i = 0; i < jsonPoint.features.length - 1; i++) {
                        const coords = jsonPoint.features[i].geometry.coordinates
                        const next_coords = jsonPoint.features[i + 1].geometry.coordinates
                        jsonLine.features.push({
                            type: 'Feature',
                            geometry: {
                                type: 'LineString',
                                coordinates: [coords, next_coords],
                            },
                        })
                    }
                    map.getSource('line' + layerId).setData(jsonLine)
                }
            }

            /**
             * 添加dom
             * @param {*} jsonPoint 点集
             */
            function addMeasureRes(jsonPoint) {

                if (isP && jsonPoint.features.length > 0) {
                    removedom()
                    const pointList = []
                    for (let i = 0; i < jsonPoint.features.length; i++) {
                        const coords = jsonPoint.features[i].geometry.coordinates
                        pointList.push(coords)

                        const close = document.createElement('div')
                        close.setAttribute('class', `measure-result ${layerId} close`)
                        close.onclick = (__e) => {
                            // 移除点
                            __e.stopPropagation()
                            removePoint(coords)
                            map.off('mousemove', onMouseMove)
                            map.off('mousedown', onmousedown)
                            if (catchMark) {
                                catchMark.remove()
                            }
                        }

                        const clear = document.createElement('div')
                        clear.setAttribute('class', `measure-result ${layerId} clear`)
                        clear.onclick = (__e) => {
                            // 全部删除
                            __e.stopPropagation()
                            removeLayer()
                            map.off('mousemove', onMouseMove)
                            map.off('mousedown', onmousedown)
                            if (catchMark) {
                                catchMark.remove()
                            }
                        }

                        const edit = document.createElement('div')
                        edit.setAttribute('class', `measure-result ${layerId} edit`)
                        edit.onclick = (__e) => {
                            // 编辑线
                            __e.stopPropagation()
                            map.off('mousemove', onMouseMove)
                            map.off('mousedown', onmousedown)
                            if (catchMark) {
                                catchMark.remove()
                            }
                            editLine()
                        }

                        const element = document.createElement('div')
                        element.setAttribute('class', 'measure-result ' + layerId)
                        const option = {
                            element: element,
                            anchor: 'left',
                            offset: [8, 0],
                        }
                        element.innerHTML = i === 0 ? '起点' : getLength(pointList)
                        if ((jsonPoint.features.length === i + 1) & !isMeasure) {
                            element.appendChild(edit)
                            element.appendChild(clear)
                        }
                        element.appendChild(close)
                        new mapboxgl.Marker(option).setLngLat(coords).addTo(map)
                    }
                }
            }

            /**
             * 移除点
             * @param {*} coords 点坐标
             */
            function removePoint(coords) {
                if (jsonPoint.features.length > 0) {
                    if (jsonPoint.features.length === 2) {
                        jsonPoint.features = []
                        jsonLine.features = []
                        map.getSource('points' + layerId).setData(jsonPoint)
                        map.getSource('line' + layerId).setData(jsonLine)
                        removedom()
                    } else {
                        for (let i = 0; i < jsonPoint.features.length; i++) {
                            if (
                                (jsonPoint.features[i].geometry.coordinates[0] === coords[0]) &
                                (jsonPoint.features[i].geometry.coordinates[1] === coords[1])
                            ) {
                                jsonPoint.features.splice(i, 1)
                            }
                        }
                        drawLine(jsonPoint)
                        addMeasureRes(jsonPoint)
                        map.getSource('points' + layerId).setData(jsonPoint)
                    }
                }
            }

            /**
             * 计算长度
             * @param {*} pointList
             * @returns
             */
            function getLength(pointList) {
                const line = turf.lineString(pointList)
                let len = turf.length(line)
                if (len < 1) {
                    len = Math.round(len * 1000) + '米'
                } else {
                    len = len.toFixed(2) + '公里'
                }
                return len
            }

            /**
             * 移除dom
             */
            function removedom() {
                const dom = document.getElementsByClassName('measure-result ' + layerId)
                const len = dom.length
                if (len) {
                    for (let i = len - 1; i >= 0; i--) {
                        if (dom[i]) dom[i].remove()
                    }
                }
            }

            /**
             * 移除图层
             */
            function removeLayer() {
                jsonPoint.features = []
                jsonLine.features = []
                if(map.getLayer('points' + layerId)) map.removeLayer('points' + layerId)
                if(map.getLayer('line' + layerId)) map.removeLayer('line' + layerId)
                removedom()
            }

            /**
             * 鼠标move事件
             * @param {} _e
             */
            function mouseMove(_e) {
                if (isMeasure) {
                    map.getCanvas().style.cursor = 'default'
                    var coords = [_e.lngLat.lng, _e.lngLat.lat]
                    const jsonp = {
                        type: 'Feature',
                        geometry: {
                            type: 'Point',
                            coordinates: coords,
                        },
                    }
                    map.getSource('point-move' + layerId).setData(jsonp)

                    if (jsonPoint.features.length > 0) {
                        const pointList = []
                        for (let i = 0; i < jsonPoint.features.length; i++) {
                            const coord = jsonPoint.features[i].geometry.coordinates
                            pointList.push(coord)
                        }
                        pointList.push(coords)
                        const prev = jsonPoint.features[jsonPoint.features.length - 1]
                        const jsonl = {
                            type: 'Feature',
                            geometry: {
                                type: 'LineString',
                                coordinates: [prev.geometry.coordinates, coords],
                            },
                        }
                        map.getSource('line-move' + layerId).setData(jsonl)
                         ele.innerHTML = getLength(pointList)
                        tooltip.setLngLat(coords)
                    }
                }
            }

            /**
             * 绘制完成
             * @param {*} _e
             */
            function finish(_e) {
                if (isMeasure) {
                    isMeasure = false
                    var coords = [_e.lngLat.lng, _e.lngLat.lat]
                    removePoint(coords)
                    if(map.getLayer('point-move' + layerId)) map.removeLayer('point-move' + layerId)
                    if(map.getLayer('line-move' + layerId)) map.removeLayer('line-move' + layerId)
                    map.getCanvas().style.cursor = 'default'
                    tooltip.remove();
                    let features = map.getSource('line'+layerId)._data.features;
                    let coordinates =  features.map(i => turf.coordAll(i)[0]);
                    if(coordinates.length ==1) coordinates = turf.coordAll(features[0])
                    callback(turf.lineString(coordinates));
                }
            }

            map.on('click', function (_e) {
                addPointforJSON(_e)
            })

            map.on('mousemove', function (_e) {
                mouseMove(_e)
            })

            map.on('dblclick', function (_e) {
                finish(_e)
            })

            /**
             * 编辑测量线
             */
            function editLine() {
                catchMark = createMarker()
                UpdataGeolist()

                map.on('mousemove', onMouseMove)
                map.on('mousedown', onmousedown)
            }

            function onMouseMove(e) {
                const moveCoord = [e.lngLat.lng, e.lngLat.lat]

                if (jsonPoint.features.length > 1) {
                    // 计算当前指针与线段最近的点
                    pointOnLine = getNearestPointOnLine(Geolist, moveCoord) // 自己计算
                    const screenOnLine = Object.values(map.project(pointOnLine)) // 线上屏幕坐标
                    const screenP = [e.point.x, e.point.y]
                    const screenDist = screenDistance(screenOnLine, screenP) // 距离
                    if (screenDist < 15) {
                        isEdit = true
                        catchMark.setLngLat(pointOnLine).addTo(map)
                        catchMark.getElement().style.display = 'block'
                    } else {
                        isEdit = false
                        catchMark.getElement().style.display = 'none'
                    }
                } else {
                    isEdit = false
                    catchMark.getElement().style.display = 'none'
                    map.dragPan.enable()
                }
            }

            function onmousedown(e) {
                if (isEdit) {
                    map.dragPan.disable()
                    let isExist = false

                    // 首先判断编辑点是否是存在(存在修改原来点,不存在新加点)
                    for (let i = 0; i < jsonPoint.features.length; i++) {
                        const coord = jsonPoint.features[i].geometry.coordinates
                        if (coord[0] === pointOnLine[0] && coord[1] === pointOnLine[1]) {
                            isExist = true
                        }
                    }

                    // 获取编辑点在列表中的位置
                    dragPointOrder = getDragCoords(pointOnLine, Geolist)

                    if (!isExist) {
                        // 添加编辑点
                        const point = {
                            type: 'Feature',
                            geometry: {
                                type: 'Point',
                                coordinates: pointOnLine,
                            },
                            properties: {
                                id: String(new Date().getTime()),
                            },
                        }
                        jsonPoint.features.splice(dragPointOrder, 0, point)

                        // 更新绘制要素
                        updataFeature()
                    }

                    map.on('mousemove', onDrag)
                    map.on('mouseup', onMouseup)
                }
            }

            function onDrag(e) {
                // 开始计时
                // var start = new Date().getTime()
                const movePoint = [e.lngLat.lng, e.lngLat.lat]

                // 点跟随鼠标移动
                jsonPoint.features[dragPointOrder].geometry.coordinates = movePoint

                // 更新绘制要素
                updataFeature()

                // 计时结束
                // var end1 = new Date().getTime()
                // console.log('渲染时间:', end1 - start + 'ms')
            }

            // 更新绘制要素
            function updataFeature() {
                UpdataGeolist()
                map.getSource('points' + layerId).setData(jsonPoint)
                drawLine(jsonPoint)
                addMeasureRes(jsonPoint)
            }

            function onMouseup(e) {
                map.off('mousemove', onDrag)
                map.dragPan.enable()
            }

            // 创建Marker
            function createMarker() {
                const markerParam = {
                    map: this.map,
                    lngLat: [0, 0],
                    height: 13,
                    width: 13,
                    size: 13,
                    isDrag: false,
                    cursor: 'default',
                }
                return new mapboxgl.Marker().setLngLat(markerParam.lngLat).setDraggable(false).addTo(markerParam.map);
            }

            // 更新点集
            function UpdataGeolist() {
                Geolist = []
                for (let i = 0; i < jsonPoint.features.length; i++) {
                    const coord = jsonPoint.features[i].geometry.coordinates
                    Geolist.push(coord)
                }
            }

            // 计算点到直线最近距离的点
            function getNearestPointOnLine(list, moveCoord) {
                var dis, point1, point2
                for (let i = 0; i < list.length - 1; i++) {
                    const distance = getNearestDistance(moveCoord, list[i], list[i + 1])
                    if (i === 0) {
                        dis = distance
                        point1 = list[i]
                        point2 = list[i + 1]
                    } else {
                        if (distance < dis) {
                            dis = distance
                            point1 = list[i]
                            point2 = list[i + 1]
                        }
                    }
                }
                const Point = getNearestPoint(moveCoord, point1, point2)
                return Point
            }

            // 计算点point到线段point1, point2最近距离
            function getNearestDistance(point, point1, point2) {
                const P = {}
                const A = {}
                const B = {}
                P.x = point[0]
                P.y = point[1]
                A.x = point1[0]
                A.y = point1[1]
                B.x = point2[0]
                B.y = point2[1]
                // 计算向量AP和向量AB的点积
                const dotProduct = (P.x - A.x) * (B.x - A.x) + (P.y - A.y) * (B.y - A.y)
                // 计算向量AB的长度的平方
                const lengthSquare = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y)
                // 计算点P到线段AB的投影点C
                const t = dotProduct / lengthSquare
                const C = { x: A.x + t * (B.x - A.x), y: A.y + t * (B.y - A.y) }
                // 如果点C在线段AB内,则点P到线段AB的最近距离为PC的长度;否则,点P到线段AB的最近距离为PA或PB中的较小值。
                const isInside = dotProduct >= 0 && dotProduct <= lengthSquare
                if (isInside) {
                    return Math.sqrt((P.x - C.x) * (P.x - C.x) + (P.y - C.y) * (P.y - C.y))
                } else {
                    return Math.min(
                        Math.sqrt((P.x - A.x) * (P.x - A.x) + (P.y - A.y) * (P.y - A.y)),
                        Math.sqrt((P.x - B.x) * (P.x - B.x) + (P.y - B.y) * (P.y - B.y))
                    )
                }
            }

            // 计算点到直线最近的点 point点坐标,point1, point2直线两个端点
            function getNearestPoint(point, point1, point2) {
                var x, y, x0, y0, x1, y1, x2, y2
                x0 = point[0]
                y0 = point[1]
                x1 = point1[0]
                y1 = point1[1]
                x2 = point2[0]
                y2 = point2[1]

                if (x1 !== x2 && y1 !== y2) {
                    const a = (y2 - y1) / (x2 - x1)
                    const b = y1 - a * x1
                    const k2 = -1 / a
                    const b2 = y0 - k2 * x0
                    x = (b2 - b) / (a - k2)
                    y = a * x + b
                } else if (x1 === x2) {
                    x = x1
                    y = y0
                } else if (y1 === y2) {
                    x = x0
                    y = y1
                }

                // 点不能超出线段
                if (x1 < x2) {
                    if (x2 < x) {
                        x = x2
                    } else if (x < x1) {
                        x = x1
                    }
                } else {
                    if (x1 < x) {
                        x = x1
                    } else if (x < x2) {
                        x = x2
                    }
                }
                if (y1 < y2) {
                    if (y2 < y) {
                        y = y2
                    } else if (y < y1) {
                        y = y1
                    }
                } else {
                    if (y1 < y) {
                        y = y1
                    } else if (y < y2) {
                        y = y2
                    }
                }

                // 点吸附端点
                const screenX0 = Object.values(map.project([x0, y0])) // 屏幕坐标
                const screenX1 = Object.values(map.project([x1, y1])) // 屏幕坐标
                const screenX2 = Object.values(map.project([x2, y2])) // 屏幕坐标
                const screenDistX1 = screenDistance(screenX0, screenX1) // 距离
                const screenDistX2 = screenDistance(screenX0, screenX2) // 距离
                if (screenDistX1 < 10) {
                    x = x1
                    y = y1
                }
                if (screenDistX2 < 10) {
                    x = x2
                    y = y2
                }

                return [x, y]
            }

            // 屏幕距离
            function screenDistance(point1, point2) {
                const x2 = Math.pow(point1[0] - point2[0], 2)
                const y2 = Math.pow(point1[1] - point2[1], 2)
                const dist = Math.sqrt(x2 + y2)

                return dist
            }

            // 计算编辑点在线段上的添加位置
            function getDragCoords(coords, list) {
                var x, y, x1, y1, x2, y2
                let index = 0
                x = coords[0]
                y = coords[1]

                for (let i = 0; i < list.length - 1; i++) {
                    x1 = list[i][0]
                    y1 = list[i][1]
                    x2 = list[i + 1][0]
                    y2 = list[i + 1][1]

                    if (x === x1 && y === y1) {
                        index = i
                        break
                    } else {
                        // 计算线段的长度
                        const length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
                        // 计算点到线段起点的距离
                        const distance1 = Math.sqrt(Math.pow(x - x1, 2) + Math.pow(y - y1, 2))
                        // 计算点到线段终点的距离
                        const distance2 = Math.sqrt(Math.pow(x - x2, 2) + Math.pow(y - y2, 2))
                        // 如果点到线段两个端点的距离之和等于线段的长度,则点在线段上
                        if (Math.abs(length - distance1 - distance2) < 0.00001) {
                            index = i + 1
                            break
                        }
                    }
                }
                return index
            }
        }

        /**
         * 测量面积
         * @param {*} layerId
         */
        measureArea(layerId,isP=true,callback=()=>{}) {
            this.layerAreaList.push(layerId)
            var isMeasure = true
            const map = this.map
            map.doubleClickZoom.disable()
            let catchMark = null
            let isEdit = false
            let Geolist = []
            let dragPointOrder = 0
            let pointOnLine = [0, 0]

            const jsonPoint = {
                type: 'FeatureCollection',
                features: [],
            }
            const jsonLine = {
                type: 'FeatureCollection',
                features: [],
            }

            const ele = document.createElement('div')
            ele.setAttribute('class', 'measure-move')
            const option = {
                element: ele,
                anchor: 'left',
                offset: [8, 0],
            }
            const tooltip = new mapboxgl.Marker(option).setLngLat([0, 0]);
            if(isP) tooltip.addTo(map);
            map.addSource('points-area' + layerId, {
                type: 'geojson',
                data: jsonPoint,
            })
            map.addSource('point-move' + layerId, {
                type: 'geojson',
                data: jsonPoint,
            })
            map.addSource('line-area' + layerId, {
                type: 'geojson',
                data: jsonLine,
            })
            map.addSource('line-move' + layerId, {
                type: 'geojson',
                data: jsonLine,
            })
            map.addLayer({
                id: 'line-move' + layerId,
                type: 'line',
                source: 'line-move' + layerId,
                paint: {
                    'line-color': '#ff0000',
                    'line-width': 2,
                    'line-opacity': 0.65,
                    'line-dasharray': [5, 2],
                },
            })
            map.addLayer({
                id: 'line-area' + layerId,
                type: 'fill',
                source: 'line-area' + layerId,
                paint: {
                    'fill-color': '#ff0000',
                    'fill-opacity': 0.1,
                },
            })
            map.addLayer({
                id: 'line-area-stroke' + layerId,
                type: 'line',
                source: 'line-area' + layerId,
                paint: {
                    'line-color': '#ff0000',
                    'line-width': 2,
                    'line-opacity': 0.65,
                },
            })
            map.addLayer({
                id: 'points-area' + layerId,
                type: 'circle',
                source: 'points-area' + layerId,
                paint: {
                    'circle-color': '#ffffff',
                    'circle-radius': 3.5,
                    'circle-stroke-width': 1.5,
                    'circle-stroke-color': '#ff0000',
                },
            })
            map.addLayer({
                id: 'point-move' + layerId,
                type: 'circle',
                source: 'point-move' + layerId,
                paint: {
                    'circle-color': '#ffffff',
                    'circle-radius': 3.5,
                    'circle-stroke-width': 1.5,
                    'circle-stroke-color': '#ff0000',
                },
            })

            this.setDistance = () => {
                isMeasure = false
                if(map.getLayer('point-move' + layerId)) map.removeLayer('point-move' + layerId)
                if(map.getLayer('line-move' + layerId)) map.removeLayer('line-move' + layerId)

                return isMeasure
            }

            /**
             * 添加点
             * @param {*} _e
             */
            function addPointforJSON(_e) {
                if (isMeasure) {
                    const point = {
                        type: 'Feature',
                        geometry: {
                            type: 'Point',
                            coordinates: [_e.lngLat.lng, _e.lngLat.lat],
                        },
                        properties: {
                            id: String(new Date().getTime()),
                        },
                    }
                    jsonPoint.features.push(point)
                    map.getSource('points-area' + layerId).setData(jsonPoint)
                    addMeasureRes(jsonPoint)
                }
            }

            /**
             * 添加dom
             * @param {*} jsonPoint 点集
             */
            function addMeasureRes(jsonPoint) {
                if (isP && jsonPoint.features.length > 0) {
                    removedom()
                    const pointList = []
                    for (let i = 0; i < jsonPoint.features.length; i++) {
                        const coords = jsonPoint.features[i].geometry.coordinates
                        pointList.push(coords)

                        const close = document.createElement('div')
                        close.setAttribute('class', `measure-result ${layerId} close`)
                        close.onclick = (__e) => {
                            // 移除点
                            __e.stopPropagation()
                            removePoint(coords)
                            map.off('mousemove', onMouseMove)
                            map.off('mousedown', onmousedown)
                            if (catchMark) {
                                catchMark.remove()
                            }
                        }
                        if ((jsonPoint.features.length === i + 1) & !isMeasure) {
                            const clear = document.createElement('div')
                            clear.setAttribute('class', `measure-result ${layerId} clear`)
                            clear.onclick = (__e) => {
                                // 全部移除
                                __e.stopPropagation()
                                removeLayer()
                                map.off('mousemove', onMouseMove)
                                map.off('mousedown', onmousedown)
                                if (catchMark) {
                                    catchMark.remove()
                                }
                            }

                            const edit = document.createElement('div')
                            edit.setAttribute('class', `measure-result ${layerId} edit`)
                            edit.onclick = (__e) => {
                                // 编辑
                                __e.stopPropagation()
                                map.off('mousemove', onMouseMove)
                                map.off('mousedown', onmousedown)
                                if (catchMark) {
                                    catchMark.remove()
                                }
                                editArea()
                            }

                            const element = document.createElement('div')
                            element.setAttribute('class', 'measure-result ' + layerId)
                            const option = {
                                element: element,
                                anchor: 'left',
                                offset: [0, 0],
                            }
                            element.innerHTML = getArea(pointList)
                            element.appendChild(edit)
                            element.appendChild(clear)
                            element.appendChild(close)
                            new mapboxgl.Marker(option).setLngLat(coords).addTo(map)
                        } else {
                            const option = {
                                element: close,
                                anchor: 'left',
                                offset: [5, -15],
                            }
                            new mapboxgl.Marker(option).setLngLat(coords).addTo(map)
                        }
                    }
                }
            }

            /**
             * 计算面积
             * @param {*} pointList
             * @returns
             */
            function getArea(pointList) {
                pointList.push(pointList[0])
                const polygon = turf.polygon([pointList])
                let area = turf.area(polygon)
                if (area < 10000) {
                    area = Math.round(area) + '平方米'
                } else {
                    area = (area / 1000000).toFixed(2) + '平方公里'
                }
                return area
            }

            /**
             * 移除点
             * @param {*} coords 点坐标
             */
            function removePoint(coords) {
                if (jsonPoint.features.length > 0) {
                    if (jsonPoint.features.length === 3) {
                        jsonPoint.features = []
                        jsonLine.features = []
                        map.getSource('points-area' + layerId).setData(jsonPoint)
                        map.getSource('line-area' + layerId).setData(jsonLine)
                        removedom()
                    } else {
                        for (let i = 0; i < jsonPoint.features.length; i++) {
                            if (
                                (jsonPoint.features[i].geometry.coordinates[0] === coords[0]) &
                                (jsonPoint.features[i].geometry.coordinates[1] === coords[1])
                            ) {
                                jsonPoint.features.splice(i, 1)
                            }
                        }
                        addMeasureRes(jsonPoint)
                        map.getSource('points-area' + layerId).setData(jsonPoint)

                        const pointList = []
                        for (let i = 0; i < jsonPoint.features.length; i++) {
                            const coord = jsonPoint.features[i].geometry.coordinates
                            pointList.push(coord)
                        }
                        const pts = pointList.concat([pointList[0]])
                        const jsona = {
                            type: 'Feature',
                            geometry: {
                                type: 'Polygon',
                                coordinates: [pts],
                            },
                        }
                        map.getSource('line-area' + layerId).setData(jsona)
                    }
                }
            }

            /**
             * 移除dom
             */
            function removedom() {
                const dom = document.getElementsByClassName('measure-result ' + layerId)
                const len = dom.length
                if (len) {
                    for (let i = len - 1; i >= 0; i--) {
                        if (dom[i]) dom[i].remove()
                    }
                }
            }

            /**
             * 移除图层
             */
            function removeLayer() {
                jsonPoint.features = []
                jsonLine.features = []
                if(map.getLayer('points-area' + layerId)) map.removeLayer('points-area' + layerId)
                if(map.getLayer('line-area' + layerId)) map.removeLayer('line-area' + layerId)
                if(map.getLayer('line-area-stroke' + layerId)) map.removeLayer('line-area-stroke' + layerId)
                removedom()
            }

            /**
             * 鼠标move事件
             * @param {} _e
             */
            function mouseMove(_e) {
                if (isMeasure) {
                    map.getCanvas().style.cursor = 'default'
                    const coords = [_e.lngLat.lng, _e.lngLat.lat]
                    const jsonp = {
                        type: 'Feature',
                        geometry: {
                            type: 'Point',
                            coordinates: coords,
                        },
                    }
                    map.getSource('point-move' + layerId).setData(jsonp)

                    if (jsonPoint.features.length > 0) {
                        if (jsonPoint.features.length === 1) {
                            const prev = jsonPoint.features[jsonPoint.features.length - 1]
                            const jsonl = {
                                type: 'Feature',
                                geometry: {
                                    type: 'LineString',
                                    coordinates: [prev.geometry.coordinates, coords],
                                },
                            }
                            map.getSource('line-move' + layerId).setData(jsonl)
                        } else {
                            const json = {
                                type: 'FeatureCollection',
                                features: [],
                            }
                            map.getSource('line-move' + layerId).setData(json)

                            const pointList = []
                            for (let i = 0; i < jsonPoint.features.length; i++) {
                                const coord = jsonPoint.features[i].geometry.coordinates
                                pointList.push(coord)
                            }
                            pointList.push(coords)
                            const pts = pointList.concat([pointList[0]])
                            const jsona = {
                                type: 'Feature',
                                geometry: {
                                    type: 'Polygon',
                                    coordinates: [pts],
                                },
                            }
                            map.getSource('line-area' + layerId).setData(jsona)
                            ele.innerHTML = getArea(pointList)
                            tooltip.setLngLat(coords)
                        }
                    }
                }
            }

            /**
             * 绘制完成
             * @param {*} _e
             */
            function finish(_e) {
                if (isMeasure) {
                    isMeasure = false
                    const coords = [_e.lngLat.lng, _e.lngLat.lat]
                    removePoint(coords)
                     if(map.getLayer('point-move' + layerId)) map.removeLayer('point-move' + layerId)
                     if(map.getLayer('line-move' + layerId)) map.removeLayer('line-move' + layerId)
                    map.getCanvas().style.cursor = 'default'
                    tooltip.remove();
                    callback(map.getSource('line-area'+layerId)._data);
                }
            }

            map.on('click', function (_e) {
                addPointforJSON(_e)
            })

            map.on('dblclick', function (_e) {
                finish(_e)
            })

            map.on('mousemove', function (_e) {
                mouseMove(_e)
            })

            /**
             * 编辑测量面
             */
            function editArea() {
                catchMark = createMarker()
                UpdataGeolist()

                map.on('mousemove', onMouseMove)
                map.on('mousedown', onmousedown)
            }

            function onMouseMove(e) {
                const moveCoord = [e.lngLat.lng, e.lngLat.lat]

                if (jsonPoint.features.length > 1) {
                    // 计算当前指针与线段的距离
                    pointOnLine = getNearestPointOnLine(Geolist, moveCoord) // 线上实际坐标
                    const screenOnLine = Object.values(map.project(pointOnLine)) // 线上屏幕坐标
                    const screenP = [e.point.x, e.point.y]
                    const screenDist = screenDistance(screenOnLine, screenP) // 距离
                    if (screenDist < 15) {
                        isEdit = true
                        catchMark.setLngLat(pointOnLine).addTo(map)
                        catchMark.getElement().style.display = 'block'
                    } else {
                        isEdit = false
                        catchMark.getElement().style.display = 'none'
                    }
                } else {
                    isEdit = false
                    catchMark.getElement().style.display = 'none'
                    map.dragPan.enable()
                }
            }

            function onmousedown(e) {
                if (isEdit) {
                    map.dragPan.disable()
                    let isExist = false

                    // 首先判断编辑点是否是存在(存在修改原来点,不存在新加点)
                    for (let i = 0; i < jsonPoint.features.length; i++) {
                        const coord = jsonPoint.features[i].geometry.coordinates
                        if (coord[0] === pointOnLine[0] && coord[1] === pointOnLine[1]) {
                            isExist = true
                        }
                    }

                    // 获取编辑点在列表中的位置
                    dragPointOrder = getDragCoords(pointOnLine, Geolist)

                    if (!isExist) {
                        // 添加编辑点
                        const point = {
                            type: 'Feature',
                            geometry: {
                                type: 'Point',
                                coordinates: pointOnLine,
                            },
                            properties: {
                                id: String(new Date().getTime()),
                            },
                        }
                        jsonPoint.features.splice(dragPointOrder, 0, point)

                        // 更新绘制要素
                        updataFeature()
                    }

                    map.on('mousemove', onDrag)
                    map.on('mouseup', onMouseup)
                }
            }

            function onDrag(e) {
                const movePoint = [e.lngLat.lng, e.lngLat.lat]

                // 点跟随鼠标移动
                jsonPoint.features[dragPointOrder].geometry.coordinates = movePoint

                // 更新绘制要素
                updataFeature()
            }

            // 更新绘制要素
            function updataFeature() {
                UpdataGeolist()
                const pts = Geolist
                const jsona = {
                    type: 'Feature',
                    geometry: {
                        type: 'Polygon',
                        coordinates: [pts],
                    },
                }
                map.getSource('line-area' + layerId).setData(jsona)
                map.getSource('points-area' + layerId).setData(jsonPoint)
                addMeasureRes(jsonPoint)
            }

            function onMouseup(e) {
                map.off('mousemove', onDrag)
                map.dragPan.enable()
            }

            // 创建Marker
            function createMarker() {
                const markerParam = {
                    map:this.map,
                    lngLat: [0, 0],
                    height: 13,
                    width: 13,
                    size: 13,
                    isDrag: false,
                    cursor: 'default',
                }
                return new mapboxgl.Marker().setLngLat(markerParam.lngLat).setDraggable(false).addTo(markerParam.map);
            }

            // 更新点集
            function UpdataGeolist() {
                Geolist = []
                for (let i = 0; i < jsonPoint.features.length; i++) {
                    const coord = jsonPoint.features[i].geometry.coordinates
                    Geolist.push(coord)
                }
                Geolist.push(Geolist[0])
            }

            // 计算点到直线最近距离的点
            function getNearestPointOnLine(list, moveCoord) {
                var dis, point1, point2
                for (let i = 0; i < list.length - 1; i++) {
                    const distance = getNearestDistance(moveCoord, list[i], list[i + 1])
                    if (i === 0) {
                        dis = distance
                        point1 = list[i]
                        point2 = list[i + 1]
                    } else {
                        if (distance < dis) {
                            dis = distance
                            point1 = list[i]
                            point2 = list[i + 1]
                        }
                    }
                }
                const Point = getNearestPoint(moveCoord, point1, point2)
                return Point
            }

            // 计算点point到线段point1, point2最近距离
            function getNearestDistance(point, point1, point2) {
                const P = {}
                const A = {}
                const B = {}
                P.x = point[0]
                P.y = point[1]
                A.x = point1[0]
                A.y = point1[1]
                B.x = point2[0]
                B.y = point2[1]
                // 计算向量AP和向量AB的点积
                const dotProduct = (P.x - A.x) * (B.x - A.x) + (P.y - A.y) * (B.y - A.y)
                // 计算向量AB的长度的平方
                const lengthSquare = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y)
                // 计算点P到线段AB的投影点C
                const t = dotProduct / lengthSquare
                const C = { x: A.x + t * (B.x - A.x), y: A.y + t * (B.y - A.y) }
                // 如果点C在线段AB内,则点P到线段AB的最近距离为PC的长度;否则,点P到线段AB的最近距离为PA或PB中的较小值。
                const isInside = dotProduct >= 0 && dotProduct <= lengthSquare
                if (isInside) {
                    return Math.sqrt((P.x - C.x) * (P.x - C.x) + (P.y - C.y) * (P.y - C.y))
                } else {
                    return Math.min(
                        Math.sqrt((P.x - A.x) * (P.x - A.x) + (P.y - A.y) * (P.y - A.y)),
                        Math.sqrt((P.x - B.x) * (P.x - B.x) + (P.y - B.y) * (P.y - B.y))
                    )
                }
            }

            // 计算点到直线最近的点 point点坐标,point1, point2直线两个端点
            function getNearestPoint(point, point1, point2) {
                var x, y, x0, y0, x1, y1, x2, y2
                x0 = point[0]
                y0 = point[1]
                x1 = point1[0]
                y1 = point1[1]
                x2 = point2[0]
                y2 = point2[1]

                if (x1 !== x2 && y1 !== y2) {
                    const a = (y2 - y1) / (x2 - x1)
                    const b = y1 - a * x1
                    const k2 = -1 / a
                    const b2 = y0 - k2 * x0
                    x = (b2 - b) / (a - k2)
                    y = a * x + b
                } else if (x1 === x2) {
                    x = x1
                    y = y0
                } else if (y1 === y2) {
                    x = x0
                    y = y1
                }

                // 点不能超出线段
                if (x1 < x2) {
                    if (x2 < x) {
                        x = x2
                    } else if (x < x1) {
                        x = x1
                    }
                } else {
                    if (x1 < x) {
                        x = x1
                    } else if (x < x2) {
                        x = x2
                    }
                }
                if (y1 < y2) {
                    if (y2 < y) {
                        y = y2
                    } else if (y < y1) {
                        y = y1
                    }
                } else {
                    if (y1 < y) {
                        y = y1
                    } else if (y < y2) {
                        y = y2
                    }
                }

                // 点吸附端点
                const screenX0 = Object.values(map.project([x0, y0])) // 屏幕坐标
                const screenX1 = Object.values(map.project([x1, y1])) // 屏幕坐标
                const screenX2 = Object.values(map.project([x2, y2])) // 屏幕坐标
                const screenDistX1 = screenDistance(screenX0, screenX1) // 距离
                const screenDistX2 = screenDistance(screenX0, screenX2) // 距离
                if (screenDistX1 < 10) {
                    x = x1
                    y = y1
                }
                if (screenDistX2 < 10) {
                    x = x2
                    y = y2
                }

                return [x, y]
            }

            // 屏幕距离
            function screenDistance(point1, point2) {
                const x2 = Math.pow(point1[0] - point2[0], 2)
                const y2 = Math.pow(point1[1] - point2[1], 2)
                const dist = Math.sqrt(x2 + y2)

                return dist
            }

            // 计算编辑点在线段上的添加位置
            function getDragCoords(coords, list) {
                var x, y, x1, y1, x2, y2
                let index = 0
                x = coords[0]
                y = coords[1]

                for (let i = 0; i < list.length - 1; i++) {
                    x1 = list[i][0]
                    y1 = list[i][1]
                    x2 = list[i + 1][0]
                    y2 = list[i + 1][1]

                    if (x === x1 && y === y1) {
                        index = i
                        break
                    } else {
                        // 计算线段的长度
                        const length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
                        // 计算点到线段起点的距离
                        const distance1 = Math.sqrt(Math.pow(x - x1, 2) + Math.pow(y - y1, 2))
                        // 计算点到线段终点的距离
                        const distance2 = Math.sqrt(Math.pow(x - x2, 2) + Math.pow(y - y2, 2))
                        // 如果点到线段两个端点的距离之和等于线段的长度,则点在线段上
                        if (Math.abs(length - distance1 - distance2) < 0.00001) {
                            index = i + 1
                            break
                        }
                    }
                }
                return index
            }
        }

        drawPoint(layerId,callback=()=>{}){
            this.layerPointList.push(layerId);
            const map = this.map;
            map.doubleClickZoom.disable();
            const jsonPoint = {
                type: 'FeatureCollection',
                features: [],
            }
            map.addSource('points' + layerId, {
                type: 'geojson',
                data: jsonPoint,
            })
            map.addLayer({
                id: 'points' + layerId,
                type: 'circle',
                source: 'points' + layerId,
                paint: {
                    'circle-color': '#ffffff',
                    'circle-radius': 3.5,
                    'circle-stroke-width': 1.5,
                    'circle-stroke-color': '#ff0000',
                },
            })

            /**
             * 添加点
             * @param {*} _e
             */
            function addPointforJSON(_e) {
                const point = {
                    type: 'Feature',
                    geometry: {
                        type: 'Point',
                        coordinates: [_e.lngLat.lng, _e.lngLat.lat],
                    },
                    properties: {
                        id: String(new Date().getTime()),
                    },
                }
                jsonPoint.features.push(point)
                map.getSource('points' + layerId).setData(jsonPoint);
                map.off('click', addPointforJSON);
                callback(point);
            }
            map.on('click', addPointforJSON)
        }

        drawRectangle(layerId,callback=()=>{}){
            this.layerPointList.push(layerId);
            const map = this.map;
            map.doubleClickZoom.disable();
            const jsonPoint = {
                type: 'FeatureCollection',
                features: [],
            }
            const jsonArea = {
                type: 'FeatureCollection',
                features: [],
            }
            map.addSource('points' + layerId, {
                type: 'geojson',
                data: jsonPoint,
            });
            map.addSource('line-area' + layerId, {
                type: 'geojson',
                data: jsonArea,
            })
            map.addLayer({
                id: 'line-area' + layerId,
                type: 'fill',
                source: 'line-area' + layerId,
                paint: {
                    'fill-color': '#ff0000',
                    'fill-opacity': 0.1,
                },
            })
            map.addLayer({
                id: 'points' + layerId,
                type: 'circle',
                source: 'points' + layerId,
                paint: {
                    'circle-color': '#ffffff',
                    'circle-radius': 3.5,
                    'circle-stroke-width': 1.5,
                    'circle-stroke-color': '#ff0000',
                },
            })

            /**
             * 添加点
             * @param {*} _e
             */
            function addPointforJSON(_e) {
                const point = {
                    type: 'Feature',
                    geometry: {
                        type: 'Point',
                        coordinates: [_e.lngLat.lng, _e.lngLat.lat],
                    },
                    properties: {
                        id: String(new Date().getTime()),
                    },
                }
                jsonPoint.features.push(point);
                if(jsonPoint.features.length == 2) {
                    map.off('click', addPointforJSON);
                    map.off('mousemove', mouseRectangle);
                    callback(jsonArea.features[0]);
                }
                map.getSource('points' + layerId).setData(jsonPoint);
            }


            function mouseRectangle(_e){
                if(!(jsonPoint.features.length)) {
                    const point = {
                        type: 'Feature',
                        geometry: {
                            type: 'Point',
                            coordinates: [_e.lngLat.lng, _e.lngLat.lat],
                        },
                        properties: {
                            id: String(new Date().getTime()),
                        },
                    }
                    return (map.getSource('points' + layerId).setData({type: 'FeatureCollection', features: [point]}));
                }
                let coordinates = jsonPoint.features[0].geometry.coordinates;
                let bbox = coordinates.concat([_e.lngLat.lng, _e.lngLat.lat]).sort((a,b)=> a-b);
                let polygon = turf.bboxPolygon([bbox[2],bbox[0],bbox[3],bbox[1]]);
                jsonArea.features = [polygon];
                map.getSource('line-area' + layerId).setData(jsonArea);
            }

            map.on('click', addPointforJSON);

            map.on('mousemove', mouseRectangle)
        }

        /**
         * 清除所有测量要素
         */
        clearMeasureAll() {
            const dom = document.getElementsByClassName('measure-result')
            const len = dom.length
            if (len) {
                for (let i = len - 1; i >= 0; i--) {
                    if (dom[i]) dom[i].remove()
                }
            }
            if (this.layerDistanceList) {
                for (let i = 0; i < this.layerDistanceList.length; i++) {
                    const layerid = this.layerDistanceList[i]
                    try {
                          if(this.map.getLayer('points' + layerid))  this.map.removeLayer('points' + layerid)
                          if(this.map.getLayer('line' + layerid))  this.map.removeLayer('line' + layerid)
                        if(this.map.getLayer('point-move' + layerid)) this.map.removeLayer('point-move' + layerid)
                        if(this.map.getLayer('line-move' + layerid))   this.map.removeLayer('line-move' + layerid)
                    } catch (error) {
                        console.log(error)
                    }
                }
            }
            this.layerDistanceList = []
            if (this.layerAreaList) {
                for (let i = 0; i < this.layerAreaList.length; i++) {
                    const layerid = this.layerAreaList[i]
                    try {
                       if(this.map.getLayer('points-area' + layerid)) this.map.removeLayer('points-area' + layerid)
                       if(this.map.getLayer('line-area' + layerid)) this.map.removeLayer('line-area' + layerid)
                       if(this.map.getLayer('line-area-stroke' + layerid)) this.map.removeLayer('line-area-stroke' + layerid)
                       if(this.map.getLayer('point-move' + layerid)) this.map.removeLayer('point-move' + layerid)
                       if(this.map.getLayer('line-move' + layerid)) this.map.removeLayer('line-move' + layerid)
                    } catch (error) {
                        console.log(error)
                    }
                }
            }
            this.layerAreaList = []
            if (this.layerPointList) {
                for (let i = 0; i < this.layerPointList.length; i++) {
                    const layerid = this.layerPointList[i]
                    try {
                        if(this.map.getLayer('points' + layerid)) this.map.removeLayer('points' + layerid)
                        if(this.map.getLayer('line-area' + layerid)) this.map.removeLayer('line-area' + layerid)
                    } catch (error) {
                        console.log(error)
                    }
                }
            }
            this.layerPointList = []
            this.map.doubleClickZoom.enable()
        }
    }



})));