当前位置: 首页 > news >正文

vue2通过leaflet实现图片点位回显功能

需求:在图片上标点了,需要根据标记点在图片上进行回显功能,并且不会根据窗口大小导致标记点移位

1.效果

2.下载插件

用到的是leaflet插件:一个交互式地图 JavaScript 库,我下载是  "leaflet": "^1.9.4"

npm install leaflet

引入到项目

icon是自带的图标

import icon from 'leaflet/dist/images/marker-icon.png';
import * as L from 'leaflet';
import 'leaflet/dist/leaflet.css';

3.主要代码详解

图片加载后需要创建map对象,注意!!如果后端传的点数据是根据图片原有大小比如图片尺寸800*800,x:20,y:20,就是在800像素上的xy的值那么直接设置leftmap的unproject为图片本身的尺寸即可

​var south_west = that.leftMap.unproject([0, img_original_height], 1); //西南var north_east = that.leftMap.unproject([img_original_width, 0], 1);​

如果图片原尺寸为800*800,后端传来尺寸为400*400,x:10,y:10,需要设置如下代码

      var style = window.getComputedStyle(document.getElementById("roc_map"));var map_height = parseFloat(style.height);     var south_west = that.leftMap.unproject([0, map_height], 1); //西南var north_east = that.leftMap.unproject([img_original_width / this_ratio, 0],1);

创建点:draggable:是否拖拽L.marker上面的这些代码全部都是坐标转换的,就是为了应对原有尺寸和后端尺寸不对应的问题

        // 1. 获取旧图片尺寸(pointArr中保存的width/height)const oldWidth = obj_.width; // 例如 1036const oldHeight = obj_.height; // 例如 582// 3. 根据地理边界 this_bounds 计算实际的地理坐标const boundsWidth = this_bounds.getEast() - this_bounds.getWest();const boundsHeight = this_bounds.getNorth() - this_bounds.getSouth();const lng = this_bounds.getWest() + (boundsWidth / oldWidth) * obj_.x;const lat = this_bounds.getNorth() - (+boundsHeight / oldHeight) * obj_.y; // Y轴取反const DefaultIcon = L.icon({iconUrl: icon,iconAnchor: [10, 41]});// 4. 创建标记点(Leaflet的Y轴需要取反)const marker = L.marker([lat, lng], {draggable: false,title: obj_.name,icon: DefaultIcon}).addTo(that.leftMap);

创建点弹窗,弹窗样式自行设计

   const popup = L.popup().setContent('加载中...');marker.bindPopup(popup);

4.完整代码

<!--* @Description:* @Author: 请叫我欧皇!* @Date: 2025-04-28 14:58:23* @FilePath: \vue-secondMenu-test-master\src\page\test4\zongti\02.leftjs.vue
-->
<template><div class="leaflet-box"><div id="roc_map" class="map"></div></div>
</template><script>
import icon from 'leaflet/dist/images/marker-icon.png';
import * as L from 'leaflet';
import 'leaflet/dist/leaflet.css';
export default {data() {return {pointArr: [{x: 80,y: 50,name: '测试111',group: ['测试111'],point_id: 1,sn: '123456789',width: 800,height: 572},{x: 200,y: 0,name: '测试222',group: ['测试222'],point_id: 2,sn: '123456789',width: 800,height: 572},{x: 200,y: 200,name: '测试333',group: ['测试222'],point_id: 3,sn: '123456789',width: 800,height: 572}],leftMap: null};},mounted() {this.initLeaflet();},methods: {initLeaflet() {let that = this;let pointArr = this.pointArr;var mark_map = {};var this_img = new Image();let imgs = 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg';// this_img.src = "../images/01.jpg";this_img.src = imgs;this_img.onload = function () {var img_original_width = this_img.width,img_original_height = this_img.height;// 在初始化地图前检查是否已存在地图实例if (that.leftMap) {that.leftMap.remove(); // 移除旧地图that.leftMap = null;}that.leftMap = new L.Map('roc_map', {minZoom: 1,maxZoom: 4,center: [0, 0],zoom: 1,crs: L.CRS.Simple,zoomControl: false,attributionControl: false// zoomControl: false, // 禁用默认的缩放控件});var south_west = that.leftMap.unproject([0, img_original_height], 1); //西南var north_east = that.leftMap.unproject([img_original_width, 0], 1);var this_bounds = new L.LatLngBounds(south_west, north_east);L.imageOverlay(imgs, this_bounds).addTo(that.leftMap);that.leftMap.fitBounds(this_bounds);init_p();//   init_grid_2();function init_p() {for (var i = 0; i < pointArr.length; i++) {let obj_ = pointArr[i];// 1. 获取旧图片尺寸(pointArr中保存的width/height)const oldWidth = obj_.width; // 例如 1036const oldHeight = obj_.height; // 例如 582// 3. 根据地理边界 this_bounds 计算实际的地理坐标const boundsWidth = this_bounds.getEast() - this_bounds.getWest();const boundsHeight = this_bounds.getNorth() - this_bounds.getSouth();const lng = this_bounds.getWest() + (boundsWidth / oldWidth) * obj_.x;const lat = this_bounds.getNorth() - (+boundsHeight / oldHeight) * obj_.y; // Y轴取反const DefaultIcon = L.icon({iconUrl: icon,iconAnchor: [10, 41]});// 4. 创建标记点(Leaflet的Y轴需要取反)const marker = L.marker([lat, lng], {draggable: false,title: obj_.name,icon: DefaultIcon}).addTo(that.leftMap);const popup = L.popup().setContent('加载中...');marker.bindPopup(popup);// 最新监测时间:2025-12-23 00:00:00 累计变化量X:1234.45mm 累计变化量Y:12345.567mm// .bindPopup(that.getBindPopup(obj_))marker.on('click', async function (e) {that.sendPointInfo = { ...obj_ };// Show loading messagemarker.bindPopup("<div style='width:260px;height:150px;font-size:12px' class='popup'>加载中...</div>").openPopup();try {const popupContent = `<div style='width:260px;height:150px;font-size:13px' class='popup'><div class="title">点编号:${obj_.name}</div><ul><li>sn:${obj_.sn}</li></ul></div>`;popup.setContent(popupContent);//                             }} catch (error) {popup.setContent('请求数据时出错');}});mark_map[obj_.point_id] = marker;}}};}}
};
</script><style lang="scss" scoped>
.leaflet-box {width: 100%;height: 800px;.map {width: 50%;height: 70%;margin: 40px;}
}
</style>

文章到此结束,希望对你有所帮助~

http://www.lqws.cn/news/459901.html

相关文章:

  • 电子制造智能化转型:MES如何解决工艺复杂、质量追溯与供应链协同
  • C++11 右值引用(Rvalue Reference)
  • HarmonyOS 6 + 盘古大模型5.5
  • Spring Boot自动装配原理解析
  • WebServer实现:muduo库的主丛Reactor架构
  • FPGA基础 -- Verilog 的属性(Attributes)
  • Spring Boot + MyBatis + Vue:从零到一构建全栈应用
  • FastJSON 或 Jackson 等库序列化 LocalDateTime 时,默认会将其转换为时间戳(毫秒数)
  • postgresql 函数调试
  • FastAPI lifespan示例
  • 《道德经》:探寻古老智慧中的哲学之光
  • 将无序json数据转换为excel表格形式
  • 一生一芯 PA2 RTFSC
  • 5.基于神经网络的时间序列预测
  • 数据库中间件ShardingSphere5
  • Vue学习笔记
  • Dify动手实战教程(进阶-知识库:新生入学指南)
  • 让大模型“更懂人话”:对齐训练(RLHF DPO)全流程实战解析
  • 《王者荣耀》系统架构深度技术解析
  • 进阶五 按键切换不同led流水效果
  • 李宏毅 《生成式人工智能导论》| 第6讲-第8讲:大语言模型修炼史
  • 关于ubuntu环境下vscode进行debug的随笔
  • 【工具教程】识别PDF中文字内容,根据文字内容对PDF批量重命名,提取识别PDF内容给图片重新命名的操作步骤和注意事项
  • 第十三章 模板
  • 机器学习流量识别(pytorch+NSL-KDD+多分类建模)
  • 自动化性能回退机制——蓝绿部署与灰度发布
  • 前端 CSS 框架:分类、选择与应用
  • 「AI高校」| 《清华大学:AI赋能教育高考志愿填报工具使用指南》
  • 新品上市 | 尺寸小且具有丰富接口的读卡器:RFID高频系列CK-FR06
  • MySQL之事务深度解析