在两个div之间画箭头,不论它们的位置如何。

3
我想在这个问题的基础上进行扩展,该问题解释了如何使用SVG在两个div之间绘制箭头,但我不想手动定位箭头在div之间的位置。无论div在页面上的位置如何,我希望能够获取div1的右侧点,div2的左侧点,并在它们之间绘制箭头。
例如,如果HTML文件是这样的:
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="styles/styles.css">
</head>
<body>

    <div><p>First div</p></div>
    <div><p>Second div</p></div>

</body>
</html>

样式文件已经

div{
    display: inline-block;
    margin-right: 100px;
    border-color: green;
    border-width: 3px;
    border-style: solid;
}

如果是这样的话,我会期望得到类似这样的东西:

inline-block example

另一方面,如果HTML文件是这样的
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="styles/styles.css">
</head>
<body>

    <div><p>First div</p></div>
    <br><br><br>
    <div><p>Second div</p></div>

</body>
</html>

样式文件已经

div{
    margin-right: 100px;
    border-color: green;
    border-width: 3px;
    border-style: solid;
}

如果是这样的话,我会期望看到这个:

static example

这是我根据评论所做出的代码。

var leftobj = document.getElementById("div1");
var rightobj = document.getElementById("div2");
var leftcoords = leftobj.getBoundingClientRect();
var rightcoords = rightobj.getBoundingClientRect();
var startx = leftcoords.right;
var endx = rightcoords.left;
var starty = (leftcoords.top + leftcoords.bottom) / 2;
var endy = (rightcoords.top + rightcoords.bottom) / 2;
var linepath = `M${startx},${starty} L${endx},${endy}`;
var arr = document.getElementById("arr1");
arr.setAttribute('d', linepath)
<div id="div1"><p>First div</p></div>
<div id="div2"><p>Second div</p></div>
<svg width="300" height="100">
  <defs>
    <marker id="arrow" markerWidth="13" markerHeight="13" refx="2" refy="6" orient="auto">
      <path d="M2,2 L2,11 L10,6 L2,2" style="fill:black;" />
    </marker>
  </defs>
  <path d="M30,150 L100,50" id="arr1"
    style="stroke:black; stroke-width: 1.25px; fill: none;marker-end: url(#arrow);" />
</svg>

但是这并没有把箭头画在我想要的地方,就像我在图片中展示的那样。非常感谢任何帮助!

1
ReferenceError: rightcoords未定义 - undefined
1个回答

2
有几个问题需要同时解决才能实现你想要的效果。
首先,你需要在相同的坐标系中工作,即对于
,原点(0,0)必须相同。为了实现这一点,需要将所有元素的margin和padding设置为0(请参考CSS代码)。
接下来,你需要将覆盖在
的上方。可以通过使用CSS的position:fixed属性来实现。然后,你需要将
包裹在一个容器
中。
如果你还想滚动页面,那么你需要对使用position:absolute属性。此外,你需要获取页面滚动的量,可以通过在JavaScript代码中相应的位置添加window.scrollX和window.scrollY来实现。
我增加了svg的大小,以覆盖更多页面。
我在div中添加了margin-left: 50px;,这样当您尝试使用HTML测试第二个布局时,您将能够看到箭头。
您的JavaScript代码似乎运行正常(然而,现在最好避免使用var,而是使用letconst)。
这种方法的一个问题是,线连接了您想要连接的点,但箭头却超出了。如果您希望箭头停在确切的点上(或找到另一种方法实现此目的),您需要绘制一条较短的线。

var leftobj = document.getElementById("div1");
var rightobj = document.getElementById("div2");
var leftcoords = leftobj.getBoundingClientRect();
var rightcoords = rightobj.getBoundingClientRect();
var startx = leftcoords.right + window.scrollX;
var endx = rightcoords.left + window.scrollX;
var starty = (leftcoords.top + leftcoords.bottom) / 2 + window.scrollY;
var endy = (rightcoords.top + rightcoords.bottom) / 2 + window.scrollY;
var linepath = `M${startx},${starty} L${endx},${endy}`;
var arr = document.getElementById("arr1");
arr.setAttribute('d', linepath)
* {
  margin: 0;
  padding: 0;
}

#div1,
#div2 {
  display: inline-block;
  padding: 10px;
  margin-left: 20px;
  margin-right: 100px;
  border-color: green;
  border-width: 3px;
  border-style: solid;
}

svg {
  position: absolute;
  left: 0px;
  top: 0px;
}

.container {
  border-width: 0px;
}
<div id="container">
  <br>
  <br>
  <br>
  <br>
  <br>
  <div id="div1">
    <p>First div</p>
  </div>
  <br>
  <br>
  <div id="div2">
    <p>Second div</p>
  </div>
  <svg width="500" height="500">
  <defs>
    <marker id="arrow" markerWidth="13" markerHeight="13" refx="2" refy="6" orient="auto">
      <path d="M2,2 L2,11 L10,6 L2,2" style="fill:black;" />
    </marker>
  </defs>
  <path d="M30,150 L100,50" id="arr1"
    style="stroke:black; stroke-width: 1.25px; fill: none;marker-end: url(#arrow);" />
</svg>
  <br>
  <br>
  <br>
  <br>
  <br>
  <br>
  <br>
  <br>
</div>


非常好,谢谢!我在您的代码中遇到的最后一个问题是,我的页面很长(垂直方向),所以当我滚动页面时,箭头不会随页面一起上下移动。有没有办法让它在滚动时保持在div1和div2之间的位置不变? - undefined
我对代码进行了一些编辑,这应该可以实现双向滚动,但这可能取决于您页面的其余结构。 - undefined
太棒了,你完美地解决了问题。非常感谢! - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接