リーフレット スタート ガイド: Gaode マップと座標オフセット処理メソッドの追加

前回のリーフレット スタート ガイド: インタラクティブ マップを最初から作成する記事では、基本的なマップ アプリケーションを実装しましたが、この記事では、Amap (サンプリング GCJ-02 座標系) とマップ オフセットを処理するいくつかの方法を追加します。

Amapと座標系補正を追加

Gaode衛星地図とGaode街路情報透明地図を追加します。

<script>
  // osm
  let openstreetmap = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'})

  // 高德
  let amap = L.layerGroup([L.tileLayer('http://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', {
    
    
    minZoom:6,
    maxZoom: 18,
    attribution: '© AMap'
  }), L.tileLayer('http://webst03.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}', {
    
    
    minZoom:6,
    maxZoom: 18,
    attribution: '© AMap'
  })]);

  let baseLayers = {
    
    
    'OpenStreetMap': openstreetmap,
    'Streets': amap
  };

  // 创建地图对象,并设置 OSM 作为默认底图
  let map = L.map('map', {
    
    
    center: [22.5247, 113.8578],
    zoom: 13,
    layers: [openstreetmap], // 设置 OSM 为默认底图
  });

  L.control.layers(baseLayers).addTo(map);
</script>

地図

地図修正

上の図のように、マーカーの実際の経度・緯度校正位置[22.5247, 113.8578]と表示されている位置との間にずれがあることがわかります。Amap は GCJ-02 座標系を使用し、マーカーは WGS-84 座標系を使用するため、WGS-84 座標系から GCJ-02 座標系への変換を実行する必要があります。
WGS-84 GCJ-02 BD-09

ディレクトリ内のファイルをウェアハウスからhttps://github.com/googollee/eviltransformダウンロードし、同じレベルのディレクトリ置きます。eviltransform/javascript/transform.jstransform.jsindex.html

以下の内容をhtmlに追加します

<script type="text/javascript" src='./transform.js' crossorigin=""></script>

または、cdn アクセラレーションtransform.min.jsファイルを使用します

<script src="https://cdn.jsdelivr.net/npm/[email protected]/transform.min.js" crossorigin=""></script>

WGS-84からGCJ-02への変換は以下の関数に入力した経度と緯度を入力するだけeviltransform.wgs2gcjで実現できます。22.5247, 113.8578

let geo = eviltransform.wgs2gcj(22.5247, 113.8578)
let marker = L.marker(geo).addTo(map);
marker.bindPopup("这是一个标记的弹出窗口。").openPopup();

アンプ
上記では、入力座標をタイルの同じ座標系に直接変換する方法を使用しました。

もちろん、他の方法も使用できます。

  1. CRS プラグインをカスタマイズし、このプラグインを使用して latLngToPoint メソッドでオフセットを処理します。
    L.CRS.CustomCRS = L.extend({
    
    }, L.CRS.EPSG3857, {
    
    
        // 实现 latLngToPoint 和 pointToLatLng 方法
        latLngToPoint: function (latlng, zoom) {
    
    

			// 判断经纬度的来源,瓦片请求不做处理,其他请求来源做偏移处理。
            // if(latlng.lat === 22.5247 && latlng.lng === 113.8578){
    
    
            //     let a = eviltransform.wgs2gcj(latlng.lat, latlng.lng)
            //     latlng.lat = a.lat
            //     latlng.lng = a.lng
            // }else
            // {
    
    
            //     console.log("other")
            // }


            // 自定义实现 latLngToPoint 方法
            var projectedPoint = this.projection.project(latlng);
            var scale = this.scale(zoom);
            var point = this.transformation.transform(projectedPoint, scale);

            console.log("latLngToPoint:",point.x,point.y)

            return point;
        },

        pointToLatLng: function (point, zoom) {
    
    
            // 自定义实现 pointToLatLng 方法
            var scale = this.scale(zoom);
            var untransformedPoint = this.transformation.untransform(point, scale);
            var latlng = this.projection.unproject(untransformedPoint);

            console.log("pointToLatLng:",point.x,point.y)

            return latlng;
        }
    })

マップをインスタンス化するときは、カスタム L.CRS.CustomCRS を使用します。

let map = L.map('map', {
    
    crs: window.L.CRS.CustomCRS}).setView([22.5247, 113.8578], 13);
  1. Marker プラグインをカスタマイズし、このプラグインを使用して更新メソッドでオフセット処理を実行します。
  // 定义 CustomMarker 插件
  L.CustomMarker = L.Marker.extend({
    options: {
      // 这里可以添加自定义的选项
    },

    // 初始化方法
    initialize: function (latlng, options) {
      L.Marker.prototype.initialize.call(this, latlng, options);
    },
    update: function () {
      if (this._icon && this._map) {
        // 偏移处理
        if(isSelectedAMap){
          let geo = eviltransform.wgs2gcj(this._latlng.lat, this._latlng.lng)
          let pos = this._map.latLngToLayerPoint(geo).round();
          this._setPos(pos);
        }else{
          let pos = this._map.latLngToLayerPoint(this._latlng).round();
          this._setPos(pos);
        }
      }
      return this;
    },
  });

  // 工厂方法
  L.customMarker = function (latlng, options) {
    return new L.CustomMarker(latlng, options);
  };

説明書:

let marker = L.customMarker([22.5247, 113.8578]).addTo(map);

完全なコード

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Leaflet@cheungxiongwei</title>
  <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
        integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
        crossorigin=""/>
  <!-- Make sure you put this AFTER Leaflet's CSS -->
  <script src="https://unpkg.com/[email protected]/dist/leaflet.js"
          integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
          crossorigin=""></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/transform.min.js" crossorigin=""></script>
  <style>
    html, body {
    
    
      overflow: hidden;
      background: #fff;
      width: 100%;
      height: 100%;
      margin: 0;
      position: absolute;
      top: 0;
    }
    #map {
    
    
      height: 100%;
      width: 100%;
      margin: 0 auto;
      background-color: #01172a;
    }
  </style>
</head>
<body>
<div id="map"></div>
</body>
<script>
  // 定义 CustomMarker 插件
  L.CustomMarker = L.Marker.extend({
    
    
    options: {
    
    
      // 这里可以添加自定义的选项
    },

    // 初始化方法
    initialize: function (latlng, options) {
    
    
        L.Marker.prototype.initialize.call(this, latlng, options);
    },
    update: function () {
    
    
      if (this._icon && this._map) {
    
    
        // 偏移处理
        if(isSelectedAMap){
    
    
          let geo = eviltransform.wgs2gcj(this._latlng.lat, this._latlng.lng)
          let pos = this._map.latLngToLayerPoint(geo).round();
          this._setPos(pos);
        }else{
    
    
          let pos = this._map.latLngToLayerPoint(this._latlng).round();
          this._setPos(pos);
        }
      }
      return this;
    },
  });

  // 工厂方法
  L.customMarker = function (latlng, options) {
    
    
    return new L.CustomMarker(latlng, options);
  };
 
  // osm
  let openstreetmap = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'})

  // 高德
  let amap = L.layerGroup([L.tileLayer('http://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', {
    
    
    minZoom:6,
    maxZoom: 18,
    attribution: '© AMap'
  }), L.tileLayer('http://webst03.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}', {
    
    
    minZoom:6,
    maxZoom: 18,
    attribution: '© AMap'
  })]);

  let baseLayers = {
    
    
    'OpenStreetMap': openstreetmap,
    'Streets': amap
  };

  // 创建地图对象,并设置 OSM 作为默认底图
  let map = L.map('map', {
    
    
    center: [22.5247, 113.8578],
    zoom: 13,
    layers: [amap], // 设置 OSM 为默认底图
  });

  L.control.layers(baseLayers).addTo(map);

  let isSelectedAMap = true
  // 监听底图切换事件
  map.on('baselayerchange', function (event) {
    
    
    // 获取当前选择的地图图层
    let selectedLayer = event.layer;

    // 判断当前选择的地图
    if (selectedLayer === openstreetmap) {
    
    
      console.log('当前选择的地图是 OpenStreetMap');
      // 在这里执行其他逻辑
      isSelectedAMap = false
    } else if (selectedLayer === amap) {
    
    
      console.log('当前选择的地图是 Streets');
      // 在这里执行其他逻辑
      isSelectedAMap = true
    }
  });

  let marker = L.customMarker([22.5247, 113.8578]).addTo(map);
</script>
</html>

おすすめ

転載: blog.csdn.net/cheungxiongwei/article/details/132062605