vue+arcgis api for js实现地图测距的分段统计线段长度
vue页面调用代码:
<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
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()
}
}
}
}
效果图: