ArcGIS测距测面(arcgis for js - vue3项目)

一、安装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,
		}
	}
}


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值