I want to build on this question which explains how to draw an arrow between two divs using svg, but I want to not have to position the arrow manually between the divs. Regardless of where the divs are on the page I want to be able to get the right side point of div1, the left side point of div2, and draw an arrow between them.
For example, if the html file was
<!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>
and the style file was
div{
display: inline-block;
margin-right: 100px;
border-color: green;
border-width: 3px;
border-style: solid;
}
then I would expect something like this:
On the other hand, if the html file was
<!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>
and the style file was
div{
margin-right: 100px;
border-color: green;
border-width: 3px;
border-style: solid;
}
then I would expect to see this:
This is the code that I’ve worked out so far, based on the comments:
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>
But this does not draw the arrow where I want it, like I’ve shown in the pictures. Any help would be super appreciated!
2
Answers
The way to assign the
linepath
to theSVG
is as follows:There are several issues that need to be addressed at the same time to achieve what you want.
First of all, you need to be working in the same coordinate system, i.e. the origin (0,0) must be the same for the
div
s and thesvg
. To achieve this, it is necessary to set themargin
andpadding
on all elements to 0 (see theCSS
code).Next, you need to overlay the
svg
on top of thediv
s. This can be achieved withCSS
by using theposition:fixed
property. And then, you need to wrap yourdiv
s and thesvg
in a containerdiv
.I increased the size of the
svg
to cover more of the page.I added
margin-left: 50px;
to thediv
s so that you will be able to see the arrowhead when you experiment with theHTML
to test the second layout you present.Your JavaScript code seems to be working (however, it is worth avoiding
var
today, it is better to uselet
orconst
).One problem with this approach is that the line joins up the points that you want to join, but the arrowhead goes further. You would need to draw a shorter line if you wanted the arrowhead to stop on the exact point (or find another way to achieve this).