Gist contains a javaScript file svgDraw.js for connecting any vertically aligned html elements with an SVG path in a pipe-like fashion.
Also, index.html, and style.css are provided for demonstration purposes.
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Vertically connect divs with SVG path</title> | |
<link rel="stylesheet" type="text/css" href="style.css"> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script> | |
</head> | |
<body> | |
<div id="svgContainer"></div> | |
<div id= "outer"> | |
<div id="purple"></div> | |
<div id="teal"></div> | |
<div id="purple2"></div> | |
<div id="teal2"></div> | |
</div> | |
<script src="svgDraw.js"></script> | |
</body> | |
</html> |
body { | |
margin: 0; | |
} | |
#svgContainer { | |
z-index: -1; | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
opacity: 1; | |
} | |
#svgContainer > svg { | |
width: 100%; | |
height: 100%; | |
} | |
#outer { | |
margin: 0; | |
} | |
#teal { | |
width: 8em; | |
height:8em; | |
background-color:teal; | |
margin-left: 30%; | |
margin-top: 0em; | |
} | |
#purple { | |
width: 8em; | |
height: 8em; | |
background-color:purple; | |
margin-top: 0em; | |
} | |
#teal2 { | |
width: 8em; | |
height:8em; | |
background-color:teal; | |
margin-left: 30%; | |
margin-top: -16em; | |
} | |
#purple2 { | |
width: 8em; | |
height: 8em; | |
background-color:purple; | |
margin-top: 10em; | |
} |
function signum(x) { | |
return (x < 0) ? -1 : 1; | |
} | |
function absolute(x) { | |
return (x < 0) ? -x : x; | |
} | |
function drawPath(svg, path, startX, startY, endX, endY) { | |
// how smooth corners | |
var deltaX = (endX - startX) * 0.07; | |
var delta = absolute(deltaX); | |
var arc1 = 0; | |
var arc2 = 1; | |
var swap = 1; | |
if (startY > endY) { | |
swap = -1; | |
arc1 = 1; | |
arc2 = 0; | |
delta = -1*delta; | |
} | |
if (startY === endY) { | |
delta = 0; | |
} | |
var space = 15; | |
// draw tha pipe-like path | |
path.attr("d", "M" + startX + " " + startY + | |
" H" + (endX - space - (swap*delta)) + | |
" A" + delta + " " + delta + " 0 0 " + arc2 + " " + (endX - space) + " " + (startY + delta) + | |
" V" + (endY - delta) + | |
" A" + delta + " " + delta + " 0 0 " + arc1 + " " + (endX - space + (swap*delta)) + " " + endY + | |
" H" + endX | |
); | |
} | |
function connectElements(svg, path, startElem, endElem) { | |
var svgContainer= $("#svgContainer"); | |
// get (top, right) 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 | |
var startX = startCoord.left + startElem.outerWidth() - svgLeft; | |
var startY = startCoord.top + 0.5*startElem.outerHeight() - svgTop; | |
// calculate path's end (x,y) coords | |
var endX = endCoord.left - svgLeft; | |
var endY = endCoord.top + 0.5*endElem.outerHeight() - svgTop; | |
// call function for drawing the path | |
drawPath(svg, path, startX, startY, endX, endY); | |
} | |
function $svgPath(id) { | |
return $(document.createElementNS('http://www.w3.org/2000/svg', 'path')) | |
.attr({ | |
'id': id, | |
'stroke-width': '4px', | |
'fill' : 'none', | |
'stroke' : '#000', | |
'd' : 'M0 0' | |
}) | |
.css('fill', 'none'); | |
} | |
function $svg(id) { | |
return $(document.createElementNS('http://www.w3.org/2000/svg', 'svg')).attr('id', id); | |
} | |
function connectAll() { | |
// connect all the paths | |
$('#svgContainer').append($svg('svg1')); | |
$("#svg1").append($svgPath("path1")); | |
$("#svg1").append($svgPath("path2")); | |
connectElements($("#svg1"), $("#path1"), $("#purple"), $("#teal")); | |
connectElements($("#svg1"), $("#path2"), $("#purple2"), $("#teal2")); | |
} | |
$(document).ready(function() { | |
// reset svg each time | |
connectAll(); | |
}); | |
$(window).resize(function () { | |
// reset svg each time | |
connectAll(); | |
}); |