arcgis api 结合turf.js实现测距

turf.js是一个开源的空间分析库,主要用实现在网页端空间几何对象关系的计算,测距只是其中的一个简单功能。

计算两个点的距离:
在这里插入图片描述
计算两个点以上的线段的总长度:
在这里插入图片描述
源码地址:https://github.com/Turfjs/turf
官网文档: http://turfjs.org/
代码中需引入turf.js库,可下载到本地,也可引用互联网上的,互联网在线引用:
在这里插入图片描述
另外,还引入了dojo的订阅发布消息模式,使代码更具灵活性和方便测试。
topic.publish:用于发布消息,接收任意多个参数,第一参数为要发布的信息名字(唯一标识),其他参数为传递给订阅回调函数的参数。
topic.subscribe:用于订阅消息,接收两个参数,第一参数为要订阅的消息名字(唯一标识),第二参数为回调函数。

实现效果:
在这里插入图片描述
所有引用和地图均来自互联网,复制可直接打开,全部代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>arcgis api 结合turf.js实现测距</title>
  <link rel="stylesheet" href="https://js.arcgis.com/3.20/esri/css/esri.css">
  <style>
    body,
    html {
      margin: 0;
      padding: 0;
      width: 100%;
      height: 100%;
      font-family: Arial;
    }
    #map {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
      border: 0px dashed black;
      background-color: rgb(0, 38, 48);
    }
  </style>
</head>
<body>
  <button type="button" onclick="mouseClick()">测距</button>
  <button type="button" onclick="clearLine()">清除</button>
  <div id="map">
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@5/turf.min.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script src="https://js.arcgis.com/3.20"></script>
<script type="text/javascript">
  dojo.require("dojo.topic") //引入发布订阅者模式
  var map, mouseClick, clearLine;
  require([
    "esri/map",
    'esri/Color',
    'esri/geometry/Point',
    "esri/geometry/Polyline",
    "esri/symbols/TextSymbol",
    "esri/layers/GraphicsLayer",
    "esri/layers/ArcGISTiledMapServiceLayer",
    'esri/graphic',
    'esri/symbols/SimpleMarkerSymbol',
    'esri/symbols/SimpleLineSymbol',
    "esri/geometry/Extent",
    "dojo/domReady!"
  ], function(
    Map,
    Color,
    Point,
    Polyline,
    TextSymbol,
    GraphicsLayer,
    ArcGISTiledMapServiceLayer,
    Graphic,
    SimpleMarkerSymbol,
    SimpleLineSymbol,
    Extent
  ) {
    //地图范围
    var mapExtent = new Extent({
      xmax: 113.799760210539,
      xmin: 106.57095767482662,
      ymax: 20.459116202966324,
      ymin: 18.27952992162579,
      spatialReference: {
        wkid: 4326
      }
    })
    map = new Map("map", {
      extent: mapExtent,
      sliderStyle: "small",
      logo: false,
    });
    map.on('load', function () {
      map.hideZoomSlider()
      map.hidePanArrows()
      map.disableDoubleClickZoom() //禁用双击缩放
    })

    //arcgis 在线切片底图图
    var myTileLayer = new ArcGISTiledMapServiceLayer("http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineCommunity/MapServer");
    map.addLayer(myTileLayer)

    var graphicLayer = new GraphicsLayer() //绘制图层
    map.addLayer(graphicLayer)

    var lineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASH,new Color([176, 196, 222]),3); //线样式
    var markerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 8, //点样式
        new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
        new Color([0, 0, 0]), 1),
        new Color([47, 79, 79, 0.5]))
    
    var linePath = [] //鼠标点击获得经纬度集合
    var index = 0 //点击次数

    //激活鼠标点击方法
    mouseClick =  function() {
     //鼠标单击并发布消息
      map.on('click',function(evt) {
        let lon = evt.mapPoint.getLongitude() //获得单击经度
        let lat = evt.mapPoint.getLatitude() //获得单击纬度
        let point = new Point(lon, lat) //生成点矢量
        dojo.topic.publish("getPoint", point) //发布单击点消息
        dojo.topic.publish("getLonLat", [lon, lat]) //发布单击经纬度消息
      }) 
      //鼠标双击并发布消息
      map.on('DblClick', function(evt) {
        let lon = evt.mapPoint.getLongitude() //获得双击经度
        let lat = evt.mapPoint.getLatitude() //获得双击纬度
        let point = new Point(lon, lat) //生成点矢量
        dojo.topic.publish("dblGetPoint", point) //发布双击点消息
        dojo.topic.publish("dblGetLonLat", [lon, lat])//发布双击经纬度消息
      })
    }

    //单击:订阅点消息并添加到地图
    dojo.topic.subscribe("getPoint", function(point) {
      let pointGraphic = new Graphic(point,markerSymbol)
      graphicLayer.add(pointGraphic)
    })

    //单击:订阅经纬度消息
    dojo.topic.subscribe("getLonLat", function(data) {
      linePath.push(data) //将单击获得的经纬度放入集合
      if (linePath.length>=2) { //如果单击次数大于等于2
        //单击点画线并添加到地图
        let line = new Polyline()
        line.addPath(linePath)
        let lineGraphic = new Graphic(line, lineSymbol)
        graphicLayer.add(lineGraphic)
        //测量两点间的距离
        let from = turf.point(linePath[index]) //上次点击的点
        let to = turf.point(linePath[index+1]) //当前点击的点
        let options = {units: 'metres'} //单位:米
        let distance = turf.distance(from, to, options).toFixed(2) //测距
        let textPoint = new Point(linePath[index+1][0],linePath[index+1][1])
        let t = lengthFormat(distance)
        let textSymbol = new TextSymbol(t) //标注实例
        textSymbol.setOffset(0, 5) //标注偏移
        let textGraphic = new Graphic(textPoint, textSymbol) 
        graphicLayer.add(textGraphic) //添加标注到地图
        index++  //点击次数自增1
      }
    })

    //双击:订阅点消息并添加到地图
    dojo.topic.subscribe("dblGetPoint", function(point) {
      let pointGraphic = new Graphic(point,markerSymbol) 
      graphicLayer.add(pointGraphic)
    })

    //双击:订阅经纬度消息
    dojo.topic.subscribe("dblGetLonLat", function(data) {
        let lineLength = linePath.length //单击次数
        linePath.push(data) //将双击点经纬度加入集合
        if (linePath.length>=2) { //双击后如果总的次数>=2
          //所有点生成的线添加到地图
          let line = new Polyline() 
          line.addPath(linePath)
          let lineGraphic = new Graphic(line, lineSymbol)
          graphicLayer.add(lineGraphic)
          //测量最后两点的距离
          let from = turf.point(linePath[lineLength-1]) //最后单击的点
          let to = turf.point(data) //双击的点
          let options = {units: 'metres'} //单位:米
          let distance = turf.distance(from, to, options).toFixed(2) //测距
          //最后两点距离标注点
          let endPoint = new Point(data[0],data[1]) //标注位置
          let t = lengthFormat(distance)
          console.log(t)
          let textSymbol = new TextSymbol(t) //标注实例
          textSymbol.setOffset(0, 5) //标注偏移
          let textGraphic = new Graphic(endPoint, textSymbol) 
          graphicLayer.add(textGraphic) //添加标注到地图
          //计算总长度和弹窗
          let length = turf.lineString(linePath) //全部线段
          let allLength = turf.length(length, {units: 'metres'}).toFixed(2) //计算全部线段长度
          let lengthText = lengthFormat(allLength) //单位转换
          map.infoWindow.setContent(lengthText) //弹窗内容
          map.infoWindow.show(endPoint) //弹窗显示位置  
          linePath.length = 0 //下次测量前清空集合
          index = 0 //双击后点击次数归零
        }
        else {
          alert("最少需要两个点")
          graphicLayer.clear() //清除
          map.infoWindow.hide() //隐藏弹窗
          linePath.length = 0  //下次测量前清空集合
      }
    })
    //清除
    clearLine = function() {
      graphicLayer.clear()
      map.infoWindow.hide()
    }

    //长度单位转换
    function lengthFormat(length) {
      if (length < 2000) {
        return lengthText = "总长:" + length + "米"
      }
      else {
        length = (length/1000).toFixed(2)
        return lengthText = "总长:" + length + "千米"
      }
    }

  });
</script>
</html>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值