Skip to content

Instantly share code, notes, and snippets.

@jrbramble76
Forked from jedwood/belay-js-example.html
Last active August 29, 2015 13:58
Show Gist options
  • Save jrbramble76/9937253 to your computer and use it in GitHub Desktop.
Save jrbramble76/9937253 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>SVG Lines</title>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="belay.js"></script>
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<style>
body{
background: #eee;
}
.grid{
padding: 30px;
}
.fact,.source, .child, .parent{
background: #fff;
margin: 10px 0px;
border-radius: 4px;
min-height: 30px;
padding: 10;
}
ol{
margin: 0;
padding: 0;
}
li{
list-style:none;
padding: 0;
}
h1,h2,h3{
margin-top:0;
}
li p{margin-bottom:0;}
</style>
</head>
<body>
<div class="grid">
<div class="row">
<h1>On Belay!</h1>
</div>
<div class="row">
<div class="col-sm-5">
<ol id="wives">
<li class="parent" id="parent-1">
<h3>Kendall</h3>
</li>
<li class="parent" id="parent-2">
<h3>Dave</h3>
</li>
<li class="parent" id="parent-3">
<h3>Tana</h3>
</li>
</ol>
</div>
<div class="col-sm-2"></div>
<div class="col-sm-5">
<ol id="children">
<li class="child parent-1">John</li>
<li class="child parent-1">Jed</li>
<li class="child parent-1">Josh</li>
<li class="child parent-1">Kory</li>
<li class="child parent-1">Bonnie</li>
<li class="child parent-2">Rob</li>
<li class="child parent-3">Freestone</li>
</ol>
</div>
</div>
</div>
</body>
<script>
function drawConnectors(){
//Draws a line from the wife to her children, based on each child having a class that is the id of the parent.
$(".parent").each(function(){
var theID = this.id;
$("."+theID).each(function(i,e){
var rand = Math.random() * .7 + .3;
Belay.set('animationDuration', rand)
Belay.on($("#"+theID), e)
});
})
}
// redraw if window is resized
$(window).resize(function(){
Belay.off();
drawConnectors();
});
Belay.init({strokeWidth: 1});
Belay.set('strokeColor', '#999');
drawConnectors();
</script>
</html>
var Belay = (function () {
var settings = {
strokeColor: '#fff',
strokeWidth: 2,
opacity: 1,
fill: 'none',
animate: true,
animationDirection: 'right',
animationDuration: .35
};
var me = {};
me.init = function (initObj) {
if (initObj) {
$.each(initObj, function (index, value) {
//TODO validation on settings
settings[index] = value;
});
}
}
me.set = function (prop, val) {
//TODO validate
settings[prop] = val;
}
me.on = function (el1, el2) {
var svgheight,
p,
svgleft,
svgtop,
svgwidth;
var el1pos = $(el1).offset();
var el2pos = $(el2).offset();
var el1H = $(el1).outerHeight();
var el1W = $(el1).outerWidth();
var el2H = $(el2).outerHeight();
var el2W = $(el2).outerWidth();
svgleft = Math.round(el1pos.left + el1W);
svgwidth = Math.round(el2pos.left - svgleft);
////Determine which is higher/lower
//If lower/higher
if ((el2pos.top + (el2H / 2)) <= (el1pos.top + (el1H / 2))) {
svgheight = Math.round((el1pos.top) + el1H / 2) - (el2pos.top + el2H / 2);
svgtop = Math.round(el2pos.top + el2H / 2);
// Curve Up -- (Left,Bottom Right,Bottom Left,Top Right,Top) http://blogs.sitepointstatic.com/examples/tech/svg-curves/cubic-curve.html
p = "M0," + (svgheight + settings.strokeWidth) + " C" + (svgwidth / 2) + "," + (svgheight + settings.strokeWidth) + " " + (svgwidth / 2) + "," + settings.strokeWidth + " " + svgwidth + "," + settings.strokeWidth;
} else {
svgheight = Math.round((el2pos.top) + el2H / 2) - (el1pos.top + el1H / 2);
svgtop = Math.round(el1pos.top + el1H / 2);
// Curve Down -- (Left,Top Right,Top Left,Bottom, Right,Bottom)
p = "M0," + settings.strokeWidth + " C" + (svgwidth / 2) + "," + settings.strokeWidth + " " + (svgwidth / 2) + "," + (svgheight + settings.strokeWidth) + " " + svgwidth + "," + (svgheight + settings.strokeWidth);
}
//ugly one-liner
$ropebag = $('#ropebag').length ? $('#ropebag') : $('body').append($("<div id='ropebag' />")).find('#ropebag');
var svgnode = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
var newpath = document.createElementNS('http://www.w3.org/2000/svg', "path");
newpath.setAttributeNS(null, "d", p);
newpath.setAttributeNS(null, "stroke", settings.strokeColor);
newpath.setAttributeNS(null, "stroke-width", settings.strokeWidth);
newpath.setAttributeNS(null, "opacity", settings.opacity);
newpath.setAttributeNS(null, "fill", settings.fill);
svgnode.appendChild(newpath);
// Adding the stroke width * 2 to the height so path is not cropped and adjusting the top offset by the stroke width
$(svgnode).css({ height: svgheight + (settings.strokeWidth * 2), left: svgleft, position: 'absolute', top: svgtop - settings.strokeWidth, width: svgwidth });
$ropebag.append(svgnode);
if (settings.animate) {
// THANKS to http://jakearchibald.com/2013/animated-line-drawing-svg/
var pl = newpath.getTotalLength();
// Set up the starting positions
newpath.style.strokeDasharray = pl + ' ' + pl;
if (settings.animationDirection == 'right') {
newpath.style.strokeDashoffset = pl;
} else {
newpath.style.strokeDashoffset = -pl;
}
// Trigger a layout so styles are calculated & the browser
// picks up the starting position before animating
// WON'T WORK IN IE. If you want that, use requestAnimationFrame to update instead of CSS animation
newpath.getBoundingClientRect();
newpath.style.transition = newpath.style.WebkitTransition = 'stroke-dashoffset ' + settings.animationDuration + 's ease-in-out';
// Go!
newpath.style.strokeDashoffset = '0';
}
}
me.off = function () {
$("#ropebag").empty();
}
return me;
}());
@jrbramble76
Copy link
Author

When using the plugin I found that it didn't animate correctly in Firefox and the lines didn't end and begin flush/horizontally, and even were cropped by the svg container. This update expands the svg to account for the stroke width to not crop and also to make the path of the svg begin and end correctly/horizontally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment