/*LIfe's Not Complete Without Art (Expand Your Editor > ASCII Is Not Responsive ;) b .$ 4r .$$ 4$r z$$$ $$$c d. $$ $$d$$c.eeeeePeee.. z"4-'P$ J$$$$$dP3"""*$*$$ee$$$$$ " $$F z$*.P*$ "- .=" '\ $$$$ .P 'F" *e" \/$$$ " 4 ^ ^ $$b 4$% ^$$$r F 4$$$ 4 $$$b . 4$b P .ec $$$$b $" 4$P"" $$$$$$c ^ 4$$$r 4" 4$eec 4$$$$P"*$e \ . $$$ 4 ^$$$F $$$$$E.TMR$$" ^\ F r d$$P" *$$$P .^ -. . % ^. J$P $$F. / "$\ .z. - $P" ^ .P .^ ""3$$$$$$e ". .d" ^ $F -" ^ $$$$$$$$L ^""==""""" / ^ - 3$ee= "$" / ." ^. ^****" z" ^ z" / -. .e$" = ^ ec..... ....ee$$*" .^ ". """**""" .=^ " === """ |Felix| */ //I've included as many comments as possible for the variables associated with Lorenz Mathamatics so you can edit and play. The rest of the script should be self - explanatory, if not, you can refer to the D3.js docs. //Lorenz Attractor Parameters var dt = 0.005, // (δτ) Represents time. Draw curve - higher the value, straighter the lines p = 28, // (ρ) point of origin w = 10, // (σ)width of main element - higher the number, narrower the width beta = 8 / 3, // (β) points of equilibrium - this applied value results in the infinity symbol. higher values will break the equilibrium, causing the ends to separate and spread. When ρ = 28, σ = 10, and β = 8/3, the Lorenz system has chaotic solutions; it is this set of chaotic solutions that make up the Lorenz Attractor (the infinity symbol). If ρ < 1 then there is only one equilibrium point, which is at the origin. This point corresponds to no convection. All orbits converge to the origin when ρ < 1. The 'fork' occurs at ρ = 1, or ρ > 1 Try it. //Below x, y, and z values are the components of a given three dimensional location in space x0 = .5, //change in x,y, or z with respect to time y0 = .5, //" " z0 = 10; //" " var width = 1200, height = 600; var canvas = d3.select("body").append("canvas") .attr("width", width) .attr("height", height); //Color Range var color = d3.scale.linear() .domain([0, 20, 30, 45]) .range(["yellow", "orange", "brown", "purple"]) .interpolate(d3.interpolateHcl); var context = canvas.node().getContext("2d"); // set how the new images are drawn onto the existing image. 'lighter' will display the new over the old context.globalCompositeOperation = "lighter"; context.translate(width / 2, height / 2); context.scale(12, 8); context.lineWidth = .25; //mouse reactions - included only for interactive fun d3.select("canvas").on("mousemove", function() { var m = d3.mouse(canvas.node()); x0 = (m[0] - width / 2) / 12; y0 = (m[1] - height / 2) / 8; z0 = 10; }); //consistent timing of animations when concurrent transitions are scheduled for fluidity d3.timer(function() { var x = x0 + (Math.random() - .5) * 4, y = y0 + (Math.random() - .5) * 4, z = z0 + (Math.random() - .5) * 4, n = Math.random() * 30 | 0, t1 = Math.random() * 500; d3.timer(function(t0) { for (var i = 0; i < n; ++i) { context.strokeStyle = color(z); context.beginPath(); context.moveTo(x, y); x += dt * w * (y - x); y += dt * (x * (p - z) - y); z += dt * (x * y - beta * z); context.lineTo(x, y); context.stroke(); } return t0 > t1; }); context.save(); context.setTransform(1, 0, 0, 1, 0, 0); //source-atop draws old image on top of the new image, eliminating the part of the old image that is outside of the new image range. context.globalCompositeOperation = "source-atop"; context.fillStyle = "rgba(0,0,0,.03)"; context.fillRect(0, 0, width, height); context.restore(); });