前端纯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>
展示
注:该文章用于自己学习和记录,如有问题可指出,所用示例图片为网图,用于练习学习。