This challenge started with an idea to play with geometry in a looping, fast-paced animation. The idea was to have several nodes where waves of color would sweep out.
Some of my initial ideas were
- being able to control the size of the node radius
- being able to control the number of nodes.
- spreading the nodes around the center of the canvas (with math)
- adding color to the fill areas
- adding a trailing glow to the circles as they expanded outward
- having multiple sweeps occur at the same time…as in drip, drip, drip
My first iteration, I created the node structure with inputs for node radius and number of elements. Changing these numbers immediately change the layout. But it had no movement. But it is fun to play with and I’m very impressed with d3’s ability to quickly draw these shapes at scale. Adding up to 500 objects appears to have no performance hits.
Working example of Iteration 1
For movement, I relied on transform functions with d3.js. But still could not make it work. So, I built a new sketch to just work on the transform alone.
I referenced quite a few examples to figure this out but this bit of code, had something that finally worked for me. I reused code from my previous sketches, and worked in some ideas of structure, such as using a nodesArray to describe the node coordinates. I decided to ditch the node id in my second array but I think it would be useful to add it back in to better target that particular node. Comparing code, I think we must have worked from similar examples because, in structure, our codes are close. – https://gist.github.com/whityiu/fb9f138a4a91032fa9ec.
I tried to work in my nodesArray function from the previous sketch so that I could control the number of nodes and radius but so far that has been unsuccessful.
var nodesArray = function (numNodes, nodeRadius) {
var nodes = [],
width = (nodeRadius * rMultiplyer) + canvasSize,
height = (nodeRadius * rMultiplyer) + canvasSize,
angle,
x,
y,
i;
for (i=0; i<numNodes; i++) {
angle = (i / (numNodes/2)) * Math.PI; // Calculate the angle at which the element will be placed.
// For a semicircle, we would use (i / numNodes) * Math.PI.
x = (nodeRadius * Math.cos(angle)) + (width/2); // Calculate the x position of the element.
y = (nodeRadius * Math.sin(angle)) + (width/2); // Calculate the y position of the element.
// nodes.push({‘id’: i, ‘x’: x, ‘y’: y});
nodes.push({‘x’:x, “y”:y});
console.log(nodes);
}
return nodes;
}
This function was particularly useful in creating the pulsing idea I had in mind.
// Set pulse animation on interval
pulseAnimationIntervalId = setInterval(function() {
var times = 1,
distance = 600,
duration = 10000;
var outlines = svg.selectAll(“.pulse”);
// Function to handle one pulse animation
function repeat(iteration) {
if (iteration < times) {
outlines.transition()
.duration(duration)
.each(“start”, function() { d3.select(“.outline”).attr(“r”, radius).attr(“stroke”, pulseLineColor); })
.attrTween(“r”, function() { return d3.interpolate(radius, radius + distance); })
.styleTween(“stroke”, function() { return d3.interpolate(pulseLineColor, bgColor); })
.each(“end”, function() {repeat(iteration+1);});
}
}
In the end, I used this animation for the final product. Using just 6 nodes set in the array