Skip to content

Instantly share code, notes, and snippets.

@rogerhutchings
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rogerhutchings/967945b1b5db5cbe623c to your computer and use it in GitHub Desktop.
Save rogerhutchings/967945b1b5db5cbe623c to your computer and use it in GitHub Desktop.
Whitelines #1
<!DOCTYPE html>
<head>
<meta charset='utf-8'>
<style>
body {
background: #1a1a1d;
}
</style>
</head>
<body>
<script src='http://d3js.org/d3.v3.min.js'></script>
<script>
(function () {
'use strict';
var margin = {
top: 10,
right: 10,
bottom: 10,
left: 10
};
var bar = {
color: '#fff',
height: 20,
margin: {
x: 20,
y: 5
},
minimumWidth: 40
};
var height = 500 - margin.top - margin.bottom;
var width = 500 - margin.left - margin.right;
var availableWidth = width - bar.margin.x;
var animation = {
// Speed in px / ms
speed: 0.1,
// Animation interval in ms
interval: 1000
};
// How many whole lines?
var numberOfLines = Math.floor(height / (bar.height + bar.margin.y));
// So work out how tall the actual content will be, divide by two,
// and save it to adjust the content transform so it's vertically
// aligned
margin.topG = margin.top + (height - (numberOfLines * (bar.height + bar.margin.y) - bar.margin.y)) / 2;
var svg = d3.select('body').append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.topG + ')');
// Generate random dataset
// We create a random value for each line. This is used to generate the
// left bar width, and then subtracted from the availableWidth to give the
// right bar width.
var randomBetween = function (min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
};
// We want our bars to BOTH be at least the minimum width, so we use that in
// setting both the upper and the lower bounds
var data = [];
for (var i = 0; i < numberOfLines; i++) {
data[i] = randomBetween(bar.minimumWidth, availableWidth - bar.minimumWidth);
}
// Create bar groups
var barGroups = svg.selectAll('.bar-group')
.data(data)
.enter()
.append('g')
.attr('class', 'bar-group')
.attr('transform', function(d, i) { return 'translate(0, ' + (i * (bar.height + bar.margin.y)) + ')'; });
// Create the left bars
barGroups.append('rect')
.attr('class', 'left-bar')
.attr('x', 0)
.attr('y', 0)
.attr('height', bar.height)
.attr('width', function (d) { return d; })
.attr('fill', bar.color);
// Create the right bars
barGroups.append('rect')
.attr('class', 'right-bar')
.attr('x', function (d) { return d + bar.margin.x; })
.attr('y', 0)
.attr('height', bar.height)
.attr('width', function (d) { return availableWidth - d; })
.attr('fill', bar.color);
var getAnimationTime = function (distance) {
// Speed = distance / time, so to get a constant speed for our
// animations, we need time = distance / speed.
return distance / animation.speed;
};
var moveBar = function () {
// Randomly select a bar group, and get its left and right bars
var target = barGroups[0][randomBetween(0, (numberOfLines - 1))];
var leftBar = d3.select(target.childNodes[0]);
var rightBar = d3.select(target.childNodes[1]);
// Generate a new width, and work out the distance from the
// starting point
var newValue = randomBetween(bar.minimumWidth, availableWidth - bar.minimumWidth);
var distance = Math.abs(leftBar.node().getBBox().width - newValue);
// Start the animations
leftBar.transition()
.duration(getAnimationTime(distance))
.ease('linear')
.attr('width', newValue);
rightBar.transition()
.duration(getAnimationTime(distance))
.ease('linear')
.attr('width', availableWidth - newValue)
.attr('x', newValue + bar.margin.x);
};
// Periodically trigger an animation
setInterval(moveBar, animation.interval);
}());
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment