Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save abhishekbhalani/b8728b84a2ca5e2c17c61a55489521cf to your computer and use it in GitHub Desktop.

Select an option

Save abhishekbhalani/b8728b84a2ca5e2c17c61a55489521cf to your computer and use it in GitHub Desktop.
Connect two elements / draw a path between two elements with SVG path (using jQuery)

connect html elements via SVG path

Gist contains a javaScript file svgDraw.js for connecting any two html elements with an SVG path in a pipe-like fashion. Also, index.html, and style.css are provided for demonstration purposes.

==

to-do: usage
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="style.css">
<title>Connect divs with SVG</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<div id="svgContainer" style="margin: 50px 50px;">
<svg id="svg1" width="0" height="0" >
<path
id="path1"
d="M0 0"
stroke="#000"
fill="none"
stroke-width="12px";/>
<path
id="path2"
d="M0 0"
stroke="#000"
fill="none"
stroke-width="12px";/>
<path
id="path3"
d="M0 0"
stroke-width="8px"
style="stroke:#000; fill:none;"/>
<path
id="path4"
d="M0 0"
stroke-width="12px"
style="stroke:#000; fill:none; stroke-width: 12px;" />
<path
id="path5"
d="M0 0"
stroke-width="10px"
style="stroke:#000; fill:none;"/>
<path
id="path6"
d="M0 0"
stroke-width="10px"
style="stroke:#000; fill:none;"/>
</svg>
</div>
<div id= "outer">
<div id="teal"></div>
<div id="red"></div>
<div id="green"></div>
<div id="purple"></div>
<div id="orange"></div>
<div id="aqua"></div>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="svgDraw.js"></script>
</body>
</html>
body{ background-color:gray; }
#svgContainer {
z-index: -10;
position:absolute;
background-color:silver;
opacity: 0.5;
}
div{ opacity: 0.6; }
#outer{
margin:0 auto;
width: 80%;
}
#teal{
width: 6em;
height: 6em;
background-color:teal;
margin-left: 10%;
}
#orange{
height: 4em;
width: 35%;
padding: 2em 8em;
margin-left: 8em;
margin-top: 6em;
background-color: orange;
}
#red{
width:6em;
height: 4em;
margin-left: 30%;
padding:4em 3em;
background-color:red;
}
#aqua{
width: 5em;
height: 5em;
margin-left:15%;
background-color:aqua;
}
#purple{
width: 15em;
height: 5em;
background-color:purple;
}
#green{
width: 5em;
height: 7em;
margin-top: 2em;
margin-left: 50%;
background-color: green;
}
//helper functions, it turned out chrome doesn't support Math.sgn()
function signum(x) {
return (x < 0) ? -1 : 1;
}
function absolute(x) {
return (x < 0) ? -x : x;
}
function drawPath(svg, path, startX, startY, endX, endY) {
// get the path's stroke width (if one wanted to be really precize, one could use half the stroke size)
var stroke = parseFloat(path.attr("stroke-width"));
// check if the svg is big enough to draw the path, if not, set heigh/width
if (svg.attr("height") < endY) svg.attr("height", endY);
if (svg.attr("width" ) < (startX + stroke) ) svg.attr("width", (startX + stroke));
if (svg.attr("width" ) < (endX + stroke) ) svg.attr("width", (endX + stroke));
var deltaX = (endX - startX) * 0.15;
var deltaY = (endY - startY) * 0.15;
// for further calculations which ever is the shortest distance
var delta = deltaY < absolute(deltaX) ? deltaY : absolute(deltaX);
// set sweep-flag (counter/clock-wise)
// if start element is closer to the left edge,
// draw the first arc counter-clockwise, and the second one clock-wise
var arc1 = 0; var arc2 = 1;
if (startX > endX) {
arc1 = 1;
arc2 = 0;
}
// draw tha pipe-like path
// 1. move a bit down, 2. arch, 3. move a bit to the right, 4.arch, 5. move down to the end
path.attr("d", "M" + startX + " " + startY +
" V" + (startY + delta) +
" A" + delta + " " + delta + " 0 0 " + arc1 + " " + (startX + delta*signum(deltaX)) + " " + (startY + 2*delta) +
" H" + (endX - delta*signum(deltaX)) +
" A" + delta + " " + delta + " 0 0 " + arc2 + " " + endX + " " + (startY + 3*delta) +
" V" + endY );
}
function connectElements(svg, path, startElem, endElem) {
var svgContainer= $("#svgContainer");
// if first element is lower than the second, swap!
if(startElem.offset().top > endElem.offset().top){
var temp = startElem;
startElem = endElem;
endElem = temp;
}
// get (top, left) corner coordinates of the svg container
var svgTop = svgContainer.offset().top;
var svgLeft = svgContainer.offset().left;
// get (top, left) coordinates for the two elements
var startCoord = startElem.offset();
var endCoord = endElem.offset();
// calculate path's start (x,y) coords
// we want the x coordinate to visually result in the element's mid point
var startX = startCoord.left + 0.5*startElem.outerWidth() - svgLeft; // x = left offset + 0.5*width - svg's left offset
var startY = startCoord.top + startElem.outerHeight() - svgTop; // y = top offset + height - svg's top offset
// calculate path's end (x,y) coords
var endX = endCoord.left + 0.5*endElem.outerWidth() - svgLeft;
var endY = endCoord.top - svgTop;
// call function for drawing the path
drawPath(svg, path, startX, startY, endX, endY);
}
function connectAll() {
// connect all the paths you want!
connectElements($("#svg1"), $("#path1"), $("#teal"), $("#orange"));
connectElements($("#svg1"), $("#path2"), $("#red"), $("#orange"));
connectElements($("#svg1"), $("#path3"), $("#teal"), $("#aqua") );
connectElements($("#svg1"), $("#path4"), $("#red"), $("#aqua") );
connectElements($("#svg1"), $("#path5"), $("#purple"), $("#teal") );
connectElements($("#svg1"), $("#path6"), $("#orange"), $("#green") );
}
$(document).ready(function() {
// reset svg each time
$("#svg1").attr("height", "0");
$("#svg1").attr("width", "0");
connectAll();
});
$(window).resize(function () {
// reset svg each time
$("#svg1").attr("height", "0");
$("#svg1").attr("width", "0");
connectAll();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment