基本思路
1、要将dwg格式的CAD图片在项目中展示并且可放大缩小不失真。
2、要在图片上添加坐标点,需要一个像素坐标到经纬度坐标的转换,并且点位坐标要可点击弹框展示基本信息。
方案1(财大气粗的建议使用这个):
使用唯杰地图 vjmap.com/ 具体使用方法可查看官网应用案例及源码。
注意!注意!注意!:唯杰地图是收费的哦!
方案2(想白嫖看这个):
1、将dwg格式的CAD图片通过插件转换为svg格式的图片。
2、使用leaflet轻松实现以上需求。
上代码
A.Leaflet插件安装
上述地址是Leaflet的官方网站,如果想查看详细的资料,可以细品。
npm安装库
npm install leaflet --save
B. 在Vue项目中引入Leaflet
可以分为全局及局部两种方式引入,按需使用
import L from "leaflet";
import 'leaflet/dist/leaflet.css'
C. 创建地图容器
仅需要创建一个Div容器,确定唯一id。
<template>
<!-- 地图容器 -->
<div id="image-map"></div>
</template>
D. leaflet基本功能
<script setup>
import { ref, onMounted, reactive } from 'vue';
import L from "leaflet";
import 'leaflet/dist/leaflet.css';
import { blueIcon, goldIcon, redIcon, greenIcon, orangeIcon, yellowIcon, violetIcon, greyIcon, blackIcon } from '../icon/leaflet-color-markers'
const map = ref(null);
const markers = reactive([
{name:'标记点1',type:'1',content:'这是标记点1的信息',position:[-100,300]},
{name:'标记点2',type:'1',content:'这是标记点2的信息',position:[-150,300]},
{name:'标记点3',type:'2',content:'这是标记点3的信息',position:[-200,300]},
{name:'标记点4',type:'2',content:'这是标记点4的信息',position:[-250,300]},
{name:'标记点5',type:'3',content:'这是标记点5的信息',position:[-300,300]},
])
const markerEnable = ref([]);
function initmap() {
map.value = L.map('image-map', {
minZoom: 1,
maxZoom: 4,
center: [0, 0],
zoom: 1,
crs: L.CRS.Simple
});
const w = 4000
const h = 3000
const url = 'https://xxx.com/loto/default/3.svg';
const southWest = map.value.unproject([0, h], map.value.getMaxZoom() - 1);
const northEast = map.value.unproject([w, 0], map.value.getMaxZoom() - 1);
const bounds = new L.LatLngBounds(southWest, northEast);
L.imageOverlay(url, bounds).addTo(map.value);
map.value.setMaxBounds(bounds);
markerEnable.value = markers.map(element => {
if(element.type === '1'){
element.icon = redIcon
}else{
element.icon = greenIcon
}
return {
...element,
markerItem:L.marker(element.position,{icon: element.icon}).addTo(map.value)
}
});
markerEnable.value.forEach((item)=>{
item.markerItem.bindPopup(item.content)
item.markerItem.on('move', (e) => {
// 当标记移动时,更新位置
const newLocation = item.markerItem.getLatLng();
console.log(`Marker moved to: ${newLocation.lat}, ${newLocation.lng}`);
});
function updateMarkerPosition(newPosition) {
item.markerItem.setLatLng(newPosition);
map.value.panTo(newPosition); // 平移地图到新位置
}
// 使标记可以被拖动
item.markerItem.dragging.enable();
item.markerItem.on('drag', (e) => {
const newPosition = item.markerItem.getLatLng();
updateMarkerPosition(newPosition);
});
})
}
onMounted(()=>{
initmap()
})
</script>
工作原理
minZoom: 1,
maxZoom: 4,
center: [0, 0],
zoom: 1,
设置能够缩放的级别,1-4级。初始级别值是1。
crs: L.CRS.Simple
这表明leaflet使用1:1映射,在屏幕像素和经纬度坐标系统之间。换句话说,我们的图片是平的,不是全球的,我们在投影一张平面图片。
const w = 4000
const h = 3000
const url = 'https://xxx.com/loto/default/3.svg';
这一段定义了图片尺寸和它的路径,路径可以引用网络链接。
const southWest = map.value.unproject([0, h], map.value.getMaxZoom() - 1);
const northEast = map.value.unproject([w, 0], map.value.getMaxZoom() - 1);
const bounds = new L.LatLngBounds(southWest, northEast);
这一段相当于告诉我们,如何把图片通过地图的方式放出来,所以需要一个像素坐标到经纬度坐标(系统)的转换。 把西南,东北角的像素坐标逆映射为经纬度坐标网。
在像素中,leaflet默认左上角的为坐标原点(0,0) 。所以,左下角的点有一个h作为y坐标值和0的x坐标值,右上角的点有一个0作为y坐标值和w作为x坐标值。
通过这些,即可知该在地图的何处放置这张照片。
L.imageOverlay(url, bounds).addTo(map.value);
把图像作为一个overlay覆盖,同时规定了图片的total size 只是我们限定的像素大小,所以用户不能把图片拖拽出边界。
const markers = reactive([
{name:'标记点1',type:'1',content:'这是标记点1的信息',position:[-100,300]},
{name:'标记点2',type:'1',content:'这是标记点2的信息',position:[-150,300]},
{name:'标记点3',type:'2',content:'这是标记点3的信息',position:[-200,300]},
{name:'标记点4',type:'2',content:'这是标记点4的信息',position:[-250,300]},
{name:'标记点5',type:'3',content:'这是标记点5的信息',position:[-300,300]},
])
这一段是mock的点位信息,name是点名称,type是类型根据类型可显示不同颜色的标记点,content是弹框内容,position是可移动的标记点
markerEnable.value = markers.map(element => {
if(element.type === '1'){
element.icon = redIcon
}else{
element.icon = greenIcon
}
return {
...element,
markerItem:L.marker(element.position,{icon: element.icon}).addTo(map.value)
}
});
循环创建点位
markerEnable.value.forEach((item)=>{
item.markerItem.bindPopup(item.content)
item.markerItem.on('move', (e) => {
// 当标记移动时,更新位置
const newLocation = item.markerItem.getLatLng();
console.log(`Marker moved to: ${newLocation.lat}, ${newLocation.lng}`);
});
function updateMarkerPosition(newPosition) {
item.markerItem.setLatLng(newPosition);
map.value.panTo(newPosition); // 平移地图到新位置
}
// 使标记可以被拖动
item.markerItem.dragging.enable();
item.markerItem.on('drag', (e) => {
const newPosition = item.markerItem.getLatLng();
updateMarkerPosition(newPosition);
});
})
给点位添加弹窗并且设置点位可拖动更新点位坐标功能