A simple D3-powered animation, inspired by an image found on Otaku Gangsta.
View on bl.ocks.org at http://bl.ocks.org/rogerhutchings/967945b1b5db5cbe623c
A simple D3-powered animation, inspired by an image found on Otaku Gangsta.
View on bl.ocks.org at http://bl.ocks.org/rogerhutchings/967945b1b5db5cbe623c
| <!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> |