美文网首页
在vite+ts中使用leftlet做工厂平面(室内)地图

在vite+ts中使用leftlet做工厂平面(室内)地图

作者: zZ_d205 | 来源:发表于2023-11-20 17:33 被阅读0次

    实现效果
    初始化:


    image.png

    点击标识点时自动放大:


    image.png

    参考文章
    Leaflet
    https://github.com/Leaflet/Leaflet
    https://leafletjs.com/index.html
    中文文档:https://leafletjs.cn/
    Leaflet Indoor
    https://github.com/cbaines/leaflet-indoor
    npm 安装 Leaflet

    npm install leaflet
    

    yarn 安装 Leaflet

    yarn add leaflet
    

    这将在你的项目中安装 Leaflet 库。安装完成后,你可以在你的 Vue 项目中按照以下方式引入 Leaflet:

    import L from 'leaflet';
    import 'leaflet/dist/leaflet.css';
    

    leaflet可能会报错,我是在app.vue中做的demo,所以需要在vite-env.d.ts中声明

    declare module 'leaflet';
    
    image.png
    <template>
      <div class="mapBox">
        <div id="map"></div>
        <div id="warehouse2"></div>
      </div>
    </template>
    
    <script setup lang="ts">
    import { onMounted } from "vue";
    import * as L from "leaflet";
    import "leaflet/dist/leaflet.css";
    import imageUrl from "./assets/warehouse1.png";
    import warehouse2 from "./assets/warehouse2.png";
    import marker from "./assets/jarMarker.png";
    // const leftBottomLat = 0; // 左下角经度
    // const leftBottomLng = 0; // 左下角纬度
    const getRealitySize = (size: number) => {
      // type: "Lat" | "Lng"
      // return type === "Lat"
      //   ? leftBottomLat + size / (40008000 / 360)
      //   : leftBottomLng + size / (40008000 / 360);// 40008000 是地球周长
      return size / (40008000 / 360);
    };
    const initMap1 = () => {
      // 创建地图实例并设置初始视图
      // Create the map
      //地图底图
      //  var osmUrl = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
      //         osm = new L.TileLayer(osmUrl, {
      //             maxZoom: 22,
      //             // attribution: "Map data &copy; OpenStreetMap contributors"
      //         });
      // 假设当前左下角坐标为 [leftBottomLat, leftBottomLng]
      const factoryWidth = 1144; // 宽度,单位:米
      const factoryHeight = 676; // 高度,单位:米
    
      // 计算右上角的经纬度
      const rightTopLng = getRealitySize(factoryWidth); //经度
      const rightTopLat = getRealitySize(factoryHeight); //纬度
    
      //[[最小底部纬度, 最左侧经度(左下角的点位)], [最大顶部纬度, 最右侧经度(右上角的点位)]];
      // 坐标的顺序应该是[纬度, 经度]
      var imageBounds = [
        [0, 0],
        [rightTopLat, rightTopLng],
      ];
      var map = new L.Map("map", {
        // layers: [osm],
        center: new L.LatLng(0, 0),
        zoom: 16,
        maxBounds: imageBounds,
        attributionControl: false,
        minZoom: 16, // 设置最小缩放级别
        maxZoom: 25, // 设置最大缩放级别
      });
      var imageOverlay = L.imageOverlay(imageUrl, imageBounds).addTo(map);
      imageOverlay.setOpacity(0.5); // 设置不透明度为 0.5
      // Add markers with custom icons
      // var marker1 = L.marker([0, 0]).addTo(map);
      // var popup1 = L.popup().setContent("Marker 1 Popup");
      // marker1.bindPopup(popup1);
      // var marker1 = L.marker([49.41873, 8.67689]).addTo(map);
      // var popup1 = L.popup().setContent("Marker 1 Popup");
      // marker1.bindPopup(popup1);
    
      // var marker2 = L.marker([0.0002, 0.0003]).addTo(map);
      // var popup2 = L.popup().setContent("Marker 2 Popup");
      // marker2.bindPopup(popup2);
    
      // L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
      //     maxZoom: 19,
      //     attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
      // }).addTo(map);
      // // 添加一个简单的标记
      // L.marker([51.5, -0.09]).addTo(map)
      //   .bindPopup('A pretty CSS3 popup. <br> Easily customizable.')
      //   .openPopup();
    
      // // 添加一个简单的圆
      // L.circle([51.508, -0.11], {
      //   color: 'red',
      //   fillColor: '#f03',
      //   fillOpacity: 0.5,
      //   radius: 500
      // }).addTo(map).bindPopup('I am a circle.');
    
      // 添加一个多边形
      const polygon = L.polygon(
        [
          [getRealitySize(45), getRealitySize(202)], // 左下角
          [getRealitySize(48), getRealitySize(528)], // 右下角
          [getRealitySize(156), getRealitySize(528)], // 右上角
          [getRealitySize(156), getRealitySize(202)], // 左上角
        ],
        {
          color: "white", // 边框颜色
          fillColor: "white", // 填充颜色
          fillOpacity: 1, // 完全不透明
        }
      )
        .addTo(map)
        .bindTooltip(
          "<div style='font-weight:bold'>Dirty Staging</br>Clean Room</div>",
          {
            permanent: true,
            direction: "center",
          }
        ) // 添加 Tooltip
        .on("click", function () {
          const bounds = polygon.getBounds();
          map.fitBounds(bounds);
        });
      // 你可以使用 polygon.getBounds() 获取多边形的边界框
      const polygonBounds = polygon.getBounds();
    
      const numberOfMarkers = 50;
      const customIcon = L.icon({
        iconUrl: marker, // 图标的 URL
        iconSize: [32, 32], // 图标的尺寸
        iconAnchor: [16, 16], // 图标的锚点,即图标的中心点
      });
      for (let i = 0; i < numberOfMarkers; i++) {
        // 随机生成一个在多边形内的点
        const randomPoint = getRandomPointInsidePolygon(polygonBounds);
    
        // 添加标记
        L.marker([randomPoint.lat, randomPoint.lng], { icon: customIcon })
          .addTo(map)
          .bindPopup(
            `<div><h3>Marker ${
              i + 1
            }</h3><p>Your custom HTML content goes here</p></div>`
          )
          .on("click", function () {
            const bounds = polygon.getBounds();
            map.fitBounds(bounds);
          });
      }
    
      // 随机生成一个在多边形内的点
      function getRandomPointInsidePolygon(bounds: {
        getSouthWest: () => any;
        getNorthEast: () => any;
      }) {
        const southWest = bounds.getSouthWest();
        const northEast = bounds.getNorthEast();
    
        const lat = Math.random() * (northEast.lat - southWest.lat) + southWest.lat;
        const lng = Math.random() * (northEast.lng - southWest.lng) + southWest.lng;
    
        return { lat, lng };
      }
      // // 例如,在多边形内的点的坐标
      // const pointInsidePolygon = [getRealitySize(90), getRealitySize(200)];
    
      // // 检查点是否在多边形内
      // if (
      //   polygonBounds.contains(
      //     L.latLng(pointInsidePolygon[0], pointInsidePolygon[1])
      //   )
      // ) {
      //   // 在多边形内,添加标记
      //   const marker = L.marker([pointInsidePolygon[0], pointInsidePolygon[1]])
      //     .addTo(map)
      //     .bindPopup("Marker inside the polygon");
      // }
    
      // const demoText = L.divIcon({
      //   className: "demo-text",
      //   html: `<div style=''>PM</br>WH</div>`,
      // });
    
      // const textMarker = L.marker(polygon.getBounds().getCenter(), {
      //   icon: demoText,
      // }).addTo(map);
    };
    onMounted(() => {
      initMap1();
    });
    </script>
    <style>
    /* 去掉 Leaflet Tooltip 的默认样式 */
    .leaflet-tooltip {
      box-shadow: none !important;
      border: none !important;
      background-color: transparent !important;
    }
    
    /* 设置 Tooltip 文字的样式 */
    .leaflet-tooltip-content {
      color: black; /* 文字颜色 */
      font-size: 14px; /* 文字大小 */
    }
    </style>
    <style scoped>
    body {
      padding: 0;
      margin: 0;
    }
    
    html,
    body {
      height: 100%;
      width: 100%;
    }
    .mapBox {
      display: flex;
      align-items: center;
      height: 100vh;
    }
    #map {
      height: 100%;
      width: 50%;
    }
    .info {
      width: 150px;
      padding: 6px 8px;
      font: 14px/16px Arial, Helvetica, sans-serif;
      background: white;
      background: rgba(255, 255, 255, 1);
      box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
      border-radius: 5px;
    }
    #warehouse2 {
      width: 50%;
      height: 100%;
    }
    </style>
    

    相关文章

      网友评论

          本文标题:在vite+ts中使用leftlet做工厂平面(室内)地图

          本文链接:https://www.haomeiwen.com/subject/ytvvwdtx.html