leafletMap封装使用

发布于:2025-08-10 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、封装leafletMap

import "leaflet.markercluster";
class LeafletMap {
  constructor() {
    const a = this;
    a.config = {
      domId: "container",
      center: [33.25, 113.52],
      zoom: 8,
      zoomSnap: 8.5, //地图缩放级别,支持小数,但会影响地图缩放      
      zoomControl: false, //禁止缩放
      touchZoom: false, //禁止触摸
      scrollWheelZoom: false, //禁止鼠标滚轮
      dragging: false, //禁止拖拽
    };
  }
  init(config) {
    const a = this;
    a.config = { ...a.config, ...config,
      renderer: L.canvas() // 或者 L.svg()
    };
    a.map = L.map(a.config.domId, a.config);
    return a.map;
  }
  // 高德离线图层
  addGDLayers(url) {
    const a = this;
    if (!configItem.tmsLayer) {
      L.tileLayer(
         "http://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}" //在线高德地图
        // "http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8" //在线高德卫星图
      ).addTo(a.map);
    } else {
      L.tileLayer(
        configItem.tmsLayer , {
        /*minZoom: 1,
        maxZoom: 14,*/
      }
      ).addTo(a.map);
    }
  }
  // 百度离线图层
  addBDLayers(url) {
    const a = this;
    L.tileLayer(
      url || "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" //在线百度地图
    ).addTo(a.map);
  }
  //标准tms图层
  addTMSLayers(url, config = {}) {
    const a = this;
    const CRS_900913 = new L.Proj.CRS(
      "EPSG:3395",
      "+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs",
      {
        resolutions: [
          156543.032, 78271.516, 39135.758, 19567.879, 9783.9395, 4891.96975,
          2445.984875, 1222.9924375, 611.49621875, 305.748109375, 152.874054688,
          76.437027344, 38.218513672, 19.109256836, 9.554628418, 4.777314209,
          2.388657104, 1.194328552, 0.597164276, 0.298582138, 0.149291069,
          0.074645535,
        ] /*(function () {
          var level = 19;
          var res = [];
          res[0] = Math.pow(2, 18);
          for (var i = 1; i < level; i++) {
            res[i] = Math.pow(2, 18 - i);
          }
          console.log(res);
          return res;
        })()*/,
        // origin: [0, 0],
        // bounds: L.bounds([20037508.342789244, 0], [0, 20037508.342789244]),
        origin: [7340032.00000000372529, -0.00000003068298],
        bounds: L.bounds(
          [7340032.00000000372529, -0.00000003068298],
          [141.291239704979603, 7340032.089508121833205]
        ),
      }
    );
    config.crs = CRS_900913;
    console.log(url);
    L.tileLayer(url, config).addTo(a.map);
  }
  //绘制行政边界(geojson)
  addBounds(response, myStyle) {
    const a = this;
    !myStyle && (myStyle = { color: "#ff7800" });
    // Add to layer
    var layer = L.geoJSON(response, {
      style: myStyle,
    }).addTo(a.map);
    return layer;
  }
  // 矢量图层(折线)
  addPolylineLayers(latlngs, color, className = "") {
    const a = this;
    !latlngs &&
      (latlngs = [
        [45.51, -122.68],
        [37.77, -122.43],
        [34.04, -118.2],
      ]);
    var polyline = L.polyline(latlngs, {
      color: color || "red",
      className: className, //类名
      weight: 2, //线条宽度
    }).addTo(a.map);
    //将地图放大到折线
    a.map.fitBounds(polyline.getBounds());
  }
  // 矢量图层(圆)
  addCircleLayers(latins, className = "") {
    const a = this;
    latins = [33.25, 113.52];
    L.circle(latins, {
      radius: 200,
      fillColor: "red", //填充色
      fillOpacity: 0.5, //填充透明度 默认0.2
      color: "yellow", //描边色
      className: className, //类名
    }).addTo(a.map);
  }
  //矢量图层(小图标)
  addIconLayers(latlng, config = {}, data, className = "", callback) {
    const a = this;
    !latlng && (latlng = [33.5, 113.5]);
    var obj = {
      iconUrl: "../../assets/images/vertices.png",
      iconSize: [30, 30],
      // iconAnchor: [22, 94], //图标尖端坐标
      // popupAnchor: [-3, -76], //弹出窗口“打开”的点相对于图标锚点的坐标
      // shadowUrl: "my-icon-shadow.png", //阴影图像
      // shadowSize: [68, 95], //阴影图像的大小
      // shadowAnchor: [22, 94], //阴影“尖端”的坐标
      className: className,
      data: data,
    };

    obj = { ...obj, ...config };
    var myIcon = L.icon(obj);
    let marker = L.marker(latlng, { icon: myIcon }).on("click", function (e) {
      callback(e);
    }).addTo(a.map)
    return marker;
    // L.marker(latlng).addTo(a.map); //标记点
  }
  //矢量图层聚合
  addClusterLayer() {
    const a = this;
    const markerClusterLayer = L.markerClusterGroup({
      showCoverageOnHover: false, // 为true时,当鼠标悬停在点上时,它会显示它聚合的边界
      zoomToBoundsOnClick: true, //  为true时,当鼠标点击某个点时,会缩放到它的边界范围
      chunkedLoading: true,
      maxClusterRadius: 50, // 聚类从中心标记覆盖的最大半径(以像素为单位),默认值 80
      // disableClusteringAtZoom: 10 // 在缩放级别10及以下不进行聚合
    }).addTo(a.map);
    return markerClusterLayer;
  }
  //矢量图层(文本)同上,可以canvas绘制
  addTextLayer(latlng, text, className = "my-div-icon", callback) {
    const a = this;
    !latlng && (latlng = [33.5, 113.5]);
   // 创建自定义图标并添加文本
    var customIcon = L.divIcon({className, html: '<span>'+text+'</span>'});
    var marker = L.marker(latlng, {className,icon: customIcon})//.addTo(a.map);
    return marker;
  }
  //添加大量的文本 使用canvas
  addLayerUseCanvas (latlng, text) {
    L.canvas().addLayer(L.marker(latlng).bindPopup(text));
  }
  //图像图层
  ImageLayers(imageUrl, imageBounds, className = "") {
    const a = this;
    // var imageUrl = "http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg",
    //   imageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];
    var imageLayer = L.imageOverlay(imageUrl, imageBounds, {
      opacity: 1, //图像透明度
      interactive: true, //为true时
      zIndex: 0, //显示层级
      className: className, //类名
    }).addTo(a.map);
    return imageLayer;
  }
  //移除图层根据类名
  removeLayersByAttr(className) {
    var layers = this.getAllLayers(this.map);
    for (var l in layers) {
      if (layers[l].options.className == className) layers[l].remove();
    }
  }
  //移除图层
  removeLayers(layer) {
    layer.remove();
  }
  //获取全部图层
  getAllLayers(map) {
    var allLayers = map._layers;
    return allLayers;
  }
  //标记点绑定弹窗
  markWithPopup(marker, popupContent) {
    popupContent = "<p>Hello world!<br />This is a nice popup.</p>";
    marker.bindPopup(popupContent).openPopup();
  }
  //弹窗
  popupBox(latlng) {
    const a = this;
    latlng = [33.5, 113.5];
    var popup = L.popup()
      .setLatLng(latlng)
      .setContent("<p>Hello world!<br />This is a nice popup.</p>")
      .openOn(a.map);
    return popup;
  }
  //关闭弹窗
  closePopupBox(popup) {
    popup.closePopup();
  }
  //交互事件
  addMapEvent() {
    const a = this;
    a.map.on("click", function (e) {
      var latlng = e.latlng, //经纬度
        _taget = e.target, //target
        pos = e.layerPoint || e.containerPoint; //屏幕位置
      console.log(latlng, _taget, pos);
    });
  }
  //移除交互事件
  removeMapEvent() {
    const a = this;
    a.map.off("click", function (e) {
      console.log(e);
    });
  }
}
export { LeafletMap };

二、vue引用

<template>
  <div class="index">
    <div class="map" id="mapContainer"></div>
  </div>
</template>

<script>
import { LeafletMap } from "@/utils/leafletMap.js";
export default {
  data() {
    return {
      areaCode:10,
      LMap: null,
      divMap: null, //地图map
      pointMarker: null,
      markClusterLayer: null, //聚合
      allMarkers: [], //要聚合的点图层
    };
  },
  mounted() {
    this.initMap();
  },
  // 方法集合
  methods: {
    initMap() {
      let dom = document.getElementById("mapContainer");
      dom.innerHTML = "";
      this.LMap = new LeafletMap();
      let Areacode = this.areaCode,
        { center, zoom, minZoom, maxZoom } = configItem.mapConfig[Areacode];
      this.divMap = this.LMap.init({
        domId: "mapContainer",
        center: [center[1], center[0]],
        zoom: zoom,
        minZoom,
        maxZoom,
      });
      this.LMap.addGDLayers();
      this.markClusterLayer = this.LMap.addClusterLayer();
      this.mapClick();
      this.mapZoomEnd();
      this.areaBoundary();
    },
    //行政边界
    areaBoundary() {
      const env = process.env.NODE_ENV;
      var str = env === "development" ? "/" : "../";
      var jsonUrl = common.getStaticFile(
        str + "static/areaJson/" + this.areaCode + ".json"
      );
      axios.get(jsonUrl).then((xcJson) => {
        var myStyle = {
          color: "#000",
          fillColor: "transparent",
          weight: 2,
          fillOpacity: 1,
        };
        this.LMap.addBounds(xcJson.data, myStyle);
      });
    },
    //行政名称
    addAreaName() {
      const env = process.env.NODE_ENV;
      var str = env === "development" ? "/" : "../";
      var jsonUrl = common.getStaticFile(
        str + "static/areaPoint/" + this.areaCode + ".json"
      );
      axios
        .get(jsonUrl)
        .then((res) => {
          res.data.forEach((item) => {
            var marker = this.LMap.addTextLayer(
              item.latlng,
              item.label,
              "areaName"
            );
            this.divMap.addLayer(marker);
            this.areaNameLayers.push(marker);
          });
        })
        .catch((e) => console.log(e));
    },
    mapClick() {
      const env = process.env.NODE_ENV;
      var str = env === "development" ? "/" : "../";
      var jsonUrl = common.getStaticFile(
        str + "static/areaPolygon/" + this.areaCode + ".json"
      );
      axios.get(jsonUrl).then((jsonData) => {
        this.areaPolygon = jsonData.data;
        this.divMap.on("click", (event) => {
          this.removePoint();
          let { lat, lng } = event.latlng;
          var pt = turf.point([lng, lat]);
          var poly = turf.polygon(this.areaPolygon);

          var isTrue = turf.booleanPointInPolygon(pt, poly);
          if (isTrue) {
            //添加点图层
            this.pointMarker = this.LMap.addIconLayers([lat, lng], {
              iconUrl: common.getAssetsFile("pos.png"),
            });
            this.$refs.ForecastBox.DialogVisible = true;
            this.$refs.ForecastBox.loadData(lng, lat);
          }
        });
      });
    },
    mapZoomEnd() {
      // 监听地图缩放后重新聚合
      this.divMap.on("zoomend", (e) => {
        // var zoom = this.divMap.getZoom();
        if (this.allMarkers.length > 0 && this.markClusterLayer) {
          this.markClusterLayer.clearLayers(); // 清除所有标记后重新添加以触发重新聚合
          this.markClusterLayer.addLayers(this.allMarkers);
        }
      });
    },
    //等值面图|格点值
    changeShowWay(ybTime) {
      //清除图层
      if (this.dztLayer) {
        this.LMap.removeLayers(this.dztLayer);
        this.dztLayer = null;
      }
      if (this.sztLayer) {
        this.LMap.removeLayers(this.sztLayer);
        this.sztLayer = null;
      }
      if (this.areaNameLayers.length > 0) {
        this.areaNameLayers.forEach((layer) => {
          this.LMap.removeLayers(layer); //移除图层
        });
        this.areaNameLayers = [];
      }
      this.legendData = [];
      //移除聚合点
      this.markClusterLayer.clearLayers();
    },
    //加载格点数值
    loadGridData(resData, unit) {
      let {
        Data: gridData,
        MaxLat,
        MaxLon,
        MinLat,
        MinLon,
        Width,
        Height,
      } = resData;
      var dx = (MaxLon - MinLon) / Width,
        dy = (MaxLat - MinLat) / Height;
      var numArray = [];

      const env = process.env.NODE_ENV;
      var str = env === "development" ? "/" : "../";
      var jsonUrl = common.getStaticFile(
        str + "static/mapPoint/" + this.areaCode + ".json"
      );
      axios.get(jsonUrl).then((jsonData) => {
        var mapData = jsonData.data,
          layers = [];
        for (var i = 0; i < gridData.length; i++) {
          var row = gridData[i];
          for (var j = 0; j < row.length; j++) {
            var text = row[j],
              x = j,
              y = gridData.length - i - 1;
            if (text < 99999 && mapData[y][x] == 1) {
              var latlng = [MinLat + dy * i, MinLon + dx * j];
              var layer = this.LMap.addTextLayer(
                latlng,
                text + unit,
                "divText"
              );
              layers.push(layer);
              // numArray.push({ label: text, x, y });
            }
          }
        }
        this.allMarkers = layers;
        this.markClusterLayer.addLayers(layers);

        if (numArray.length > 0) {
          var canvas = document.createElement("canvas"),
            ctx = canvas.getContext("2d"),
            textW = 70,
            textH = 50,
            sumW = Width * textW,
            sumH = Height * textH;
          canvas.width = sumW;
          canvas.height = sumH;

          for (var o of numArray) {
            ctx.fillStyle = "#000"; // 设置文本颜色为白色
            ctx.font = "20px Arial"; // 设置字体大小和类型
            ctx.textAlign = "center"; // 设置文本对齐方式为居中
            ctx.textBaseline = "middle"; // 设置文本基线为中间
            var value = o.label,
              text = value < 99999 ? value + unit : "";
            text &&
              ctx.fillText(
                text,
                (o.x - 0.5) * textW + textW / 2,
                (o.y + 1.2) * textH + textH / 2
              ); // 在矩形中心绘制文本"Hello, Canvas!"
          }
          var imageUrl = canvas.toDataURL("image/png");
          var imageBounds = [
            [MinLat, MinLon],
            [MaxLat, MaxLon],
          ];
          this.dztLayer = this.LMap.ImageLayers(imageUrl, imageBounds, "szt");
        }
      });
    },
    //移除图标点
    removePoint() {
      if (this.pointMarker) {
        this.LMap.removeLayers(this.pointMarker);
        this.pointMarker = null;
      }
    },
  },
  watch: {},
};
</script>
<style rel="stylesheet/less" lang="less" scoped>
.map{width:100%;height:100%;}
</style>


网站公告

今日签到

点亮在社区的每一天
去签到