vue+arcgis api for js实现地图测距的分段统计线段长度

vue页面调用代码:

javascript 复制代码
<template>
	<el-button @click="handleMeasureDis">地图测距</el-button>
	<el-button @click="handleClear">清除</el-button>
</template>
import measureDistance from '@/views/fisheryMap/components/mixins/measureDistance.js'
export default {
    mixins: [ measureDistance],
    methods: {
		handleMeasureDis(){
			this.drawLine()
		},
		handleClear(){
			this.clearDistanceLine()
		},
	}
}

详细实现逻辑代码:measureDistance.js

javascript 复制代码
import Draw from '@arcgis/core/views/draw/Draw.js'
import GroupLayer from '@arcgis/core/layers/GroupLayer.js'
import * as geometryEngine from '@arcgis/core/geometry/geometryEngine.js'
import GraphicsLayer from '@arcgis/core/layers/GraphicsLayer.js'
import Graphic from '@arcgis/core/Graphic.js'
export default {
    data() {
        return {
            drawLineLayer: null,
            textLayer: null,
            draw: null,
            groupLayer: null,
            lineNum: 0,
            mouseOperate: {
                start: false,
                end: null,
                pointermove: null,
                drag: null,
                click: null
            },
            curDrawLine: null,
            curLineLayer: null
        }
    },
    methods: {
        drawLine() {
            this.lineNum += 1
            this.drawLineLayer = this.mapAndView.map.findLayerById('drawLineLayer')
            if (!this.drawLineLayer) {
                this.drawLineLayer = new GraphicsLayer({
                    id: 'drawLineLayer',
                    graphics: [],
                    spatialReference: this.mapAndView.spatialReference
                })
                this.mapAndView.map.add(this.drawLineLayer)
            } else {
                this.drawLineLayer.graphics.removeAll()
            }
            this.textLayer = this.mapAndView.map.findLayerById('textLayer')
            if (!this.textLayer) {
                this.textLayer = new GraphicsLayer({
                    id: 'textLayer',
                    graphics: [],
                    spatialReference: this.mapAndView.spatialReference
                })
                this.mapAndView.map.add(this.textLayer)
            } else {
                this.textLayer.graphics.removeAll()
            }

            this.draw = new Draw({
                view: this.mapAndView
            })
            let action = this.draw.create('polyline', { mode: 'click' })
            // fires when a vertex is added
            action.on('vertex-add', evt => {
                let polyline = this.createLine(evt.vertices)
                let lineLength =  geometryEngine.geodesicLength(polyline, 'kilometers')
                if (evt.vertices.length > 1) {
                    this.createSymbol(evt.vertices[evt.vertices.length - 1][0], evt.vertices[evt.vertices.length - 1][1], lineLength.toFixed(2) + 'km')
                } else {
                    this.createSymbol(evt.vertices[evt.vertices.length - 1][0], evt.vertices[evt.vertices.length - 1][1])
                }
            })

            // fires when the pointer moves
            action.on('cursor-update', evt => {
                this.createLine(evt.vertices)
            })

            // fires when the drawing is completed
            action.on('draw-complete', evt => {
                this.createLine(evt.vertices)
                this.groupLayer = this.mapAndView.map.findLayerById('groupLayer')
                if (!this.groupLayer) {
                    this.groupLayer = new GroupLayer({
                        id: 'groupLayer',
                        spatialReference: this.mapAndView.spatialReference
                    })
                    this.mapAndView.map.add(this.groupLayer)
                } 

                let lineAndTextLayer = new GraphicsLayer({
                    id: 'distanceLineLayer' + this.lineNum,
                    graphics: [],
                    spatialReference: this.mapAndView.spatialReference
                })
                this.mapAndView.map.add(lineAndTextLayer)
                // 添加线尾的删除图标
                this.createLastSymbol(evt.vertices[evt.vertices.length - 1][0], evt.vertices[evt.vertices.length - 1][1])

                lineAndTextLayer.addMany(this.drawLineLayer.graphics.items)
                lineAndTextLayer.addMany(this.textLayer.graphics.items)

                this.groupLayer.layers.add(lineAndTextLayer)
                this.drawLineLayer.graphics.removeAll()
                this.textLayer.graphics.removeAll()
            })

            // fires when a vertex is removed
            action.on('vertex-remove', evt => {
                this.createLine(evt.vertices)
            })

            this.mapAndView.on('pointer-move', event => {
                let graphic = null
                this.mapAndView.hitTest(event).then(res => {
                    this.mapAndView.cursor = 'default'
                    if (res.results.length) {
                        graphic = res.results[0].graphic
                        if (graphic?.layer?.id?.indexOf('distanceLineLayer') > -1 && (graphic.symbol?.type === 'simple-marker'
                         || graphic.symbol?.type === 'picture-marker')) {
                            this.mapAndView.cursor = 'pointer'
                        }
                    } 
                })

                if (this.mouseOperate.start && this.arrIndex > -1) {
                    const screenPoint = {
                        x: event.x,
                        y: event.y,
                        spatialReference: this.mapAndView.spatialReference
                    }
                    let coordinate = this.mapAndView.toMap(screenPoint)
                    this.curDrawLine.geometry.paths[0][this.arrIndex] = [coordinate.x, coordinate.y]
                    this.createLine(this.curDrawLine.geometry.paths[0], this.curLineLayer)
                    this.textLayer.graphics.removeAll()
                    this.curDrawLine.geometry.paths[0].map((item, index) => {
                        if (index === 0) {
                            this.createSymbol(item[0], item[1])
                        } else if (index === this.curDrawLine.geometry.paths[0].length - 1) {
                            this.createSymbol(item[0], item[1])
                            this.createLastSymbol(item[0], item[1])
                        } else {
                            let polyline = {
                                type: 'polyline', 
                                paths: [[this.curDrawLine.geometry.paths[0][0], item]],
                                spatialReference: this.mapAndView.spatialReference
                            }
                            let lineLength =  geometryEngine.geodesicLength(polyline, 'kilometers')
                            this.createSymbol(item[0], item[1], lineLength.toFixed(2) + 'km')
                        }
                    })
                    this.curLineLayer.addMany(this.textLayer.graphics.items)
                    this.textLayer.graphics.removeAll()
                }
            })

            this.mapAndView.on('double-click', event => {
                this.mapAndView.hitTest(event).then(res => {
                    if (this.mouseOperate.start) {
                        this.mouseOperate.start = false
                    } 
                })
            })
            this.mapAndView.on('pointer-down', event => {
                this.mapAndView.hitTest(event).then(res => {
                    if (res.results.length) {
                        let graphic = res.results[0].graphic
                        this.arrIndex = -1
                        this.curDrawLine = null
                        this.curLineLayer = null
                        if (graphic?.layer?.id?.indexOf('distanceLineLayer') > -1) {
                            if (graphic.symbol?.type === 'simple-marker') {
                                let lineLayer = this.groupLayer.findLayerById(graphic.layer.id)
                                let lineGeometry = lineLayer.graphics.items[0]
                                lineGeometry.geometry.paths[0].map((item, index) => {
                                    if (item[0] === graphic.geometry.x && item[1] === graphic.geometry.y) {
                                        this.arrIndex = index
                                    }
                                })
                                if (this.arrIndex > -1) {
                                    this.curDrawLine = lineGeometry
                                    this.curLineLayer = lineLayer
                                }
                                if (!this.mouseOperate.start) {
                                    this.mouseOperate.start = true
                                }  
                            }
                            if (graphic.symbol?.type === 'picture-marker') {
                                let lineLayer = this.groupLayer.findLayerById(graphic.layer.id)
                                if (lineLayer) {
                                    this.groupLayer.remove(lineLayer)
                                }
                            }
                        }
                    } 
                })
            })
        },
        // 绘制线
        createLine(vertices, layer) {
            if (layer) {
                layer.graphics.removeAll()
            } else {
                this.drawLineLayer.graphics.removeAll()
            }
            
            let polyline = {
                type: 'polyline', 
                paths: [vertices],
                spatialReference: this.mapAndView.spatialReference
            }
            let graphic = new Graphic({
                geometry: polyline,
                symbol: {
                    type: 'simple-line', 
                    color: '#FF8C00',
                    width: 2,
                    cap: 'round',
                    join: 'round'
                }
            })
            
            if (layer) {
                layer.graphics.add(graphic)
            } else {
                this.drawLineLayer.graphics.add(graphic)
            }
            return polyline
        },
        // 添加圆点和距离文字
        createSymbol(lon, lat, text) {
            if (!this.textLayer) {
                this.textLayer = new GraphicsLayer({
                    id: 'textLayer',
                    graphics: [],
                    spatialReference: this.mapAndView.spatialReference
                })
                this.mapAndView.map.add(this.textLayer)
            } 
            let textSymbol = {
                type: 'text',  
                color: 'white',
                haloColor: 'black',
                haloSize: '1px',
                text: text || '起点',
                xoffset: 3,
                yoffset: -13,
                font: {  
                    size: 12,
                    // family: 'Josefin Slab',
                    weight: 'bold'
                }
            }
            let markerSymbol = {
                type: 'simple-marker',  
                size: 7,
                color: 'rgba(255,255,255,1)',
                outline: {  
                    width: 1,
                    color: '#ff0000'
                }
            }
           
            let geometry = {
                type: 'point',
                longitude: lon,
                latitude: lat,
                spatialReference: this.mapAndView.spatialReference
            }
            const markerGraphic = new Graphic({
                geometry: geometry, 
                symbol: markerSymbol 
            })
            this.textLayer.graphics.add(markerGraphic)

            const textGraphic = new Graphic({
                geometry: geometry, 
                symbol: textSymbol 
            })
            this.textLayer.graphics.add(textGraphic)
        },
        // 添加线尾的删除图标
        createLastSymbol(lon, lat) {
            let markerSymbol = {
                type: 'picture-marker',  
                xoffset: 5,
                yoffset: 9,
                width: 10,
                height: 10,
                url: require('@/assets/images/system/layer/deleteLine.jpg')
            }
            let geometry = {
                type: 'point',
                longitude: lon,
                latitude: lat,
                spatialReference: this.mapAndView.spatialReference
            }
            const markerGraphic = new Graphic({
                geometry: geometry, 
                symbol: markerSymbol 
            })
            this.textLayer.graphics.add(markerGraphic)
        },
        //清除测距线
        clearDistanceLine() {
            if (this.draw) {
                this.groupLayer.removeAll()
                this.draw.reset()
            }
        }
    }
}

效果图:

相关推荐
城数派1 小时前
2026年500米分辨率DEM地形数据(全球/全国/分省/分市)
数据库·arcgis·信息可视化·数据分析·excel
MaCa .BaKa3 小时前
55-宠物爱心救助领养系统-宠物救助领养系统
java·vue.js·tomcat·maven·springboot·宠物救助领养系统
海鸥两三4 小时前
基于 Vue 3 + 高德地图的网格规划系统实战(有源码)
前端·javascript·vue.js
专注VB编程开发20年4 小时前
我制作excel工作簿的选项卡,发给deep seek, 昨天修改了一天
前端·vue.js·excel
qq_420362035 小时前
前端国际化方案
前端·javascript·vue.js·国际化·reactjs
香香爱编程6 小时前
vue3自定义顶部弹窗
前端·javascript·vue.js
蜡台6 小时前
Vue Echart 的 **高阶组件化** 封装思路
前端·javascript·vue.js·echarts
xuankuxiaoyao6 小时前
vue.js 路由第二篇
前端·javascript·vue.js
一 乐6 小时前
图书电子商务网站系统|基于SprinBoot+vue图书电子商务网站设计与实现(源码+数据库+文档)
java·前端·数据库·vue.js·论文·毕设·图书电子商务网站系统
吃乔巴的糖20 小时前
Vue 3 打印模板设计器 (print-canvas-designer)
前端·vue.js