一、安装arcgis
命令行:
npm install @arcgis/core
二、引入所需依赖
import Draw from "@arcgis/core/views/draw/Draw";
import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer";
import Graphic from "@arcgis/core/Graphic";
import Point from "@arcgis/core/geometry/Point";
import Polyline from "@arcgis/core/geometry/Polyline";
// Pro SDK中的一个关键组件,它提供了一系列用于处理几何图形(Point、Polyline、Polygon……)的方法和算法。例如计算距离、缓冲区分析、叠加分析和几何关系检查等。
import * as geometryEngine from "@arcgis/core/geometry/geometryEngine";
import Polygon from "@arcgis/core/geometry/Polygon";
// GeometryService几何服务模块
import * as geometryService from "@arcgis/core/rest/geometryService.js";
//操作设置长度单位和其他参数
import LengthsParameters from "@arcgis/core/rest/support/LengthsParameters";
// 操作设置面积、周长和其他参数
import AreasAndLengthsParameters from "@arcgis/core/rest/support/AreasAndLengthsParameters";
三、定义对象
let lineLayer = null;
let lineEditLayer = null;
let lineTxtLayer = null;
let areaLayer = null;
let areaEditLayer = null;
let areaTxtLayer = null;
let lineLayerId = "measurementLineLayer";
let lineEditLayerId = "lineEditLayer";
let lineTxtLayerId = "lineTxtLayer";
let areaLayerId = "measurementAreaLayer";
let areaEditLayerId = "areaEditLayer";
let areaTxtLayerId = "areaTxtLayer";
// 缓冲服务对象
const geometryServiceUrl = "http://localhost:6080/arcgis/rest/services/Utilities/Geometry/GeometryServer";
四、实现方法
1、初始化方法(测距测面都可以单独引用)
// 测量工具初始化
export const initMeasure = ((view, map) => {
lineLayer = map.findLayerById(lineLayerId)
if (lineLayer === null || lineLayer === undefined) {
lineLayer = new GraphicsLayer({id: lineLayerId})
map.add(lineLayer)
}
lineLayer.removeAll() //清空上次绘制的线
lineTxtLayer = map.findLayerById(lineTxtLayerId)
if (lineTxtLayer === null || lineTxtLayer === undefined) {
lineTxtLayer = new GraphicsLayer({id: lineTxtLayerId})
map.add(lineTxtLayer)
}
lineTxtLayer.removeAll() //清空上次绘制的标注
lineEditLayer = map.findLayerById(lineEditLayerId)
if (lineEditLayer === null || lineEditLayer === undefined) {
lineEditLayer = new GraphicsLayer({id: lineEditLayerId})
map.add(lineEditLayer)
}
lineEditLayer.removeAll() //清空上次绘制的编辑点
areaLayer = map.findLayerById(areaLayerId)
if (areaLayer === null || areaLayer === undefined) {
areaLayer = new GraphicsLayer({id: areaLayerId})
map.add(areaLayer)
}
areaLayer.removeAll() //清空上次绘制的标注
areaEditLayer = map.findLayerById(areaEditLayerId)
if (areaEditLayer === null || areaEditLayer === undefined) {
areaEditLayer = new GraphicsLayer({id: areaEditLayerId})
map.add(areaEditLayer)
}
areaEditLayer.removeAll() //清空上次绘制的编辑点
areaTxtLayer = map.findLayerById(areaTxtLayerId)
if (areaTxtLayer === null || areaTxtLayer === undefined) {
areaTxtLayer = new GraphicsLayer({id: areaTxtLayerId})
map.add(areaTxtLayer)
}
areaTxtLayer.removeAll() //清空上次绘制的编辑点
});
2、测距方法
/******* 测距 *******/
export const measureLine = ((view,map) => {
// 测距/测面初始化
initMeasure(view,map);
let editGps = [];
// 测距绘制
let draw = new Draw({
view: view
});
let action = draw.create("polyline");
// 获取焦点
view.focus();
// 顶点添加事件
action.on('vertex-add',function(evt){
createPolyline(evt,view,map);
});
//顶点移除事件
action.on('vertex-remove', function (evt) {
createPolyline(evt,view,map);
});
// 鼠标移动事件
action.on('cursor-update', function (evt) {
createPolyline(evt, view, map);
});
// 绘制完成事件
action.on('draw-complete', function (evt) {
createPolyline(evt, view, map);
})
// 绘制测线路径
function createPolyline(event,view,map){
let vertices = event.vertices;
lineLayer.removeAll() //清空上次绘制的线
lineTxtLayer.removeAll() //清空上次绘制的标注
lineEditLayer.removeAll() //清空上次绘制的编辑点
let graphic = null;
//开始绘制时只有一个点,鼠标移动的时候。
if(vertices.length == 1) {
addEditPt(lineLayer, event.vertices[0], 0)
}
//大于两个点,显示线
if(vertices.length >= 2){
// 线
let line = new Polyline({
paths:vertices,
spatialReference:view.spatialReference
});
// 生成绘制的图形
graphic = new Graphic({
geometry:line,
symbol:createLineSymbol()
})
// 线添加到绘制图形中
lineLayer.add(graphic);
// 测距单位文字添加
calLength(line.paths,view);
}
// 每次单击添加顶点时添加一个可移动的编辑节点
if(event.type == "vertex-add"){
let addGp = addEditPt(lineEditLayer, vertices[event.vertexIndex], event.vertexIndex)
editGps.push(addGp)
}
// 点击后鼠标移动
if(event.type == "cursor-update") {
//console.log("cursor-update");
}
// 绘制完成
if(event.type == "draw-complete") {
graphic.attributes = {
"drawId": "drawLine"
}
}
}
// 添加可编辑点
function addEditPt(layer,addVerties,index){
let editaddpt = {
type: "point",
x: addVerties[0],
y: addVerties[1],
spatialReference: view.spatialReference
}
let addPtSym = createPointSymbol();
let editAddGp = new Graphic({
attributes: {
"index": index
},
geometry: editaddpt,
symbol: addPtSym
})
layer.add(editAddGp);
return editAddGp;
}
});
// 计算长度
/**
* @param verties - 线段集合
* @param view - MapView容器
*/
function calLength(verties, view){
let polyline = new Polyline({
paths: verties,
spatialReference: view.spatialReference
});
let length = parseFloat(geometryEngine.geodesicLength(polyline, 'meters').toFixed(2)) //测距
let content = "距离:" + length + "米";
let txtPt = new Point({
x: verties[0][0][0],
y: verties[0][0][1],
spatialReference: view.spatialReference
})
createLineTextGraphic(content, txtPt)
// 使用几何服务计算距离
// let params = new LengthsParameters({
// calculationType:"planar",// 平面
// polylines:[polyline]
// });
// geometryService.lengths(geometryServiceUrl,params).then(function(results){
// let length = results.lengths[0];
// // 测距的单位
// let content = "距离:"+length.toFixed(2) + "米";
// // 文字位置
// let txPt = new Point({
// x:verties[0][0][0],
// y:verties[0][0][1],
// spatialReference:view.spatialReference
// });
// createLineTextGraphic(content, txtPt);
// });
}
//测距文字标注
function createLineTextGraphic(content, point){
lineTxtLayer.removeAll();// 清除上一次文字内容
let txtGp = new Graphic({
geometry: point,
symbol: createTextSymbol(content)
});
lineTxtLayer.add(txtGp);
}
3、测面方法
//******** 测面 **********/
export const measureArea = ((view,map) =>{
// 测距/测面初始化
initMeasure(view,map);
let editGps = [];
// 测距绘制
let draw = new Draw({
view: view
})
let action = draw.create("polygon", {
mode: "click"
})
// 获取焦点
view.focus();
// 顶点添加事件
action.on('vertex-add', function (evt) {
createPolygon(evt, view, map);
})
//顶点移除事件
action.on('vertex-remove', function (evt) {
createPolygon(evt, view, map);
})
// 鼠标移动事件
action.on('cursor-update', function (evt) {
createPolygon(evt, view, map);
})
// 绘制完成事件
action.on('draw-complete', function (evt) {
createPolygon(evt, view, map);
})
//根据点坐标生成新的线
function createPolygon(event, view, map) {
//获取所有顶点
let vertices = event.vertices;
let graphic = null;
//清除之前绘制
areaLayer.removeAll();//清空上次绘制的面
areaEditLayer.removeAll() //清空上次绘制的编辑点
areaTxtLayer.removeAll() //清空上次绘制的编辑点
//开始绘制时只有一个点,鼠标移动的时候。
if(vertices.length == 1) {
addEditPt(areaLayer, event.vertices[0], 0)
}
if(vertices.length == 2) {
let polyline = new Polyline({
paths:vertices,
spatialReference:view.spatialReference
})
let polylineGp = new Graphic({
geometry:polyline,
symbol: createLineSymbol()
})
areaLayer.add(polylineGp)
}
if(vertices.length > 2) {
let polygon = new Polygon({
hasZ: false,
hasM: false,
rings: [vertices],
spatialReference: view.spatialReference
})
// 生成绘制的图形
graphic = new Graphic({
geometry: polygon,
symbol: createFillSymbol()
});
// 将绘制的图形添加到view
areaLayer.add(graphic);
calArea(polygon,view)
}
//每次单击添加顶点时添加一个可移动的编辑节点
if(event.type == "vertex-add") {
let addGp = addEditPt(areaEditLayer, vertices[event.vertexIndex], event.vertexIndex)
editGps.push(addGp)
}
if(event.type == "cursor-update") {
}
if(event.type == "draw-complete") {
graphic.attributes = {
"drawId": "drawArea"
}
}
}
//添加可编辑点
function addEditPt(layer, addVerties, index) {
let editaddpt = {
type: "point",
x: addVerties[0],
y: addVerties[1],
spatialReference: view.spatialReference
}
let addPtSym = createPointSymbol();
let editAddGp = new Graphic({
attributes: {
"index": index
},
geometry: editaddpt,
symbol: addPtSym
})
layer.add(editAddGp);
return editAddGp;
}
});
//计算面积
function calArea(geom, view) {
let area = geometryEngine.geodesicArea(geom, "square-meters");
if(area < 0) {
// simplify the polygon if needed and calculate the area again
let simplifiedPolygon = geometryEngine.simplify(geom);
if(simplifiedPolygon) {
area = geometryEngine.geodesicArea(simplifiedPolygon, "square-meters");
}
}
let content = "面积:" + area.toFixed(2) + "平方米";
createAreaTextGraphic(content, geom.centroid);
// 使用几何服务计算面积
// let params = new AreasAndLengthsParameters({
// areaUnit:"square-meters",
// calculationType:"planar",
// lengthUnit:"meters",
// polygons:[geom]
// })
// geometryService.areasAndLengths(geometryServiceUrl, params).then(function (results) {
// let area = results.areas[0];
// let content = "面积:" + area.toFixed(2) + "平方米";
// createAreaTextGraphic(content, geom.centroid);
// });
}
//测面积文字标注
function createAreaTextGraphic(content, point) {
areaTxtLayer.removeAll();
let txtGp = new Graphic({
geometry: point,
symbol: createTextSymbol(content)
})
areaTxtLayer.add(txtGp);
}
4、公共方法
//测量清除
export const cleanMeasure = (() => {
lineLayer.removeAll() //清空上次绘制的线
lineTxtLayer.removeAll() //清空上次绘制的标注
lineEditLayer.removeAll() //清空上次绘制的编辑点
areaLayer.removeAll() //清空上次绘制的标注
areaEditLayer.removeAll() //清空上次绘制的编辑点
areaTxtLayer.removeAll() //清空上次绘制的编辑点
});
// 点样式设置
function createPointSymbol(){
return { //点样式
type: "simple-marker",
color: [255,165,0,0.5],
style: "circle",
width: 1,
size: 10,
outline:{//点的边界线
color: [255,255,255,0.5],
width: 1
}
}
}
// 线段样式设置
function createLineSymbol(){
return {
type: "simple-line", // autocasts as new SimpleFillSymbol
color: "#ff5502",
width: 2,
cap: "round",
join: "round"
}
}
// 填充样式设置
function createFillSymbol(){
return {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: [255,85,2,0.5],
style: "solid",
outline: { // autocasts as new SimpleLineSymbol()
color: "orange",
width: 2
}
}
}
// 文字符号设置
function createTextSymbol(content){
return {
type: "text",
text: content,
color: 'green',
font: {
size: 15,
}
}
}