<html>
<head>
<script src="//code.jquery.com/jquery.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<meta charset="utf-8">
<title>JQBezier</title>
<script>
(function($){
$.fn.extend({
bezier: function(options)
{
var defaults = {
strokeColor : '#999',
strokeWidth : 2,
opacity : 1,
fill : 'none',
animate : true,
animationDirection : 'right',
animationDuration : 0.75
};
// Color wheel stuff
var color_wheel = [];
var frequency = .3;
for (var i = 0; i < 32; ++i)
{
red = Math.sin(frequency*i + 0) * 127 + 128;
green = Math.sin(frequency*i + (2*Math.PI/3)) * 127 + 128;
blue = Math.sin(frequency*i + (4*Math.PI/3)) * 127 + 128;
color_wheel.push(RGB2Color(red,green,blue));
}
var color_index = 0;
function RGB2Color(r,g,b)
{
return '#' + byte2Hex(r) + byte2Hex(g) + byte2Hex(b);
}
function byte2Hex(n)
{
var nybHexString = "0123456789ABCDEF";
return String(nybHexString.substr((n >> 4) & 0x0F,1)) + nybHexString.substr(n & 0x0F,1);
}
// Color wheel stuff
//override default options with user set options
var settings = $.extend(defaults, options);
var me = {};
me.init = function(initObj){
if (initObj) {
$.each(initObj, function(index, value){
settings[index] = value;
});
}
};
me.set = function(prop, val) {
settings[prop] = val;
};
me.on = function(el1, el2) {
var $el1 = $(el1);
var $el2 = $(el2);
if ($el1.length && $el2.length) {
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);
var curvinessFactor, cpt;
////Determine which is higher/lower
if ((el2pos.top + (el2H / 2)) <= (el1pos.top + (el1H / 2)))
{
// console.log("low to high");
svgheight = Math.round((el1pos.top + el1H / 2) - (el2pos.top + el2H / 2));
svgtop = Math.round(el2pos.top + el2H / 2) - settings.strokeWidth;
cpt = Math.round(svgwidth * Math.min(svgheight / 300, 1));
p = "M0," + (svgheight + settings.strokeWidth) + " C" + cpt + "," + (svgheight + settings.strokeWidth) + " " + (svgwidth - cpt) + "," + settings.strokeWidth + " " + svgwidth + "," + settings.strokeWidth;
}
else
{
// console.log("high to low");
svgheight = Math.round((el2pos.top + el2H / 2) - (el1pos.top + el1H / 2));
svgtop = Math.round(el1pos.top + el1H / 2) - settings.strokeWidth;
cpt = Math.round(svgwidth * Math.min(svgheight / 300, 1));
p = "M0," + settings.strokeWidth + " C" + cpt + ",0 " + (svgwidth - cpt) + "," + (svgheight + settings.strokeWidth) + " " + svgwidth + "," + (svgheight + settings.strokeWidth);
}
$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");
var color_to_use = (settings.strokeColor != 'rainbow') ? settings.strokeColor : color_wheel[color_index];
color_index = color_index + 1;
if (color_index == 32)
{
color_index = 0;
}
newpath.setAttributeNS(null, "d", p);
newpath.setAttributeNS(null, "stroke", color_to_use);
newpath.setAttributeNS(null, "stroke-width", settings.strokeWidth);
newpath.setAttributeNS(null, "opacity", settings.opacity);
newpath.setAttributeNS(null, "fill", settings.fill);
svgnode.appendChild(newpath);
$(svgnode).css({
left : svgleft,
top : svgtop,
position : 'absolute',
width : svgwidth,
height : svgheight + settings.strokeWidth * 2,
minHeight : '20px'
});
$ropebag.append(svgnode);
if (settings.animate)
{
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;
}
// IE sucks, dont expect this to work.
newpath.getBoundingClientRect();
newpath.style.transition = newpath.style.WebkitTransition = 'stroke-dashoffset ' + settings.animationDuration + 's ease-in-out';
newpath.style.strokeDashoffset = '0';
}
}
};
me.off = function() {
$("#ropebag").empty();
};
// Redraw upon resizing the window
var selector = this.selector;
$(window).resize(function(){
me.off();
$(selector).each(function(){
var theID = this.id;
$("."+theID).each(function(i,e){
var rand = Math.random() * 0.7 + 0.3;
me.set('animationDuration', rand);
me.on($("#"+theID), e);
});
});
});
// Loop through each parent and draw the lines connecting children
return this.each(function(){
var theID = this.id;
$("."+theID).each(function(i,e){
var rand = Math.random() * 0.7 + 0.3;
me.set('animationDuration', rand);
me.on($("#"+theID), e);
});
});
}
});
})(jQuery);
</script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-3 pull-left">
<div id="s1" class="supply box">Supply 1</div>
<div id="s2" class="supply box">Supply 2</div>
<div id="s3" class="supply box">Supply 3</div>
</div>
<div class="col-sm-1 pull-left">
<div class="box box-blue s1 s2">Building 1</div>
<div class="box box-blue s2">Building 2</div>
<div class="box box-red s3 s1">Process 1</div>
</div>
</div>
</div>
<script>
$('.supply').bezier({strokeWidth: 1, strokeColor: 'rainbow'});
</script>
</body>
</html>
.box
{
margin: 10px;
background-color: yellow;
width: 100px;
padding: 10px;
text-align: center;
font-weight: bold;
border: 2px solid black;
}
.box-blue
{
background-color: #0000AA;
color: white;
}
.box-red
{
background-color: #AA0000;
color: white;
}
Output
300px
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |