Skip to content

Instantly share code, notes, and snippets.

@jrbramble76
Forked from jedwood/belay-js-example.html
Created April 2, 2014 16:16
Show Gist options
  • Save jrbramble76/9937374 to your computer and use it in GitHub Desktop.
Save jrbramble76/9937374 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 : .75
};
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 - 1);
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);
if (svgheight <=20){
//things get tricky if the lines are straight, had trouble with this, so wrote this thing that seems to fix it by leaving out the control points of the bezier curve.
p = "M0,"+(svgheight)+" "+(svgwidth)+",1";
}else{
p = "M0,"+(svgheight)+" C"+svgwidth/4+","+(svgheight-2)+" "+(svgwidth/4)+",0 "+(svgwidth)+",1";
}
}else{
svgheight = Math.round((el2pos.top)+el2H/2) - (el1pos.top+el1H/2);
svgtop = Math.round(el1pos.top + el1H/2);
if(svgheight <= 20){
//things get tricky if the lines are straight, had trouble with this, so wrote this thing that seems to fix it by leaving out the control points of the bezier curve.
p = "M1,1 "+(svgwidth)+","+(svgheight-1)
}else{
p = "M1,1 C"+svgwidth/4+",0 "+(0+svgwidth/4)+","+svgheight+" "+(svgwidth)+","+(svgheight-1)
}
}
//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);
//for some reason, adding a min-height to the svg div makes the lines appear more correctly.
$(svgnode).css({left: svgleft, top: svgtop, position: 'absolute',width: svgwidth, height: svgheight, minHeight: '20px' });
$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;
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment