欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

leaflet_常用方法

程序员文章站 2022-06-11 16:12:43
...

0. note

    点     116.519623 39.871277
    线 116.341782 39.91316 ,116.431732 39.944753
    面 116.273804 39.931591,116.344528 39.939225,116.328049 39.898148,116.258354 39.906049
      经lng 纬lat度

1. 度转度°分′秒″

function ToDegrees(val) { //156.3564
    if (typeof (val) == "undefined" || val == "") {
        return "";
    }
    var i = val.indexOf('.');
    var strDu = i < 0 ? val : val.substring(0, i);//获取度
    var strFen = 0;
    var strMiao = 0;
    if (i > 0) {
        var strFen = "0" + val.substring(i);
        strFen = strFen * 60 + "";
        i = strFen.indexOf('.');
        if (i > 0) {
            strMiao = "0" + strFen.substring(i);
            strFen = strFen.substring(0, i);//获取分
            strMiao = strMiao * 60 + "";
            i = strMiao.indexOf('.');
            strMiao = strMiao.substring(0, i + 4);//取到小数点后面三位
            strMiao = parseFloat(strMiao).toFixed(2);//精确小数点后面两位
        }
    }
    return strDu + "," + strFen + "," + strMiao;
}

2. 度°分′秒″转度

function ToDigital(strDu, strFen, strMiao, len) {
    len = (len > 6 || typeof (len) == "undefined") ? 6 : len;//精确到小数点后最多六位   
    strDu = (typeof (strDu) == "undefined" || strDu == "") ? 0 : parseFloat(strDu);
    strFen = (typeof (strFen) == "undefined" || strFen == "") ? 0 : parseFloat(strFen) / 60;
    strMiao = (typeof (strMiao) == "undefined" || strMiao == "") ? 0 : parseFloat(strMiao) / 3600;
    var digital = strDu + strFen + strMiao;
    if (digital == 0) {
        return "";
    } else {
        return digital.toFixed(len);
    }
}

3. line.js 画线 + 动画

import {
path
} from ‘./line.js’;

let ary = [];
for (let i = 0; i < this.route_list.length; i++) {
  let lng = parseFloat(this.route_list[i].LNG);
  let lat = parseFloat(this.route_list[i].LAT);
  let color = this.route_list[i].LEVEL_COLOR;
  let ary_0 = [lat, lng, color];
  ary.push(ary_0);
}
let newarr = [];
newarr.push(ary);
let props = {};
props = {
  data: newarr,
  map: this.myMap,
  XCSJ: "2019-07-03"
}
path.initpath(props);
var path = {
  name: "人员路径",
  layerGroups: [],
  TotalLine: 0, //轨迹总数
  TotalPoint: 0, //轨迹中点的总数
  lineIndex: 0, //当前轨迹序号
  PointList: [], //每条轨迹包含点的个数
  linePathColor: '#bb343b', //路径颜色
  // 初始化
  initpath(props) {
    console.log(props);
    this.routeCoords = props.data;
    this.myMap = props.map;
    this.initLayer(props.XCSJ);
    this.setStartIcon(this.routeCoords[0][0]);
    this.setEndIcon(this.routeCoords[0][0]);
    this.addAllLine();
    this.TotalLine = this.routeCoords.length;
    this.TotalPoint = 0; //轨迹中点的总数
    this.pointIndex = 0;
    this.lineIndex = 0; //当前轨迹序号
    this.PointList = [];
    this.routeCoords.forEach((v, index) => {
      this.TotalPoint = this.TotalPoint + v.length;
      this.PointList.push(v.length);
      this.addPatrol(index);
    });
    // console.log(this.PointList);
  },
  //初始化图层
  initLayer() {
    if (this.layerGroups.length > 0) {
      this.layerGroups.forEach(da => {
        da.clearLayers();
      });
    } else {
      this.layerGroup = L.layerGroup().addTo(this.myMap);
      this.layerGroups.push(this.layerGroup);
    }
  },

  setStartIcon(val) { //设置起点
    // let markerS = L.circle([val[0], val[1]], {
    //   color: val[2],
    //   fillColor: val[2],
    //   fillOpacity: 1,
    //   radius: 12000, //半径
    // });
    // this.layerGroup.addLayer(markerS);
  },

  setEndIcon(val) { //设置终点
    let myIcon = L.divIcon({
      html: `<img style="" src="static/image/typhoon.png"></img> `,
      className: 'windy_direction_rotate',
    })
    let markerS = L.marker([val[0], val[1]], {
      icon: myIcon
    });
    // markerS.on('click', () => {
    //   typhoon_monitor_show_detail(this.routeCoords[0].length - 1);
    // });
    this.layerGroup.addLayer(markerS);
    this.nowMarker = markerS;
  },

  addAllLine() { //重置地图 使轨迹位于屏幕中部
    if (this.polyline) {
      this.polyline.remove();
    }
    this.polyline = L.polyline(this.routeCoords, {
      color: '#bb343b'
    });
    this.myMap.fitBounds(this.polyline.getBounds(), {
      paddingTopLeft: [100, 100],
      paddingBottomRight: [200, 100],
    })
  },

  addPatrol(index) { //添加轨迹
    // 线的起始点
    let start_lng = this.routeCoords[index][0][1];
    let start_lat = this.routeCoords[index][0][0];
    let start_color = this.routeCoords[index][0][2];
    let arr = [start_lat, start_lng];
    let linePathName = 'linePath' + index;
    this[linePathName] = L.polyline([arr], {
      color: this.linePathColor
    });
    let myIcon = L.divIcon({
      html: `<div style="width:10px;height:10px;background:${start_color};border-radius:50%;font-weight:600;"></div> `,
      iconAnchor: [5, 5],
      className: ''
    })
    let markerS = L.marker([start_lat, start_lng], {
      icon: myIcon,
    });
    // 起始点 marker
    // let markerS = L.circle([start_lat, start_lng], {
    //   color: start_color,
    //   fillColor: start_color,
    //   fillOpacity: 1,
    //   radius: 12000, //半径
    //   offset: [0, 0],
    // });
    markerS.on('click', () => {
      typhoon_monitor_show_detail(0)
    });
    this.layerGroup.addLayer(this[linePathName]);
    this.layerGroup.addLayer(markerS);

    if (index == this.TotalLine - 1) {
      this.startAnimation();
    }
  },
  //开始移动轨迹
  startAnimation() {
    let goto = true;
    while (this.isPath()) {
      this.pointIndex++;
      if (this.pointIndex = this.PointList[this.lineIndex] - 1) {
        goto = false;
        break;
      }
    }
    if (goto) {
      this.nowTime = new Date().getTime();
      this.moveFeature();
    }
  },
  //计算两个轨迹点之间的距离 如果距离过大 不移动 跳过该点
  isPath() {
    let A = this.routeCoords[this.lineIndex][this.pointIndex];
    let B = this.routeCoords[this.lineIndex][this.pointIndex + 1];
    var lat = [A[0], B[0]]
    var lng = [A[1], B[1]]
    var R = 6378137;
    var dLat = (lat[1] - lat[0]) * Math.PI / 180;
    var dLng = (lng[1] - lng[0]) * Math.PI / 180;
    var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat[0] * Math.PI / 180) * Math.cos(lat[1] * Math.PI / 180) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = R * c;
    return false;
  },
  //移动轨迹
  moveFeature() {
    if (this.routeCoords.length > 0) { //几条线  []
      let timestamp = new Date().getTime();
      let elapsedTime = timestamp - this.nowTime;
      let duration = elapsedTime / 100; //22毫秒
      if (duration < 1 && this.TotalPoint > this.pointIndex) {
        // let offsetX = (this.routeCoords[this.lineIndex][this.pointIndex + 1][0] - this.routeCoords[this.lineIndex][this.pointIndex][0]) * duration;
        // let offsetY = (this.routeCoords[this.lineIndex][this.pointIndex + 1][1] - this.routeCoords[this.lineIndex][this.pointIndex][1]) * duration;
        // let position = [this.routeCoords[this.lineIndex][this.pointIndex][0] + offsetX, this.routeCoords[this.lineIndex][this.pointIndex][1] + offsetY];
        // this.nowMarker.setLatLng(position);
        // this['linePath' + this.lineIndex].addLatLng(position);
        this['linePath' + this.lineIndex].addLatLng(this.routeCoords[this.lineIndex][this.pointIndex + 1]);
        requestAnimationFrame(this.moveFeatureSelf(this));
      } else {
        this.stopAnimation();
      }
    }
  },
  moveFeatureSelf(self) {
    return self.moveFeature.bind(self)
  },

  stopAnimation() { //停止移动轨迹
    let num = this.pointIndex + 1;
    let val = this.routeCoords[0][this.pointIndex + 1];
    let myIcon = L.divIcon({
      html: `<div style="width:10px;height:10px;background:${val[2]};border-radius:50%;font-weight:600;"></div> `,
      iconAnchor: [5, 5],
      className: 'stopAnimation'
    })

    let markerS = L.marker([val[0], val[1]], {
      icon: myIcon
    });
    // let markerS = L.circle([val[0], val[1]], {
    //   color: val[2],
    //   fillColor: val[2],
    //   fillOpacity: 1,
    //   radius: 12000 //半径
    // });
    markerS.on('click', () => {
      typhoon_monitor_show_detail(num)
    });
    this.layerGroup.addLayer(markerS);

    this.pointIndex++;
    // 画完一条线 开始画另一条线
    if ((this.pointIndex > this.PointList[this.lineIndex] - 2) &&
      this.lineIndex < this.TotalLine - 1) {
      this.lineIndex++;
      this.pointIndex = 0;
    }
    if (this.pointIndex < this.PointList[this.lineIndex] - 1) { //更新终点位置
      this.nowMarker.setLatLng(this.routeCoords[this.lineIndex][this.pointIndex + 1]);
      this.startAnimation();
    }
  },
}

export {
  path
}

4. 画四个半径不同的圆形

由四个扇形构成 200,200,200,200

draw_arcs(item, LAT, LNG, type) {
      let radius_list = Array.from(item.split(","));
      let arc_list = [{
        from: 0,
        to: 90
      }, {
        from: 90,
        to: 180
      }, {
        from: 180,
        to: 270
      }, {
        from: 270,
        to: 360
      }];
      let lng_lat = {
        lon: LNG,
        lat: LAT,
      }
      this.typhoon_range = [];

      arc_list.map((item, index) => {
        let points = this.getPoints([LAT, LNG], parseInt(radius_list[index]) / 200, item.from, item.to, 500);
        this.typhoon_range = this.typhoon_range.concat(points);
      })

      let typhoon_range_item = L.polygon(this.typhoon_range, {
        color: type == 7 ? "rgb(255, 248, 0)" : "rgb(247, 122, 6)",
        fillColor: type == 7 ? "rgb(210, 205, 45)" : "rgb(192, 121, 55)",
        fillOpacity: 0.2,
      }).addTo(this.typhoon_range_group);
    }

画扇形

  getPoints(center, radius, startAngle, endAngle, pointNum) {
      /**
       *
       * @param center 中心点 数组
       * @param radius 半径 km
       * @param startAngle 起始角度
       * @param endAngle 终止角度
       * @param pointNum 圆弧上点的个数
       */
      var sin;
      var cos;
      var x;
      var y;
      var angle;
      var points = new Array();

      for (var i = 0; i <= pointNum; i++) {
        angle = startAngle + (endAngle - startAngle) * i / pointNum;
        sin = Math.sin(angle * Math.PI / 180);
        cos = Math.cos(angle * Math.PI / 180);
        y = parseFloat(center[0]) + parseFloat(radius * cos);
        x = parseFloat(center[1]) + parseFloat(radius * sin);
        points[i] = [y, x];
      }
      // points.push(center); //扇形
      return points;
    },

5. 已知一个经纬度,距离,仰角->另一个经纬度

import {
get_another_lng_lat
} from ‘./get_another_lng_lat.js’;

let arc_list = [{
      from: 0,
      to: 90
    }, {
      from: 90,
      to: 180
    }, {
      from: 180,
      to: 270
    }, {
      from: 270,
      to: 360
    }];
    
    
    let circle_list = [{
      radius: 5000,
      color: 'red',
      rotate: 120,
      num: 0,
    }, {
      radius: 4000,
      color: 'green',
      rotate: 160,
      num: 1,
    }, {
      radius: 3000,
      color: 'blue',
      rotate: 180,
      num: 2,
    }, {
      radius: 3000,
      color: 'pink',
      rotate: 90,
      num: 2,
    }];
    let lng_lat = {
      lng: this.initMap.lng,
      lat: this.initMap.lat,
    }
    
    arc_list.map((item, index) => {
      let points = this.getPoints([this.initMap.lat, this.initMap.lng], circle_list[index].radius / 100000, item.from, item.to, 500);
      points[points.length] = points[0];
      L.polygon(points, {
        color: circle_list[index].color
      }).addTo(this.myMap);
    })
    
    circle_list.map((item) => {
      L.circle([this.initMap.lat, this.initMap.lng], { // 圆形 LatLng
        color: item.color,
        fillColor: '#ccc',
        fillOpacity: 0,
        radius: item.radius //半径
      }).addTo(this.myMap);
    
    
    
      L.polygon([ // 多边形  LatLng
        [this.initMap.lat, this.initMap.lng],
        [get_another_lng_lat.destinationVincenty(lng_lat, item.rotate, item.radius).lat,
          get_another_lng_lat.destinationVincenty(lng_lat, item.rotate, item.radius).lng
        ],
      ], {
        color: item.color
      }).addTo(this.myMap);
    
      let myIcon = L.divIcon({
        html: `<div style="position:relative;top:20px;width:100px;font-weight:600;">${item.radius}米,${item.num}次</div> `,
        iconAnchor: [20, 20],
        iconSize: [40, 40],
        className: 'higtIcon'
      })
    
      L.marker([get_another_lng_lat.destinationVincenty(lng_lat, item.rotate, item.radius).lat,
        get_another_lng_lat.destinationVincenty(lng_lat, item.rotate, item.radius).lng
      ], {
        icon: myIcon
      }).addTo(this.myMap);
    })
var get_another_lng_lat = {
  VincentyConstants: {
    a: 6378137,
    b: 6356752.3142,
    f: 1 / 298.257223563
  },
  /**
   *Calculate destination point given start point lat/long (numeric degrees),
   * bearing (numeric degrees) & distance (in m).
   */
  destinationVincenty: function(lonlat, brng, dist) {
    var u = this;
    var ct = u.VincentyConstants;
    var a = ct.a,
      b = ct.b,
      f = ct.f;

    var lon1 = lonlat.lon;
    var lat1 = lonlat.lat;

    var s = dist;
    var alpha1 = u.rad(brng);
    var sinAlpha1 = Math.sin(alpha1);
    var cosAlpha1 = Math.cos(alpha1);

    var tanU1 = (1 - f) * Math.tan(u.rad(lat1));
    var cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)),
      sinU1 = tanU1 * cosU1;
    var sigma1 = Math.atan2(tanU1, cosAlpha1);
    var sinAlpha = cosU1 * sinAlpha1;
    var cosSqAlpha = 1 - sinAlpha * sinAlpha;
    var uSq = cosSqAlpha * (a * a - b * b) / (b * b);
    var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
    var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));

    var sigma = s / (b * A),
      sigmaP = 2 * Math.PI;
    while (Math.abs(sigma - sigmaP) > 1e-12) {
      var cos2SigmaM = Math.cos(2 * sigma1 + sigma);
      var sinSigma = Math.sin(sigma);
      var cosSigma = Math.cos(sigma);
      var deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
        B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
      sigmaP = sigma;
      sigma = s / (b * A) + deltaSigma;
    }

    var tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;
    var lat2 = Math.atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
      (1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp));
    var lambda = Math.atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1);
    var C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
    var L = lambda - (1 - C) * f * sinAlpha *
      (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));

    var revAz = Math.atan2(sinAlpha, -tmp); // final bearing

    //                    return new OpenLayers.LonLat(lon1 + u.deg(L), u.deg(lat2));
    // console.log(lon1 + u.deg(L), u.deg(lat2));
    return {
      lng: parseFloat(lon1) + parseFloat(u.deg(L)),
      lat: parseFloat(u.deg(lat2))
    }
  },

  /**
   * 度换成弧度
   * @param  {Float} d  度
   * @return {[Float}   弧度
   */
  rad: function(d) {
    return d * Math.PI / 180.0;
  },

  /**
   * 弧度换成度
   * @param  {Float} x 弧度
   * @return {Float}   度
   */
  deg: function(x) {
    return x * 180 / Math.PI;
  }
}
export {
  get_another_lng_lat
}

6.地图联动

this.mapImgInit.map.on('mouseover', e => {
    this.mapImgActiveNum = 0;
});

this.mapImgCollect.map.on('mouseover', e => {
    this.mapImgActiveNum = 1;
});

this.mapImgInit.map.on("moveend", ev => {
    if (this.mapImgActiveNum === 0) {
        let obj = this.mapImgInit.map.getBounds();
        let imageBounds = [[obj._northEast.lat, obj._northEast.lng], [obj._southWest.lat, obj._southWest.lng]];
        this.mapImgCollect.map.fitBounds([imageBounds]);
    }

});
this.mapImgCollect.map.on("moveend", ev => {
    if (this.mapImgActiveNum === 1) {
        let obj = this.mapImgCollect.map.getBounds();
        let imageBounds = [[obj._northEast.lat, obj._northEast.lng], [obj._southWest.lat, obj._southWest.lng]];
        this.mapImgInit.map.fitBounds([imageBounds]);
        this.mapImgInit.isActive = false;
    }
});

7. geo_json_data

import * as map_geojson_data from ‘…/…/…/…/static/js/map/sample-geojson.js’

link

let greenIcon = L.icon({ //坐标图
    iconUrl: '../../../../static/img/market/marker-icon.png', //图标地址
    iconSize: [25, 41], // 图标宽高
    popupAnchor: [-0, -20] // 弹出框弹出位置,相对于图标锚点
});

let coorsLayer = L.geoJSON(map_geojson_data.coorsField, { //小人
    pointToLayer: (feature, latlng) => {
        return L.marker(latlng, {
            icon: greenIcon
        }).bindPopup(feature.properties.popupContent);
    },
}).addTo(this.mymap);

L.geoJSON([map_geojson_data.bicycleRental, map_geojson_data.campus], { //点
    style: function(feature) {
        return feature.properties && feature.properties.style;
    },
    onEachFeature: this.onEachFeature,
    pointToLayer: function(feature, latlng) {
        return L.circleMarker(latlng, {
            radius: 8,
            fillColor: "darkgreen",
            color: "black",
            weight: 1,
            opacity: 1,
            fillOpacity: 0.8
        });
    }
}).addTo(this.mymap);

L.geoJSON(map_geojson_data.freeBus, { //线
    filter: function(feature, layer) {
        if (feature.properties) {
            // If the property "underConstruction" exists and is true, return false (don't render features under construction)
            return feature.properties.underConstruction !== undefined ? !feature.properties.underConstruction : true;
        }
        return false;
    },
    style: function(feature) {
        switch (feature.properties.party) {
            case 'Republican':
                return {
                    color: "#ff0000"
                };
            case 'Democrat':
                return {
                    color: "#0000ff"
                };
            case 'Democrat_1':
                return {
                    color: "lightblue"
                };
        }
    },
    onEachFeature: this.onEachFeature
}).addTo(this.mymap);

 onEachFeature(feature, layer) { // 弹出框
    let popupContent = "<p>我来自GeoJSON的" +
        feature.geometry.type + ", 但是我现在是个矢量元素</p>";
    if (feature.properties && feature.properties.popupContent) {
        popupContent += feature.properties.popupContent;
    }
    layer.bindPopup(popupContent);
}


8. 定位

8.1 天地图

http://api.tianditu.gov.cn/geocoder?
postStr={%27lon%27:116.37304,%27lat%27:39.92594,%27ver%27:1}&
type=geocode&tk=c32c9da708e8fd5117a5af5cf71f58ed

8.2 百度地图

<html>

    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
        <style type="text/css">
            body,
            html,
            #allmap {
                width: 100%;
                height: 100%;
                overflow: hidden;
                margin: 0;
                font-family: "微软雅黑";
            }
        </style>
        <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=NCF1cHxumgwMdr12FRWhVSdY5yhfzR0f"></script>
        <title>浏览器定位</title>

    </head>

    <body>
        <div id="allmap"></div>
    </body>

</html>

9. 加载矢量瓦片地图 错位

切换矢量瓦片地图 
marker点 marker标题 和矢量瓦片地图错误

解决办法 将瓦片地图放到 多个图层组
相关标签: gis