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

前端纯JS实现手绘地图 地图导引

创造来源

公司接到的项目,实现制作一张图片(地图导引),并点击图片上的建筑物后可以弹出该建筑的具体信息。

编码逻辑

先在图片上确定各个建筑物的具体位置,我是以长方形来确定的(确定四个点的位置),1.获取图片原始尺寸,2.获取图片容器的尺寸和位置,计算出点击位置在容器内的相对位置,3.计算点击位置在原始图片上的像素坐标(考虑图片可能被缩放或拉伸,需要按比例换算)

计算缩放比例

  •  const scaleX = 原始宽度 / 容器显示宽度;
  • const scaleY = 原始高度 / 容器显示高度;

原始图片上的坐标

  • const originalX = 容器内X坐标 * scaleX;
  • const originalY = 容器内Y坐标 * scaleY;

4.判断点击位置落在那个建筑物区域,并设置对应的弹窗。

HTML代码和样式

<template><div class="bigPages" ref="imageContainer" @click="clickImg"><img src="../assets/0.png" alt="手绘地图" ref="targetImage" class="img_bg" /><!-- 对应位置的弹窗 --><div class="popup_box" ref="popupRef" v-show="popupShow">这个一个建筑物</div></div>
</template><style lang="scss" scoped>.bigPages {padding: 0;margin: 0;width: 100%;height: 100%;position: relative;}.img_bg {position: absolute;top: 0;left: 0;height: 100%;width: 100%;}.popup_box {position: absolute;height: 10%;width: 10%;background-color: #fff;border-radius: 15px;font-size: 1rem;}.popup_box::before {content: '';position: absolute;bottom: -19px;right: 50%;transform: translate(50%, 0);height: 20px;width: 20px;background-color: #fff;-webkit-clip-path: polygon(100% 0, 0 0, 50% 100%);clip-path: polygon(100% 0, 0 0, 50% 100%);}

JS代码逻辑

<script setup>import {ref,onMounted} from "vue";const imageContainer = ref(null)const targetImage = ref(null)const popupRef = ref(null);const imgNaturalWidth = ref(0);const imgNaturalHeight = ref(0);// 原始图片上的坐标const originalX = ref(0)const originalY = ref(0)// 百分比坐标const percentX = ref(0)const percentY = ref(0)// 中点百分比坐标const middlePercentX = ref(0)const middlePercentY = ref(0)// 中点图片上的原始坐标const middleOriginalX = ref(0)const middleOriginalY = ref(0)const popupShow = ref(false)const imgInfoFrom = ref([{minX: 110,maxX: 340,minY: 840,maxY: 980,name: '这是龙王庙'}, {minX: 270,maxX: 410,minY: 480,maxY: 590,name: '这是财神庙'}, {minX: 280,maxX: 450,minY: 790,maxY: 840,name: '这是白进桥'}])onMounted(() => {// 等待图片加载完成targetImage.value.addEventListener('load', () => {// 获取图片原始尺寸(非显示尺寸)imgNaturalWidth.value = targetImage.value.naturalWidth;imgNaturalHeight.value = targetImage.value.naturalHeight;// console.log(`图片原始 宽度:${imgNaturalWidth.value} px,高度:${imgNaturalHeight.value} px`);});})// 点击图片const clickImg = (e) => {// 获取图片容器的尺寸和位置let containerRect = imageContainer.value.getBoundingClientRect();let containerWidth = containerRect.width;let containerHeight = containerRect.height;// console.log(`示口距离 宽度:${containerWidth} px,高度:${containerHeight} px`);// 计算点击位置在容器内的相对坐标(像素)let clickX = e.clientX - containerRect.left;let clickY = e.clientY - containerRect.top;// console.log(`点击的相对坐标 宽度:${clickX} px,高度:${clickY} px`);// 计算点击位置在原始图片上的像素坐标// (考虑图片可能被缩放或拉伸,需要按比例换算)// 计算缩放比例// const scaleX = 原始宽度 / 容器显示宽度;// const scaleY = 原始高度 / 容器显示高度;// // 原始图片上的坐标// const originalX = 容器内X坐标 * scaleX;// const originalY = 容器内Y坐标 * scaleY;let scaleX = imgNaturalWidth.value / containerWidth;let scaleY = imgNaturalHeight.value / containerHeight;originalX.value = Math.round(clickX * scaleX);originalY.value = Math.round(clickY * scaleY);// console.log(`原始图片上的坐标 宽度:${originalX.value} px,高度:${originalY.value} px`);// 计算百分比坐标// 最终百分比 = (原始坐标 / 原始尺寸) * 100%percentX.value = ((originalX.value / imgNaturalWidth.value) * 100).toFixed(2);percentY.value = ((originalY.value / imgNaturalHeight.value) * 100).toFixed(2);// console.log(`最终百分比 宽度:${percentX.value} %,高度:${percentY.value} %`);// 判断是否点击了那一个建筑for (let i = 0; i < imgInfoFrom.value.length; i++) {let imgVale = imgInfoFrom.value[i]let isBoal = (originalX.value >= imgVale.minX && originalX.value <= imgVale.maxX) && (originalY.value >= imgVale.minY && +originalY.value <= imgVale.maxY)if (isBoal) {popupRef.value.innerHTML = imgVale.name;popupShow.value = true;setPopup(i)break}}}// 设置弹出框的位置const setPopup = (i) => {// 获取中点值middleOriginalX.value = imgInfoFrom.value[i].minX + (imgInfoFrom.value[i].maxX - imgInfoFrom.value[i].minX) / 2;// 中点百分比坐标middlePercentX.value = ((middleOriginalX.value / imgNaturalWidth.value) * 100).toFixed(2);middlePercentY.value = ((imgInfoFrom.value[i].minY / imgNaturalHeight.value) * 100).toFixed(2);console.log(`中点百分比 宽度:${middlePercentX.value} %,高度:${middlePercentY.value} %`);popupRef.value.style.left = middlePercentX.value + '%'popupRef.value.style.top = middlePercentY.value + '%'// 获取元素本身宽高let popupHeight = popupRef.value.getBoundingClientRect().height;let popupWidth = popupRef.value.getBoundingClientRect().width;popupRef.value.style.transform = "translate(" + -50 + "%," + -100 + "%)"}
</script>

展示

注:该文章用于自己学习和记录,如有问题可指出,所用示例图片为网图,用于练习学习。

http://www.lryc.cn/news/624567.html

相关文章:

  • YAML 语法结构速查表(完整版)
  • 【tips】unsafe-eval线上页面突然空白
  • Lucene 8.5.0 的 `.pos` 文件**逻辑结构**
  • 永磁同步电机控制算法--转速环电流环超螺旋滑模控制器STASMC
  • 大数据毕业设计选题推荐:基于Hadoop+Spark的城镇居民食品消费分析系统源码
  • 【项目】分布式Json-RPC框架 - 项目介绍与前置知识准备
  • 将 iPhone 联系人转移到 Infinix 的完整指南
  • Zephyr下ESP32S3开发环境搭建(Linux篇)
  • 【Python语法基础学习笔记】常量变量运算符函数
  • 分布式系统的“不可能三角”:CAP定理深度解析
  • flask——4:请求与响应
  • 敏感数据加密平台设计实战:如何为你的系统打造安全“保险柜”
  • 实战演练:通过API获取商品详情并展示
  • pytest的前置与后置
  • 【笔记ing】考试脑科学 脑科学中的高效记忆法
  • c++26新功能—可观测检查点
  • 晨控CK-GW08S与欧姆龙PLC配置Ethernet/IP通讯连接手册
  • PHP现代化全栈开发:微前端架构与模块化实践
  • 深入解析RabbitMQ与AMQP-CPP:从原理到实战应用
  • Elasticsearch全文检索中文分词:IK分词器详解与Docker环境集成
  • 【VUE】Vue3 绘制 3D 蓝图利器 Grid Plan
  • 蛇形方阵构造
  • k8sday10服务发现(1/2)
  • 深度学习在订单簿分析与短期价格预测中的应用探索
  • elasticsearch-集成prometheus监控(k8s)
  • 电子电气架构 --- 软件会给汽车带来哪些变化?
  • Git+Jenkins 基本使用
  • cesium中实时获取鼠标精确坐标和高度
  • 开放最短路径优先协议
  • 在 CentOS 7 上使用 LAMP 架构部署 WordPress