> For the complete documentation index, see [llms.txt](https://training.callysto.ca/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://training.callysto.ca/infovis/animation.md).

# Animations - D3.js

All of our demos should involve snazzy, eye-catching visuals. As an example, here is a D3 animation with colourful balls to chase with your mouse. If you see nothing, click on "Reload" in your browser.

(The animation does not show up in the Gitbook Editor, only in the published version.)

\
\
circle {\
&#x20; stroke: #000;\
&#x20; stroke-opacity: .5;\
}\
\
&#x20;   \
\
var w = 600,\
&#x20;   h = 400;\
\
var nodes = d3.range(50).map(function() { return {radius: Math.random() \* 10 + 3}; }),\
&#x20;   color = d3.scale.category10();\
\
var force = d3.layout.force()\
&#x20;   .gravity(0.1)\
&#x20;   .charge(function(d, i) { return i ? 0 : -2000; })\
&#x20;   .nodes(nodes)\
&#x20;   .size(\[w, h]);\
\
var root = nodes\[0];\
root.radius = 0;\
root.fixed = true;\
\
force.start();\
\
var svg = d3.select("#body").append("svg:svg")\
&#x20;   .attr("width", w)\
&#x20;   .attr("height", h);\
\
svg.selectAll("circle")\
&#x20;   .data(nodes.slice(1))\
&#x20; .enter().append("svg:circle")\
&#x20;   .attr("r", function(d) { return d.radius - 2; })\
&#x20;   .style("fill", function(d, i) { return color(i % 17); });\
\
force.on("tick", function(e) {\
&#x20; var q = d3.geom.quadtree(nodes),\
&#x20;     i = 0,\
&#x20;     n = nodes.length;\
\
&#x20; while (++i < n) {\
&#x20;   q.visit(collide(nodes\[i]));\
&#x20; }\
\
&#x20; svg.selectAll("circle")\
&#x20;     .attr("cx", function(d) { return d.x; })\
&#x20;     .attr("cy", function(d) { return d.y; });\
});\
\
svg.on("mousemove", function() {\
&#x20; var p1 = d3.svg.mouse(this);\
&#x20; root.px = p1\[0];\
&#x20; root.py = p1\[1];\
&#x20; force.resume();\
});\
\
function collide(node) {\
&#x20; var r = node.radius + 16,\
&#x20;     nx1 = node.x - r,\
&#x20;     nx2 = node.x + r,\
&#x20;     ny1 = node.y - r,\
&#x20;     ny2 = node.y + r;\
&#x20; return function(quad, x1, y1, x2, y2) {\
&#x20;   if (quad.point && (quad.point !== node)) {\
&#x20;     var x = node.x - quad.point.x,\
&#x20;         y = node.y - quad.point.y,\
&#x20;         l = Math.sqrt(x \* x + y \* y),\
&#x20;         r = node.radius + quad.point.radius;\
&#x20;     if (l < r) {\
&#x20;       l = (l - r) / l \* .5;\
&#x20;       node.x -= x \*= l;\
&#x20;       node.y -= y \*= l;\
&#x20;       quad.point.x += x;\
&#x20;       quad.point.y += y;\
&#x20;     }\
&#x20;   }\
&#x20;   return x1 > nx2\
&#x20;       || x2 < nx1\
&#x20;       || y1 > ny2\
&#x20;       || y2 < ny1;\
&#x20; };\
}\
\
&#x20;  &#x20;
