使用循环与数组实现Div间类网络连线时出现position is not a function错误的排查与解决
问题分析与修复方案
首先,你遇到的position is not a function错误根源非常明确:你在原生DOM元素上调用了jQuery专属的position()方法。
你通过document.getElementsByClassName('org')获取的orgs是原生HTMLCollection集合,里面的每一项都是普通DOM节点——而position()是jQuery对象特有的方法,原生DOM元素根本没有这个方法,自然会抛出错误。除此之外,你的代码还有几个潜在问题需要同步解决:
具体问题拆解
- 原生DOM与jQuery对象混淆
org1 = orgs[i]拿到的是原生DOM元素,不能直接用.position();同理,line = lines[count]也是原生SVG元素,直接调用.attr()也会报错(原生DOM元素没有这个方法)。
- 重复连线与数组越界风险
- 嵌套循环
for (i)+for (j)会让每两个元素之间连两次线(比如i=0,j=1和i=1,j=0),既浪费性能,还会快速耗尽lines数组的元素,导致line变成undefined后调用.attr()触发新的错误。
- 嵌套循环
- 固定lines数量不够灵活
- 提前写好所有
<line>标签的方式非常僵硬,如果orgs的数量变化,lines的数量也得手动调整,很容易出错。
- 提前写好所有
修复后的代码
我们可以用jQuery统一处理元素,优化循环逻辑,甚至动态创建SVG线条,彻底摆脱提前写死lines的限制:
$(function() { // 直接转为jQuery对象,方便调用各类方法 const $orgs = $('.org'); // 获取SVG容器(假设你的线条都放在这个容器里,比如页面有<svg class="line-container"></svg>) const $svgContainer = $('.line-container'); // 循环只处理i<j的情况,避免重复连线 for (let i = 0; i < $orgs.length; i++) { const $org1 = $orgs.eq(i); const pos1 = $org1.position(); for (let j = i + 1; j < $orgs.length; j++) { const $org2 = $orgs.eq(j); const pos2 = $org2.position(); // 动态创建line元素,无需提前写好所有标签 const $line = $('<line></line>') .attr('x1', pos1.left + $org1.width()/2) // 可选:让线条连接元素中心,视觉更自然 .attr('y1', pos1.top + $org1.height()/2) .attr('x2', pos2.left + $org2.width()/2) .attr('y2', pos2.top + $org2.height()/2) .attr('stroke', 'red') .attr('stroke-width', 2); $svgContainer.append($line); } } });
关键修复点说明
- 统一使用jQuery对象:用
$('.org')直接获取jQuery集合,调用.position()、.eq()等方法就不会再出现方法不存在的错误。 - 优化循环逻辑:让
j从i+1开始遍历,每对元素只连线一次,减少无效操作。 - 动态创建线条:根据
org的数量自动生成<line>元素,不用再手动维护固定数量的线条标签,灵活性拉满。 - 可选优化:连线到元素中心:代码中额外添加了
+$org1.width()/2和+$org1.height()/2,让线条从元素中心出发,视觉效果更协调,你可以根据需求随时去掉这部分。
其他实现Div连线的方法
除了SVG,还有两种常用方案可供选择:
- Canvas绘制:如果需要更复杂的动画或实时交互(比如元素移动时线条同步更新),可以用Canvas API绘制连线,监听元素位置变化后重绘即可。
- CSS伪元素模拟:对于固定位置的元素,可以用绝对定位的伪元素(比如
::after),通过transform: rotate()模拟连线,但这种方法不适用于动态位置的元素,灵活性较差。
内容的提问来源于stack exchange,提问作者Ahmed Gouda
相关产品推荐
相关产品推荐

