Preview

包含繪制的一些基本功能,點線面的繪制,坐標、距離、面積的測量,繪制緩沖區做空間統計功能,點擊當前標注可以洗掉,
功能統一封裝
DrawingGraphics.js
import {
MessageBox
} from 'element-ui' // 做文字標繪
let DrawGraphicsLayer = null // 繪制圖形圖層
let DrawLayer = null // 繪制圖層
let drawingOption = {} // 繪制配置,根據配置可實作空間統計、空間測量、標繪等功能
/**
* @name: 坐標測量
* @msg: 顯示點擊位置的坐標資訊
* @param {event}
*/
function coordinateMeasuring(event) {
const content = '<div><p>經度:' + event.geometry.x.toFixed(6) + '</p><p>緯度:' + event.geometry.y.toFixed(6) + '</p></div>'
this.map.infoWindow.resize(200, 100)
this.map.infoWindow.setTitle('坐標資訊')
this.map.infoWindow.setContent(content)
this.map.infoWindow.show(event.geometry)
this.map.infoWindow.on('hide', () => {})
}
/**
* @name: 設定圖片標注
*/
function setPictureMarkerSymbol() {
return {
url: require('@/assets/images/ico01.png'),
height: 20,
width: 20,
type: 'esriPMS',
angle: 0,
}
}
/**
* @name: 設定標注顏色
*/
function setSymbolColor(type) {
if (type === 'fill') {
// 圖形填充顏色
return new this.gisConstructor.Color([255, 0, 0, 0.25])
} else if (type === 'line') {
// 線條顏色
return new this.gisConstructor.Color([255, 0, 0, 0.8])
} else {
return new this.gisConstructor.Color([255, 0, 0, 0.8])
}
}
/**
* @name: 設定線標注樣式
*/
function setLineSymbolStyle() {
return {
color: setSymbolColor.call(this, 'line'),
width: 2,
}
}
/**
* @name: 設定文字標注樣式
* @param {text} String
*/
function setTextSymbolStyle(text) {
let _this = this
return {
text: text,
color: [255, 0, 0],
font: new _this.gisConstructor.Font({
family: 'microsoft Yahei',
size: 8,
style: 'normal',
weight: 'bold',
}),
haloColor: [255, 255, 255],
haloSize: 2, // haloColor 和 haloSize 需要 arcgis 3.15 版本及以上
horizontalAlignment: 'center', // 文本對齊方式 "left" | "right" | "center" | "justify"
xoffset: 0,
yoffset: 0,
}
}
/**
* @name: 根據 id 清除圖形
* @msg: 點擊當前標注可以洗掉
* @param {ID}
*/
function clearCurrentMarker(ID) {
const graphicsArr = DrawGraphicsLayer.graphics
for (let i = graphicsArr.length - 1; i >= 0; i--) {
if (
graphicsArr[i].attributes.id && graphicsArr[i].attributes.id === ID
) {
DrawGraphicsLayer.remove(graphicsArr[i])
}
}
}
/**
* @name: 地圖點擊
* @param {event}
*/
function mapHandleClick(event) {
if (event.graphic && event.graphic.attributes) {
let attributes = event.graphic.attributes
clearCurrentMarker(attributes.id)
}
}
/**
* @name: 查詢緩沖區范圍內的資料
* @param {geometry} 幾何圖形
*/
function doQueryBuffer(geometry) {
let queryUrl = drawingOption.StatisticalServerURL || ''
let query = new this.gisConstructor.query()
query.geometry = geometry
query.outFields = ['*']
query.returnGeometry = true
var queryTask = new this.gisConstructor.QueryTask(queryUrl)
queryTask.execute(
query,
(featureSet) => {
console.log(featureSet)
},
(error) => {
console.log(error)
}
)
}
/**
* @name: 繪制圖形
* @param {event}
*/
function drawGraphic(event) {
let _this = this
let symbol = ''
let _type = event.geometry.type
let resultSymbol = '' // 繪制的完整圖形
let symbolID = 'symbolMarker' + new Date().getTime() // 用于洗掉當前標注
if (drawingOption.name === '標繪') {
if (_type === 'point' && drawingOption.text === false) {
resultSymbol = new this.gisConstructor.PictureMarkerSymbol(setPictureMarkerSymbol.call(this))
DrawGraphicsLayer.add(new this.gisConstructor.graphic(
event.geometry,
resultSymbol, {
id: symbolID,
name: '圖形標注'
}
))
} else if (_type === 'point' && drawingOption.text === true) {
// 文字標繪
MessageBox.prompt('', '請輸入文字', {
confirmButtonText: '確定',
cancelButtonText: '取消'
}).then(
({
value
}) => {
if (value !== '') {
resultSymbol = new this.gisConstructor.TextSymbol(setTextSymbolStyle.call(this, value))
DrawGraphicsLayer.add(new this.gisConstructor.graphic(
event.geometry,
resultSymbol, {
id: symbolID,
name: '圖形標注'
}
))
}
}
).catch(error => {
console.log(error)
})
} else if (_type === 'polyline') {
resultSymbol = new this.gisConstructor.SimpleLineSymbol(setLineSymbolStyle.call(this))
console.log(event.geometry)
console.log(new this.gisConstructor.graphic(
event.geometry,
resultSymbol, {
id: symbolID,
name: '圖形標注'
}
))
DrawGraphicsLayer.add(new this.gisConstructor.graphic(
event.geometry,
resultSymbol, {
id: symbolID,
name: '圖形標注'
}
))
} else if (_type === 'polygon') {
// 添加繪制好的面圖形
resultSymbol = new this.gisConstructor.SimpleFillSymbol(
this.gisConstructor.SimpleFillSymbol.STYLE_SOLID,
new this.gisConstructor.SimpleLineSymbol(setLineSymbolStyle.call(this)),
setSymbolColor.call(this, 'fill'),
)
DrawGraphicsLayer.add(new this.gisConstructor.graphic(
event.geometry,
resultSymbol, {
id: symbolID, // 洗掉功能
name: '圖形標注'
}
))
}
}
if (drawingOption.name === '空間測量') {
if (_type === 'point') {
// infoWindow 顯示坐標資訊
coordinateMeasuring.call(this, event)
} else if (_type === 'polyline') {
resultSymbol = new this.gisConstructor.SimpleLineSymbol(setLineSymbolStyle.call(this))
DrawGraphicsLayer.add(new this.gisConstructor.graphic(
event.geometry,
resultSymbol, {
id: symbolID,
name: '圖形標注'
}
))
// 測量距離
const lengthParams = new _this.gisConstructor.LengthsParameters()
const geometryService = new _this.gisConstructor.GeometryService(
drawingOption.GeometryServerURL
)
lengthParams.distanceUnit = _this.gisConstructor.GeometryService.UNIT_KILOMETER
lengthParams.calculationType = 'preserveShape'
const polyline = new _this.gisConstructor.Polyline(
_this.map.spatialReference
)
const paths = event.geometry.paths[0]
polyline.addPath(paths)
lengthParams.polylines = [polyline]
// 根據引數,動態計算長度
geometryService.lengths(lengthParams, (length) => {
let distance = _this.gisConstructor.number.format(length.lengths[0])
// 設距離顯示樣式,并添加到地圖上
let text = '總長度:' + distance + '米'
const distanceSymbol = new _this.gisConstructor.TextSymbol(setTextSymbolStyle.call(this, text))
const distanceCenterPoint = event.geometry.getExtent().getCenter()
const distancePoint = new _this.gisConstructor.Point(distanceCenterPoint, _this.map.spatialReference)
const distanceGraphic = new _this.gisConstructor.graphic(
distancePoint,
distanceSymbol, {
id: symbolID, // 洗掉功能
name: '圖形標注'
}
)
DrawGraphicsLayer.add(distanceGraphic)
})
} else if (_type === 'polygon') {
// 添加繪制好的面圖形
resultSymbol = new this.gisConstructor.SimpleFillSymbol(
this.gisConstructor.SimpleFillSymbol.STYLE_SOLID,
new this.gisConstructor.SimpleLineSymbol(setLineSymbolStyle.call(this)),
setSymbolColor.call(this, 'fill'),
)
DrawGraphicsLayer.add(new this.gisConstructor.graphic(
event.geometry,
resultSymbol, {
id: symbolID, // 洗掉功能
name: '圖形標注'
}
))
// 測量面積
// https://developers.arcgis.com/javascript/3/jsapi/geometryservice-amd.html
const areasAndLengthParams = new this.gisConstructor.AreasAndLengthsParameters()
const geometryService = new this.gisConstructor.GeometryService(drawingOption.GeometryServerURL)
areasAndLengthParams.areaUnit = this.gisConstructor.GeometryService.UNIT_SQUARE_KILOMETERS // 平方公里(平方米:UNIT_SQUARE_METERS)
areasAndLengthParams.calculationType = 'preserveShape'
geometryService.simplify([event.geometry], (simplifiedGeometries) => {
areasAndLengthParams.polygons = simplifiedGeometries
geometryService.areasAndLengths(areasAndLengthParams, (area) => {
let areas = this.gisConstructor.number.format(area.areas[0])
// 設距離顯示樣式,并添加到地圖上
let text = areas + '平方公里'
const areaSymbol = new this.gisConstructor.TextSymbol(setTextSymbolStyle.call(this, text))
const areaCenterPoint = event.geometry.getExtent().getCenter()
const areaPoint = new this.gisConstructor.Point(areaCenterPoint, this.map.spatialReference)
const areaGraphic = new this.gisConstructor.graphic(
areaPoint,
areaSymbol, {
id: symbolID, // 洗掉功能
name: '圖形標注'
}
)
DrawGraphicsLayer.add(areaGraphic)
})
})
}
}
if (drawingOption.name === '空間統計') {
if (_type === 'point') {
symbol = new this.gisConstructor.SimpleMarkerSymbol(
this.gisConstructor.SimpleMarkerSymbol.STYLE_SQUARE,
10,
new this.gisConstructor.SimpleLineSymbol(setLineSymbolStyle.call(this)),
setSymbolColor.call(this, 'fill')
)
} else if (_type === 'polyline') {
symbol = new _this.gisConstructor.SimpleLineSymbol(setLineSymbolStyle.call(this))
} else if (_type === 'polygon') {
symbol = new this.gisConstructor.SimpleFillSymbol(
this.gisConstructor.SimpleFillSymbol.STYLE_NONE,
new this.gisConstructor.SimpleLineSymbol(
this.gisConstructor.SimpleLineSymbol.STYLE_DASHDOT,
new this.gisConstructor.SimpleLineSymbol(setLineSymbolStyle.call(this)),
setSymbolColor.call(this, 'fill'),
),
new this.gisConstructor.Color(setSymbolColor.call(this, 'fill'))
)
}
let drawingGraphic = new this.gisConstructor.graphic(event.geometry, symbol, {
id: symbolID,
name: '圖形標注'
})
DrawGraphicsLayer.add(drawingGraphic)
// 空間統計做緩沖區,查詢資料
let params = new this.gisConstructor.BufferParameters()
params.bufferSpatialReference = this.map.spatialReference
params.outSpatialReference = this.map.spatialReference
params.distances = [Number(drawingOption.distances) || 1]
params.unit = this.gisConstructor.GeometryService.UNIT_METER
params.geodesic = true
params.geometries = [drawingGraphic.geometry]
new this.gisConstructor.GeometryService(drawingOption.GeometryServerURL || 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer').buffer(params, features => {
let symbol = new _this.gisConstructor.SimpleFillSymbol(
_this.gisConstructor.SimpleFillSymbol.STYLE_SOLID,
new _this.gisConstructor.SimpleLineSymbol(
setLineSymbolStyle.call(this)
),
new _this.gisConstructor.Color(setSymbolColor.call(this, 'fill'))
)
let graphic = new _this.gisConstructor.graphic(features[0], symbol, {
id: symbolID,
name: '圖形標注'
})
DrawGraphicsLayer.add(graphic)
// 獲取緩沖范圍里的資料一般有兩種情況:
// 一:用 MapServer 查詢
doQueryBuffer.call(_this, graphic.geometry)
// 二:取構成圖形范圍的坐標點集合傳給后臺,后臺查詢圖形范圍內的資料,例如:
let rings = features[0].rings
console.log(rings)
})
}
DrawLayer.deactivate()
this.map.setMapCursor('default')
}
/**
* @name: 初始化繪制圖層
*/
function initDrawLayer() {
// GraphicsLayer 第一個引數是 url,沒有也要占位,否則在第二個引數物件中設定圖層 id 等資訊無效,無法通過 map.addLayer(id) 獲取指定 id 的圖層
DrawGraphicsLayer = new this.gisConstructor.GraphicsLayer('', {
id: '繪制圖層'
}, this.map.spatialReference)
this.map.addLayer(DrawGraphicsLayer)
DrawLayer = new this.gisConstructor.draw(this.map, {
showTooltips: true
})
// 官網:draw-end This event is deprecated. Use draw-complete instead.
DrawLayer.on('draw-complete', drawGraphic.bind(this))
}
/**
* @name: 繪制工具
* @param {status} 繪制狀態
* @return {option} 配置
*/
function DrawingGraphics(status, option) {
drawingOption = option
if (!DrawLayer) {
// 防止第二次點擊繪制型別,任然為上一次繪制型別狀態
initDrawLayer.call(this)
}
if (status === 'active') {
DrawLayer.activate(option.type)
this.map.setMapCursor('crosshair')
} else {
// 清除繪制狀態和繪制圖形
DrawLayer.deactivate()
this.map.setMapCursor('default')
DrawGraphicsLayer.clear()
this.map.infoWindow.hide()
}
this.map.on('click', mapHandleClick.bind(this))
}
export {
DrawingGraphics
}
使用
<template>
<div id="map-container"
style="width:100%;height:100%;">
<div
style="position:absolute;right:50px;top:50px;z-index:999;">
<span>標繪:</span>
<button
@click="drawingGraphicsTool('標繪', 'point')">點</button>
<button
@click="drawingGraphicsTool('標繪', 'polyline')">線</button>
<button
@click="drawingGraphicsTool('標繪', 'polygon')">面</button>
<button
@click="drawingGraphicsTool('標繪', 'point', 'text')">文字</button>
<br>
<span>空間測量:</span>
<button
@click="drawingGraphicsTool('空間測量', 'point')">坐標測量</button>
<button
@click="drawingGraphicsTool('空間測量', 'polyline')">距離測量</button>
<button
@click="drawingGraphicsTool('空間測量', 'polygon')">面積測量</button>
<br>
<span>空間統計:</span>
<button
@click="drawingGraphicsTool('空間統計', 'point')">點</button>
<button
@click="drawingGraphicsTool('空間統計', 'polyline')">線</button>
<button
@click="drawingGraphicsTool('空間統計', 'polygon')">面</button>
<br>
<button
@click="drawingGraphicsTool()">clear</button>
</div>
</div>
</template>
<script>
import { loadCss, loadModules } from 'esri-loader'
import { DrawingGraphics } from './DrawingGraphics.js'
export default {
name: 'DrawingGraphics',
components: {},
data() {
return {
map: '',
gisConstructor: {}, // gis 建構式
gisModules: [
'esri/map',
'esri/SpatialReference',
'esri/geometry/Extent',
'esri/geometry/Point',
'esri/geometry/Polyline',
'esri/geometry/Polygon',
'esri/geometry/geometryEngine',
'esri/tasks/GeometryService',
'esri/tasks/ProjectParameters',
'esri/tasks/AreasAndLengthsParameters',
'esri/tasks/LengthsParameters',
'esri/tasks/query',
'esri/tasks/QueryTask',
'esri/tasks/BufferParameters',
'esri/graphic',
'esri/symbols/PictureMarkerSymbol',
'esri/symbols/TextSymbol',
'esri/symbols/SimpleMarkerSymbol',
'esri/symbols/SimpleLineSymbol',
'esri/symbols/SimpleFillSymbol',
'esri/symbols/Font',
'esri/layers/GraphicsLayer',
'esri/layers/ArcGISDynamicMapServiceLayer',
'esri/layers/ArcGISTiledMapServiceLayer',
'esri/toolbars/draw',
'esri/Color',
'dojo/_base/declare',
'dojo/number',
'esri/config',
'esri/geometry/normalizeUtils',
],
}
},
mounted() {
this.init()
},
methods: {
/**
* @name: 地圖點擊事件
*/
mapClickFun() {
this.map.on('click', () => { })
},
/**
* @name: 繪制工具
* @msg: 標繪,空間測量,空間統計
* @param {name}
* @param {type}
* @param {text} true
*/
drawingGraphicsTool(name, type, text) {
if (name && type) {
let option = {}
if (name === '標繪') {
option = {
name: '標繪',
type: type,
text: text ? true : false,
}
}
if (name === '空間測量') {
option = {
GeometryServerURL:
'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer',
name: '空間測量',
type: type,
}
}
if (name === '空間統計') {
option = {
StatisticalServerURL:
'https://sampleserver6.arcgisonline.com/arcgis/rest/services/StoryMaps/StoryMapPlaces4/MapServer/0',
GeometryServerURL:
'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer',
distances: 100,
name: '空間統計',
type: type,
}
}
DrawingGraphics.call(this, 'active', option)
} else {
DrawingGraphics.call(this, 'clear')
}
},
/**
* @name: 初始化地圖
*/
init() {
// 加載 css
loadCss('https://js.arcgis.com/3.32/esri/css/esri.css')
// 加載模塊
loadModules(this.gisModules, {
url: 'https://js.arcgis.com/3.32/init.js',
})
.then(this.initMap)
.then(this.mapClickFun)
},
// 初始化地圖
initMap(args) {
// 將 ArcGIS 的每個功能模塊都存放到 gisConstructor 中
for (let k in args) {
let name = this.gisModules[k].split('/').pop()
this.gisConstructor[name] = args[k]
}
this.map = new this.gisConstructor.map('map-container', {
basemap: 'osm',
logo: false,
slider: true,
})
let extent = {
xmin: -117.1839455,
ymin: 32.68087830000002,
xmax: -117.15035189999998,
ymax: 32.732100979999984,
}
/*
如果坐標系是 4490,初始化范圍需要設定空間參考坐標系
new this.gisConstructor.SpatialReference({
wkid: 4490
})
*/
this.map.setExtent(
new this.gisConstructor.Extent(
extent.xmin,
extent.ymin,
extent.xmax,
extent.ymax,
new this.gisConstructor.SpatialReference()
)
)
// 添加一個 MapServer 做測驗
let StoryMapPlaces4 = new this.gisConstructor.ArcGISDynamicMapServiceLayer(
'https://sampleserver6.arcgisonline.com/arcgis/rest/services/StoryMaps/StoryMapPlaces4/MapServer',
{
id: 'StoryMapPlaces4',
opacity: 1,
visible: true,
}
)
this.map.addLayer(StoryMapPlaces4, 2)
},
},
}
</script>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/221076.html
標籤:其他
上一篇:【MATLAB-app】appdesigner 設計中的幾個神招數(精心打造,附源代碼)
下一篇:小白的學習路程
