在vite+ts中使用leftlet做工廠平面(室內(nèi))地圖

實(shí)現(xiàn)效果
初始化:


image.png

點(diǎn)擊標(biāo)識(shí)點(diǎn)時(shí)自動(dòng)放大:


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

這將在你的項(xiàng)目中安裝 Leaflet 庫(kù)蒙揣。安裝完成后悠夯,你可以在你的 Vue 項(xiàng)目中按照以下方式引入 Leaflet:

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

leaflet可能會(huì)報(bào)錯(cuò)扫步,我是在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; // 左下角經(jīng)度
// const leftBottomLng = 0; // 左下角緯度
const getRealitySize = (size: number) => {
  // type: "Lat" | "Lng"
  // return type === "Lat"
  //   ? leftBottomLat + size / (40008000 / 360)
  //   : leftBottomLng + size / (40008000 / 360);// 40008000 是地球周長(zhǎng)
  return size / (40008000 / 360);
};
const initMap1 = () => {
  // 創(chuàng)建地圖實(shí)例并設(shè)置初始視圖
  // 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"
  //         });
  // 假設(shè)當(dāng)前左下角坐標(biāo)為 [leftBottomLat, leftBottomLng]
  const factoryWidth = 1144; // 寬度移剪,單位:米
  const factoryHeight = 676; // 高度,單位:米

  // 計(jì)算右上角的經(jīng)緯度
  const rightTopLng = getRealitySize(factoryWidth); //經(jīng)度
  const rightTopLat = getRealitySize(factoryHeight); //緯度

  //[[最小底部緯度, 最左側(cè)經(jīng)度(左下角的點(diǎn)位)], [最大頂部緯度, 最右側(cè)經(jīng)度(右上角的點(diǎn)位)]];
  // 坐標(biāo)的順序應(yīng)該是[緯度, 經(jīng)度]
  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, // 設(shè)置最小縮放級(jí)別
    maxZoom: 25, // 設(shè)置最大縮放級(jí)別
  });
  var imageOverlay = L.imageOverlay(imageUrl, imageBounds).addTo(map);
  imageOverlay.setOpacity(0.5); // 設(shè)置不透明度為 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 
  // }).addTo(map);
  // // 添加一個(gè)簡(jiǎn)單的標(biāo)記
  // L.marker([51.5, -0.09]).addTo(map)
  //   .bindPopup('A pretty CSS3 popup. <br> Easily customizable.')
  //   .openPopup();

  // // 添加一個(gè)簡(jiǎn)單的圓
  // L.circle([51.508, -0.11], {
  //   color: 'red',
  //   fillColor: '#f03',
  //   fillOpacity: 0.5,
  //   radius: 500
  // }).addTo(map).bindPopup('I am a circle.');

  // 添加一個(gè)多邊形
  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, // 圖標(biāo)的 URL
    iconSize: [32, 32], // 圖標(biāo)的尺寸
    iconAnchor: [16, 16], // 圖標(biāo)的錨點(diǎn),即圖標(biāo)的中心點(diǎn)
  });
  for (let i = 0; i < numberOfMarkers; i++) {
    // 隨機(jī)生成一個(gè)在多邊形內(nèi)的點(diǎn)
    const randomPoint = getRandomPointInsidePolygon(polygonBounds);

    // 添加標(biāo)記
    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);
      });
  }

  // 隨機(jī)生成一個(gè)在多邊形內(nèi)的點(diǎn)
  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 };
  }
  // // 例如,在多邊形內(nèi)的點(diǎn)的坐標(biāo)
  // const pointInsidePolygon = [getRealitySize(90), getRealitySize(200)];

  // // 檢查點(diǎn)是否在多邊形內(nèi)
  // if (
  //   polygonBounds.contains(
  //     L.latLng(pointInsidePolygon[0], pointInsidePolygon[1])
  //   )
  // ) {
  //   // 在多邊形內(nèi)蚓庭,添加標(biāo)記
  //   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 的默認(rèn)樣式 */
.leaflet-tooltip {
  box-shadow: none !important;
  border: none !important;
  background-color: transparent !important;
}

/* 設(shè)置 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>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市仅仆,隨后出現(xiàn)的幾起案子器赞,更是在濱河造成了極大的恐慌,老刑警劉巖墓拜,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件港柜,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡咳榜,警方通過(guò)查閱死者的電腦和手機(jī)夏醉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)涌韩,“玉大人畔柔,你說(shuō)我怎么就攤上這事〕加#” “怎么了靶擦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵腮考,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我玄捕,道長(zhǎng)踩蔚,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任桩盲,我火速辦了婚禮寂纪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赌结。我一直安慰自己捞蛋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布柬姚。 她就那樣靜靜地躺著拟杉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪量承。 梳的紋絲不亂的頭發(fā)上搬设,一...
    開(kāi)封第一講書(shū)人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音撕捍,去河邊找鬼拿穴。 笑死,一個(gè)胖子當(dāng)著我的面吹牛忧风,可吹牛的內(nèi)容都是我干的默色。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼狮腿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼腿宰!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起缘厢,我...
    開(kāi)封第一講書(shū)人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吃度,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后贴硫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體椿每,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年英遭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拖刃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贪绘,死狀恐怖兑牡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情税灌,我是刑警寧澤均函,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布亿虽,位于F島的核電站,受9級(jí)特大地震影響苞也,放射性物質(zhì)發(fā)生泄漏洛勉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一如迟、第九天 我趴在偏房一處隱蔽的房頂上張望收毫。 院中可真熱鬧,春花似錦殷勘、人聲如沸此再。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)输拇。三九已至,卻和暖如春贤斜,著一層夾襖步出監(jiān)牢的瞬間策吠,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工瘩绒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猴抹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓锁荔,卻偏偏與公主長(zhǎng)得像洽糟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子堕战,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355