用js如何计算地图某区域面积

JavaScript07

用js如何计算地图某区域面积,第1张

ArcGIS JS其实已经提供了量算的Widget,但是用过的童鞋都知道,那个玩意儿实在是太丑了,和程序搭配起来实在很突兀,因此自己实现一个量算工具是无疑是最好的办法,无图无真相,我先放两张效果图。

图1.量算面积

图2 量算距离

官方给出的Sample里,测量距离和面积都要用到GeoServeice,而且网上也都是类似的代码,都不是直接在客户端进行的量算。好在ArcGIS JS 在 3.13版本增加了 "esri/geometry/geometryEngine" 模块,借助这个模块就可以实现客户端的量算。

这个模块还有很多方法,具体内容可以到官网上查看geometryEngine的详细信息。

//计算距离

_calDistance: function (point1, point2) {            var line = new Polyline(this.defaults.map.spatialReference)

line.addPath([point1, point2])           if (this.defaults.map.spatialReference.isWebMercator()||this.defaults.map.spatialReference.wkid == "4326") {//在web麦卡托投影和WGS84坐标系下的计算方法

return geometryEngine.geodesicLength(line, "meters")

} else {//在其他投影坐标系下的计算方法

return geometryEngine.planarLength(line, "meters")

}

},

//计算面积

_calArea: function (polygon) {            var spatialReference = this.defaults.map.spatialReference           if (spatialReference.isWebMercator()||spatialReference.wkid == "4326" ) {                return geometryEngine.geodesicArea(polygon, "square-meters")

} else {                return geometryEngine.planarArea(polygon, "square-meters")

}

},

好了,解决了核心问题,剩下的就只需要如何分段显示距离和提高用户体验了。

1.测量距离

绘制线的时候,用的是ArcGIS JS 的Draw 模块在开始测量的时候,监听地图点击事件,把在地图上点击到的点加到 this._stopPoints 数组中,然后每次点击地图,就用当前点和上一个点进行距离计算,计算结果添加到this_stopDistances数组中,接着把计算结果用graphic添加到地图上。

//开始测量距离

_startMeasureDistance: function () {            this._clearMapMouseClickEvent()           this._stopPoints = []           this._stopDistances = []           this._measureLayer.clear()           this.toolbar.deactivate()           this.toolbar.activate(Draw.POLYLINE)           var stopPoints = this._stopPoints           var stopDistances = this._stopDistances           var self = this           this._mapClickFlag = this.defaults.map.on("click", function (evt) {                var distance = 0               var stopPoint = evt.mapPoint               if (stopPoints.length >0) {                    var startPoint = stopPoints[stopPoints.length - 1]

distance = self._calDistance(startPoint, stopPoint)                   if (self._stopDistances.length >0) {

distance += self._stopDistances[self._stopDistances.length - 1]

}

stopDistances.push(distance)

}

stopPoints.push(stopPoint)               var stopGraphic = new Graphic(stopPoint, self.defaults.markerSymbol)               var textGraphic = self._getStopPointGraphic(stopPoint, distance)

self._measureLayer.add(stopGraphic)

self._measureLayer.add(textGraphic)

})

},

结束量测,添加清除按钮,这里的清除按钮是用svg路径绘制的,在代码最后的this._clearMapMouseClickEvent()是用于取消监听map的click事件,在最后我会贴出全部代码。

//测量距离结束,添加清除按钮、测量线段

_endMeasureDistance:function(line,endPoint){            var lineGraphic = new Graphic(line, this.toolbar.lineSymbol)           var clearGraphic = this._createClearBtn(endPoint)           this._measureLayer.add(clearGraphic)           this._measureLayer.add(lineGraphic)

lineGraphic.getDojoShape().moveToBack()           this._clearMapMouseClickEvent()

},

2.面积量测

面积量测就相对简单了,用Draw模块绘制完成Polygon后,利用之前贴出的计算面积的方法计算完成后再把结果添加到地图上。

//开始测量面积

_startMeasureArea: function () {            this._clearMapMouseClickEvent()           this._measureLayer.clear()           this.toolbar.deactivate()           this.toolbar.activate(Draw.POLYGON)

},        //测量面积结束,添加清除按钮、测量结果

_endMeasureArea: function (polygon) {            var area = this._calArea(polygon)           if (area >1000000) {

area = (area / 1000000).toFixed(2) + "平方千米"

} else {

area = area.toFixed(2) + "平方米"

}            var center = polygon.getCentroid()           var ploygonGraphic = new Graphic(polygon, this.toolbar.fillSymbol)           var textSymbol = this._createTextSymbol(area)

textSymbol.setOffset(30, 10)           var textGraphic = new Graphic(center, textSymbol)           var clearBtn = this._createClearBtn(center)           this._measureLayer.add(ploygonGraphic)           this._measureLayer.add(textGraphic)           this._measureLayer.add(clearBtn)

ploygonGraphic.getDojoShape().moveToBack()

},

下面我们就来看一看如何使用这个自定义的测量模块了。

<!DOCTYPE html><html lang="en"><head>

<meta charset="UTF-8">

<title>Extra-Map-App</title>

<link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/css/esri.css">

<link rel="stylesheet" href="css/mainApp.css">

<script>

var dojoConfig = {

packages: [{

name: 'custom',

location: location.pathname.replace(/\/[^/]+$/, '') + '/custom'//从cdn加载自己定义的模块方法

},

{

name: 'dextra',

location: '/extra.arcgis.3.x/dist/'//从cdn加载自己定义的模块方法                }]

}   </script>

<script src="https://js.arcgis.com/3.16/"></script>

<script src="js/mainApp.js"></script>

<style>

#measureTools {

position: absolute

top: 50px

left: 50px

z-index: 1000

}

</style></head><body><div id="measureTools">

<button class="measure-distance">距离</button>

<button class="measure-area">面积</button></div><div id="map" style="overflow: hidden"></div></body></html>

在使构造时测量工具时,添加”.measure-distance”类表示测量距离;添加”.measure-area”类表示测量面积。在这个例子中,我的自定义模块名叫dextra,添加引用时按照dojo的AMD规范来进行加载。

require([    "esri/map",    "dextra/dijit/MeasureTools",    "dextra/layers/GoogleImageLayer",    "dextra/layers/GoogleImageAnnoLayer",    "dojo/domReady!"],    function(Map,

deMeasureTools,GoogleImageLayer,GoogleImageAnnoLayer) {        var map = new Map("map", {

showAttribution:false,

fadeOnZoom:true,

force3DTransforms:true,

center: [101.7, 24.6],

zoom: 10,

autoResize:true,

sliderPosition:"bottom-right",

logo:false,

})       var googleimgLayer=new GoogleImageLayer()       var googleAnnoLayer=new GoogleImageAnnoLayer()

map.addLayer(googleimgLayer)

map.addLayer(googleAnnoLayer)       var measureTool=new deMeasureTools({

map:map

},"measureTools")

})

CircleGeometry

圆形

RingGeometry

环形

PlaneGeometry

矩形的几何体

ShapeGeometry

通过路径构建一个多边形=>自定义形状

BoxGeometry

长方体

TetrahedronGeometry

四面体

ConeGeometry

圆锥

CylinderGeometry

圆柱

DodecahedronGeometry

十二面体

IcosahedronGeometry

二十面体

OctahedronGeometry

八面体

SphereGeometry

球体

TorusGeometry

圆环几何

TubeGeometry

管状体

LatheGeometry

轴向对称:例如花瓶

PolyhedronGeometry

多面体 =顶点+面

注:将它们投射到球体上,然后将其分割到所需的细节水平

ParametricGeometry

通过函数构建几何体,参量体

TextGeometry

文字体

TorusKnotGeometry

创建圆环结,其特殊形状由一对互质整数p和q定义。如果p和q不是互质的,结果将是环面连接。

ExtrudeGeometry

伸出的几何体,该对象将2D形状挤出到3D几何体。

EdgesGeometry

获取几何体的边线

WireframeGeometry

作帮助对象来将几何 对象视为线框