一、安装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()});// 将绘制的图形添加到viewareaLayer.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 againlet 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 SimpleFillSymbolcolor: "#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,}}
}