侧边栏壁纸
博主头像
优吉斯空间 - YouGIS.COM.CN博主等级

行动起来,活在当下

  • 累计撰写 6 篇文章
  • 累计创建 17 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

Leaflet加载百度地图开发示例 - 最新最全最详细

Administrator
2024-08-29 / 0 评论 / 1 点赞 / 434 阅读 / 14187 字 / 正在检测是否收录...

优吉斯(武汉)空间信息

> 公众号:yougis

> 主页:yougis.com.cn

> 工具:yougis.cn

yougis_wx_ewm.jpg

百度地图是国内使用最广泛的互联网地图之一,在WebGIS开发中,有广泛的应用。但不同于谷歌、天地图、高德等互联网地图,百度地图的坐标系(百度09)、切片方式自成体系。本文详细介绍如何通过Leaflet加载百度地图,如使用其他JS SDK,参照本文的加载思路,进行相应修改即可。

Leaflet加载百度地图的开发示例(load-baidu-map.html)

一、自定义百度坐标系

百度地图的切片原点与谷歌、天地图等不一致,且坐标系与常用的WGS84、GCJ02不一致,因此需自定义空间参考,在Leaflet中定义的方式如下所示。

L.CRS.Baidu = new L.Proj.CRS(
  "EPSG:900913",
  "+proj=merc +a=6378206 +b=6356584.314245179 +lat_ts=0.0 +lon_0=0.0 +x_0=0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs",
  {
    resolutions: (function () {
      level = 19;
      re = 18;
      var res = [];
      res[0] = Math.pow(2, re);
      for (var i = 1; i < level; i++) {
        res[i] = Math.pow(2, re - i);
      }
      return res;
    })(),
    origin: [0, 0],
    bounds: L.bounds([20037508.342789244, 0], [0, 20037508.342789244]),
  }
);

二、定义百度地图加载函数

下面定义加载百度各类型地图的加载函数,方便在不同地图间的切换,Leaflet中定义方式如下所示。

L.tileLayer.baidu = function (option) {
  option = option || {};
  var layer;
  var subdomains = "0123456789";
  switch (option.layer) {
    //单图层
    case "vec":
    default:
      //"http://online{s}.map.bdimg.com/tile/?qt=tile&x={x}&y={y}&z={z}&styles=pl&b=0&limit=60&scaler=1&udt=20170525"
      // layer = L.tileLayer("http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=" + (option.bigfont ? "ph" : "pl") + "&scaler=1&p=1", {
      //     name: option.name, subdomains: subdomains, tms: true
      // });
      layer = L.tileLayer(
        "https://maponline0.bdimg.com/tile/?qt=vtile&x={x}&y={y}&z={z}&styles=pl&scaler=2&udt=20230105&from=jsapi2_0",
        {
          name: option.name,
          subdomains: subdomains,
          tms: true,
        }
      );
      break;
    case "img_d":
      layer = L.tileLayer(
        "http://shangetu{s}.map.bdimg.com/it/u=x={x};y={y};z={z};v=009;type=sate&fm=46",
        {
          name: option.name,
          subdomains: subdomains,
          tms: true,
        }
      );
      break;
    case "img_z":
      layer = L.tileLayer(
        "http://online{s}.map.bdimg.com/tile/?qt=tile&x={x}&y={y}&z={z}&styles=" +
        (option.bigfont ? "sh" : "sl") +
        "&v=020",
        {
          name: option.name,
          subdomains: subdomains,
          tms: true,
        }
      );
      break;

    case "custom": //Custom 各种自定义样式
      //可选值:dark,midnight,grayscale,hardedge,light,redalert,googlelite,grassgreen,pink,darkgreen,bluish
      option.customid = option.customid || "dark";
      layer = L.tileLayer(
        //   "http://api{s}.map.bdimg.com/customimage/tile?&x={x}&y={y}&z={z}&scale=1&customid=" + option.customid,
        "http://api{s}.map.bdimg.com/customimage/tile?&x={x}&y={y}&z={z}&ak=yipxfCwhMDozKT3GDCM7UGARmSKbAMXh&scale=1&customid=" +
        option.customid,
        {
          name: option.name,
          subdomains: "012",
          tms: true,
        }
      );
      break;

    case "time": //实时路况
      var time = new Date().getTime();
      layer = L.tileLayer(
        "http://its.map.baidu.com:8002/traffic/TrafficTileService?x={x}&y={y}&level={z}&time=" +
        time +
        "&label=web2D&v=017",
        {
          name: option.name,
          subdomains: subdomains,
          tms: true,
        }
      );
      break;

    //合并
    case "img":
      layer = L.layerGroup([
        L.tileLayer.baidu({
          name: "底图",
          layer: "img_d",
          bigfont: option.bigfont,
        }),
        L.tileLayer.baidu({
          name: "注记",
          layer: "img_z",
          bigfont: option.bigfont,
        }),
      ]);
      break;
  }
  return layer;
};

三、添加图层控制控件

Leaflet提供了图层控制的控件,方便在地图底图的切换和业务图层的显示与隐藏进行控制,下面以上述百度地图加载类函数为例,对图层控制的使用进行说明。

let vec = new L.tileLayer.baidu({ layer: "vec", name: "矢量图" });
let img_d = new L.tileLayer.baidu({ layer: "img_d", name: "影像图" });
let img_z = new L.tileLayer.baidu({ layer: "img_z", name: "影像注记" });
let img = new L.tileLayer.baidu({ layer: "img", name: "影像图(含注记)" });
let custom = new L.tileLayer.baidu({ layer: "custom", name: "自定义图" });
let time = new L.tileLayer.baidu({ layer: "time", name: "实时路况" });

const baseLayers = {
    矢量图: vec,
    影像图: img_d,
    影像注记: img_z,
    "影像图(含注记)": img,
    自定义图: custom,
    实时路况: time,
};

// 添加图层控制控件
L.control.layers(baseLayers).addTo(map);

四、加载百度地图的完整代码

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

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>LeafletJS加载百度地图 - 优吉斯(YouGIS)</title>
  <link href="../lib/leaflet/leaflet.css" rel="stylesheet" />
  <script src="../lib/jquery/jquery.min.js"></script>
  <script src="../lib/leaflet/leaflet.js"></script>
  <script src="../lib/proj4/proj4.min.js"></script>
  <script src="../lib/proj4/proj4leaflet.min.js"></script>
  <style>
    * {
      padding: 0;
      margin: 0;
    }

    #location {
      position: fixed;
      padding: 5px;
      left: 0;
      bottom: 0;
      background-color: #fff;
      z-index: 999;
      font-size: 12px;
      font-weight: bold;
      color: blue;
      border-top-right-radius: 5px;
      /* width: 255px; */
    }

    #mapdiv {
      width: 100vw;
      height: calc(100vh - 156px);
    }

    #promptInfo {
      z-index: 999;
      position: absolute;
      color: red;
      font-size: large;
      font-weight: bold;
      margin-left: 80px;
      margin-top: 20px;
    }
  </style>
</head>

<body>
  <!-- https://www.cnblogs.com/echohye/p/17040982.html -->
  <iframe src="../yougis.html" style="width: 100vw; height: 156px"></iframe>
  <div id="mapdiv">
    <div id="promptInfo"></div>
  </div>
  <div id="location"></div>
  <script>
    L.CRS.Baidu = new L.Proj.CRS(
      "EPSG:900913",
      "+proj=merc +a=6378206 +b=6356584.314245179 +lat_ts=0.0 +lon_0=0.0 +x_0=0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs",
      {
        resolutions: (function () {
          level = 19;
          re = 18;
          var res = [];
          res[0] = Math.pow(2, re);
          for (var i = 1; i < level; i++) {
            res[i] = Math.pow(2, re - i);
          }
          return res;
        })(),
        origin: [0, 0],
        bounds: L.bounds([20037508.342789244, 0], [0, 20037508.342789244]),
      }
    );
    L.tileLayer.baidu = function (option) {
      option = option || {};
      var layer;
      var subdomains = "0123456789";
      switch (option.layer) {
        //单图层
        case "vec":
        default:
          //"http://online{s}.map.bdimg.com/tile/?qt=tile&x={x}&y={y}&z={z}&styles=pl&b=0&limit=60&scaler=1&udt=20170525"
          // layer = L.tileLayer("http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=" + (option.bigfont ? "ph" : "pl") + "&scaler=1&p=1", {
          //     name: option.name, subdomains: subdomains, tms: true
          // });
          layer = L.tileLayer(
            "https://maponline0.bdimg.com/tile/?qt=vtile&x={x}&y={y}&z={z}&styles=pl&scaler=2&udt=20230105&from=jsapi2_0",
            {
              name: option.name,
              subdomains: subdomains,
              tms: true,
            }
          );
          break;
        case "img_d":
          layer = L.tileLayer(
            "http://shangetu{s}.map.bdimg.com/it/u=x={x};y={y};z={z};v=009;type=sate&fm=46",
            {
              name: option.name,
              subdomains: subdomains,
              tms: true,
            }
          );
          break;
        case "img_z":
          layer = L.tileLayer(
            "http://online{s}.map.bdimg.com/tile/?qt=tile&x={x}&y={y}&z={z}&styles=" +
            (option.bigfont ? "sh" : "sl") +
            "&v=020",
            {
              name: option.name,
              subdomains: subdomains,
              tms: true,
            }
          );
          break;

        case "custom": //Custom 各种自定义样式
          //可选值:dark,midnight,grayscale,hardedge,light,redalert,googlelite,grassgreen,pink,darkgreen,bluish
          option.customid = option.customid || "dark";
          layer = L.tileLayer(
            //   "http://api{s}.map.bdimg.com/customimage/tile?&x={x}&y={y}&z={z}&scale=1&customid=" + option.customid,
            "http://api{s}.map.bdimg.com/customimage/tile?&x={x}&y={y}&z={z}&ak=yipxfCwhMDozKT3GDCM7UGARmSKbAMXh&scale=1&customid=" +
            option.customid,
            {
              name: option.name,
              subdomains: "012",
              tms: true,
            }
          );
          break;

        case "time": //实时路况
          var time = new Date().getTime();
          layer = L.tileLayer(
            "http://its.map.baidu.com:8002/traffic/TrafficTileService?x={x}&y={y}&level={z}&time=" +
            time +
            "&label=web2D&v=017",
            {
              name: option.name,
              subdomains: subdomains,
              tms: true,
            }
          );
          break;

        //合并
        case "img":
          layer = L.layerGroup([
            L.tileLayer.baidu({
              name: "底图",
              layer: "img_d",
              bigfont: option.bigfont,
            }),
            L.tileLayer.baidu({
              name: "注记",
              layer: "img_z",
              bigfont: option.bigfont,
            }),
          ]);
          break;
      }
      return layer;
    };

    let vec = new L.tileLayer.baidu({ layer: "vec", name: "矢量图" });
    let img_d = new L.tileLayer.baidu({ layer: "img_d", name: "影像图" });
    let img_z = new L.tileLayer.baidu({ layer: "img_z", name: "影像注记" });
    let img = new L.tileLayer.baidu({ layer: "img", name: "影像图(含注记)" });
    let custom = new L.tileLayer.baidu({ layer: "custom", name: "自定义图" });
    let time = new L.tileLayer.baidu({ layer: "time", name: "实时路况" });

    $(document).ready(function () {
      var options = {
        center: [31.245414, 121.506379], // The initial center(baidu BD-09 format) of map
        zoom: 15, // initial zoom of map
        crs: L.CRS.Baidu,
        layers: [vec],
      };
      var map = L.map("mapdiv", options);
      L.marker([31.245414, 121.506379])
        .addTo(map)
        .bindTooltip("上海东方明珠")
        .openTooltip();

      const baseLayers = {
        矢量图: vec,
        影像图: img_d,
        影像注记: img_z,
        "影像图(含注记)": img,
        自定义图: custom,
        实时路况: time,
      };

      // 添加图层控制控件
      L.control.layers(baseLayers).addTo(map);

      // 设置初始显示内容
      let initInfo = "请通过右上角图层控制切换地图, 点击地图左下角展示坐标|https协议下访问受限<br/>";
      initInfo += "当前选择地图:" + vec.options.name + "<br/>";
      initInfo += "服务地址:" + vec._url;
      document.getElementById("promptInfo").innerHTML = initInfo;

      // 图层切换事件, 设置显示的提示信息
      map.on('baselayerchange', function (e) {
        let info = "请通过右上角图层控制切换地图, 点击地图左下角展示坐标|https协议下访问受限<br/>";
        info += "当前选择地图:" + e.name + "<br/>";
        if (e.layer._url) {
          info += "服务地址:" + e.layer._url;
        } else if (e.layer._layers) {
          for (k in e.layer._layers) {
            let v = e.layer._layers[k]
            info += "服务地址" + k + ":" + v._url + "<br/>";
          }
        }
        document.getElementById("promptInfo").innerHTML = info;
      });

      map.on("click", (e) => {
        let lnglat = "鼠标点击位置坐标:" + e.latlng.lng + " , " + e.latlng.lat;
        $("#location")[0].innerText = lnglat;
      });
      window.map = map;
    });
  </script>
</body>

</html>

1

评论区