点击图片指定位置添加pin图标出现偏移问题的技术求助
偏移问题成因
- 父容器无定位规则:你给pin标注设置了
absolute绝对定位,该定位默认相对于整个<body>元素生效,而包裹图片的#floorplan容器默认是static静态定位,没有成为绝对定位的参考父级。页面有其他内容时#floorplan的位置被挤压下移,标注的定位原点和你计算的图片坐标原点完全不匹配,自然出现偏移。 - 坐标计算逻辑错误:你将点击坐标换算为了基于图片原始尺寸(
naturalWidth/naturalHeight)的数值,却直接把该数值当做当前页面显示尺寸下的像素偏移使用,如果图片做了响应式缩放,坐标会完全错位。同时你的坐标计算冗余混用了pageX、scrollX、getBoundingClientRect等不同基准的属性,进一步增加了计算误差。 - 标注锚点未对齐:默认设置下是用标注的左上角对准点击位置,但地图图钉的有效锚点是底部尖点,没有做锚点偏移的话视觉上也会出现偏移。
修复方案
步骤1:修正容器样式
给图片父容器设置相对定位,让标注的绝对定位以容器左上角为参考原点,同时消除图片默认的排版间隙:
<style> #floorplan { position: relative; display: inline-block; } #floorplanImg { display: block; max-width: 100%; } #newOfficeLocation { position: absolute; z-index: 1000; /* 修正锚点:图钉尖点对准点击位置 */ transform: translate(-50%, -100%); pointer-events: none; } </style>
把这段样式放到<head>标签里即可。
步骤2:修正JS坐标计算逻辑
删除冗余的坐标转换代码,直接使用相对于图片的实时显示坐标赋值:
document.getElementById('floorplanImg').addEventListener('click', function (event) { // 移除旧标注 const previousModals = document.getElementById('newOfficeLocation'); if (previousModals) previousModals.remove(); // 计算准确的相对坐标 const bounds = this.getBoundingClientRect(); const x = event.clientX - bounds.left; const y = event.clientY - bounds.top; // 创建新标注 const newLocation = document.createElement('div'); const floorplan = document.getElementById('floorplan'); newLocation.innerHTML = ` <div id="newOfficeLocation"> <div id="dragContainer"> <div id="item"> <span style="font-size: 2em; color: Tomato;"> <i class="fas fa-map-marker-alt"></i> </span> </div> </div> </div>`; floorplan.appendChild(newLocation); // 赋值坐标 const newLoc = document.getElementById('newOfficeLocation'); newLoc.style.left = `${x}px`; newLoc.style.top = `${y}px`; // 如果需要持久化存储标注跨设备显示,存储以下两个比例值即可 // const ratioX = x / this.clientWidth; // const ratioY = y / this.clientHeight; // 下次加载时用当前图片的clientWidth * ratioX、clientHeight * ratioY 即可换算为对应位置 });
完整修正后代码参考
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <script src="fontawesome.min.js"></script> <style> #floorplan { position: relative; display: inline-block; } #floorplanImg { display: block; max-width: 100%; } #newOfficeLocation { position: absolute; z-index: 1000; transform: translate(-50%, -100%); pointer-events: none; } </style> </head> <body> <div> I'm another element on the page! <ul>Cool</ul> <ul>Noice</ul> </div> <div id="floorplan"> <img id="floorplanImg" src="floorplan-example.png" alt="Floorplan Example Image" /> </div> <script type="text/javascript"> document.getElementById('floorplanImg').addEventListener('click', function (event) { const previousModals = document.getElementById('newOfficeLocation'); if (previousModals) previousModals.remove(); const bounds = this.getBoundingClientRect(); const x = event.clientX - bounds.left; const y = event.clientY - bounds.top; const newLocation = document.createElement('div'); const floorplan = document.getElementById('floorplan'); newLocation.innerHTML = ` <div id="newOfficeLocation"> <div id="dragContainer"> <div id="item"> <span style="font-size: 2em; color: Tomato;"> <i class="fas fa-map-marker-alt"></i> </span> </div> </div> </div>`; floorplan.appendChild(newLocation); const newLoc = document.getElementById('newOfficeLocation'); newLoc.style.left = `${x}px`; newLoc.style.top = `${y}px`; }); </script> </body> </html>
内容的提问来源于stack exchange,提问作者MrPadingy
相关产品推荐
相关产品推荐

