如何自动在任意位置的两个div间绘制SVG箭头
优化SVG绘制Div间箭头方案
你的代码无法实现预期效果,核心问题有三个:
- SVG尺寸固定且过小,没法覆盖页面所有区域,箭头很容易超出SVG范围导致看不见
- SVG处于正常文档流,会挤压Div的布局,同时
getBoundingClientRect()获取的是元素相对于视口的坐标,和SVG的局部坐标不匹配 - JS执行时机可能过早,DOM还没完全加载就去获取元素,容易出现获取不到的情况
下面是修复后的完整实现,能自动适配Div的任意位置,无需手动定位箭头:
完整代码
HTML
<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="styles/styles.css"> </head> <body> <div id="div1"><p>First div</p></div> <div id="div2"><p>Second div</p></div> <!-- 全屏覆盖的SVG,用于绘制箭头 --> <svg id="arrow-svg" style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 1000;"> <defs> <marker id="arrow" markerWidth="13" markerHeight="13" refX="2" refY="6" orient="auto"> <path d="M2,2 L2,11 L10,6 L2,2" fill="black" /> </marker> </defs> <path id="arr1" style="stroke:black; stroke-width: 1.25px; fill: none; marker-end: url(#arrow);" /> </svg> <script src="script.js"></script> </body> </html>
CSS(styles/styles.css)
div{ display: inline-block; margin-right: 100px; border-color: green; border-width: 3px; border-style: solid; }
JS(script.js)
// 等待DOM加载完成后执行 document.addEventListener('DOMContentLoaded', function() { const div1 = document.getElementById('div1'); const div2 = document.getElementById('div2'); const arrowPath = document.getElementById('arr1'); // 计算并更新箭头位置的函数 function updateArrow() { const rect1 = div1.getBoundingClientRect(); const rect2 = div2.getBoundingClientRect(); // 起点:div1右侧中点 const startX = rect1.right; const startY = rect1.top + rect1.height / 2; // 终点:div2左侧中点 const endX = rect2.left; const endY = rect2.top + rect2.height / 2; // 设置SVG路径 arrowPath.setAttribute('d', `M${startX},${startY} L${endX},${endY}`); } // 初始加载时更新箭头 updateArrow(); // 窗口大小变化或滚动时,实时更新箭头位置 window.addEventListener('resize', updateArrow); window.addEventListener('scroll', updateArrow); });
关键优化点
- 全屏SVG:将SVG设置为
fixed定位,铺满整个视口,这样getBoundingClientRect()的视口坐标可以直接对应SVG的绘图坐标,避免位置偏移 - 无干扰布局:给SVG加上
pointer-events: none,确保它不会遮挡页面元素的交互,同时不占据文档流,不会影响Div的原有布局 - 动态更新:监听窗口
resize和scroll事件,实时更新箭头位置,适配页面变化 - 正确执行时机:通过
DOMContentLoaded确保JS在DOM完全加载后执行,避免获取不到元素的问题
这个方案不管两个Div是横向排列还是纵向排列,都能准确在它们之间画出箭头,完全符合你的预期效果。
内容的提问来源于stack exchange,提问作者shaelebrown
相关产品推荐
相关产品推荐

