"use strict"; // so that touchmove is not scrolling document.body.addEventListener('touchmove', function(event) { event.preventDefault(); }, false); var FizzyText = function() { this.jitter = 12; this.tailLength = 40; this.tailColor = '#ffffff'; }; var iteratePerSecond = 30; var period = 1000 / iteratePerSecond; var text = new FizzyText(); var gui = new dat.GUI(); var controller = {jitter: gui.add(text, 'jitter', 0, 80) .onChange(function(value) { text.jitter = value; }), tailLength: gui.add(text, 'tailLength', 0 , 100) .onChange(function(value) { text.tailLength = Math.floor(value); points.splice(0, (points.length - text.tailLength)); }), color: gui.addColor(text, 'tailColor') .onChange(function(value) { svg.select("path").attr("stroke", value); }) }; // standard parameters var margin = { top: 20, right: 0, bottom: 0, left: 0 }, width = 1400 - margin.left - margin.right, height = 1000 - margin.bottom - margin.top; // new parameters // #3 - here is points, but it's empty! var points = []; // define the function for the line with jitter // #6 but something happens to our coords in the line Function var lineFunction = d3.svg.line() // #7 - when we define our x position, we add something to it .x(function(d) { return d.x + text.jitter * (Math.random() - .5) - margin.left; }) // #8 same to y .y(function(d) { return d.y + text.jitter * (Math.random() - .5) - margin.top; }) // #9 and there is an interpolation .interpolate('basis'); // standard svg intro + mousemove // STANDARD SVG SETUP var svg = d3.select('body') .append('svg') .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top + margin.bottom) .on("mousemove", function() { // #5 - ahha! coord comes from the mouse position updateArray(d3.mouse(this)); }) .on("touchmove", function() { updateArray(d3.mouse(this)); }); // #1 - here is our path! svg.append('path') // #2 and here is where "d" gets defined based on the array "points" .attr("d", lineFunction(points)) .attr("stroke", text.tailColor) .attr("class", "mainPath"); var paths = svg.select("path"); // update line with new points function jitter() { // update points paths.attr("d", lineFunction(points)) // call repeatedly // #6 - how do we animate? Change the random variation on every browser frame refresh requestAnimationFrame(jitter); } jitter(); // update point array function updateArray(coord) { // #4 points gets populated in here, based on coord if(points.length < text.tailLength - 1){ points.push({ x: coord[0], y: coord[1] }); } else { // set up so as not to create a new object, but to reuse the old one points.push(points[0]); points[points.length - 1].x = coord[0]; points[points.length - 1].y = coord[1]; points.shift() } }; // in short: // we create an array of points based on user's mouse movement in the updateArray function // and we use the lineFunction to turn this set of points into a line or curve (depending on the interpolation), adding a random factor to each point