# Edit in JSFiddle

```(function( \$ ) {

// Setup canvas
var animate,
refreshRate = 50, // How fast (smooth) it animates
click = false,
clickIncrement = 0.5,
clickDelta = 0,
hueDelta = 0,
\$win = \$( window ),
\$canvas = \$( 'canvas' ),
canvas = \$canvas[0],
ctx = canvas.getContext( '2d' ),
points = [],
interval = 10,
canvasWidth = \$canvas.width(),
canvasHeight = \$canvas.height(),
mouseX = 200,
mouseY = 200,
// Our workhorse draw function
drawPoint = function( x, y, radius, color ) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc( x, y, radius, 0, Math.PI * 2, false );
ctx.closePath();
ctx.fill();
},
render = function( points ) {
var hue;

// Each time this renders, we clear the previous content
ctx.clearRect( 0, 0, canvasWidth, canvasHeight );

// If the mousebutton is currently clicked, keep growing the clickDelta
// modifier (which makes the points bigger) by clickIncrement
if ( click ) {
// But only to a certain point
if ( clickDelta < 5 ) {
clickDelta += clickIncrement;
}
} else {
// And don't let it fall below zero
if ( clickDelta > 0 ) {
clickDelta -= clickIncrement;
}
}

// Strobe colors for maximum chillaxment
if ( click === false ) {
// If the mousebutton isn't clicked, strobe inward
hueDelta += 10;
} else {
// If it is, strobe outward
hueDelta -= 10;
}

// Reset the hue once it reaches the end of the color wheel
if ( hueDelta > 360 ) {
hueDelta = 0;
} else if ( hueDelta < 0 ) {
// Or the beginning
hueDelta = 360;
}

// Iterate through all the points in our array
for ( var i = 0, iLength = points.length; i < iLength; i += 1 ) {
var x = points[i][0],
y = points[i][1],
x2,
y2,
// The distance formula:
// http://www.mathwarehouse.com/algebra/distance_formula/index.php
distance = Math.sqrt( Math.pow( mouseX - x, 2 ) + Math.pow( mouseY - y, 2 ) ),
step = ( canvasWidth ) / 3;

radiusDelta = ( distance / step );

// Set the hue of points by their distance to the mouse
if ( mouseX && mouseY ) {
// Add randomization to the edge to make it more ragged / textured
distance += ( Math.random() * 50 ) - 25;
hue = ( distance > 360 ) ? distance % 360 : distance;
hue = ( hue + hueDelta ) % 360;
} else {
hue = 360;
}

// Set the size of the point

// Randomize the opacity of each point to create attractive variance
points[i][4] += ( Math.random() * 0.1 ) - 0.05;

// Ensure opacity is between 1 and 0
if ( points[i][4] > 1 ) {
points[i][4] = 1;
} else if ( points[i][4] < 0 ) {
points[i][4] = 0;
}

// We're done calculating -- draw the point!
drawPoint( x, y, radius, 'hsla(' + hue + ', 50%, 50%, ' + points[i][4] + ')' );
}
};

// Set up an array of points to iterate over with each rendering
for ( var i = interval; i < canvasHeight; i += interval ) {

for ( var j = interval; j < canvasWidth; j += interval ) {
var rand = ( Math.random() * 2 ) - 1,
randDelta = Math.floor( Math.random() * 2 ),
opacity = Math.random();

// This is an atavism - disregard
if ( randDelta !== 1 ) {
randDelta = -1;
}

points.push( [ j, i, rand, randDelta, opacity ] );
}
}

// Set the mouseX and mouseY variables on mouse move so that
// the visualization responds to mouse movement
\$win.bind( 'mousemove', function( event ) {
mouseX = event.pageX - \$canvas.offset().left;
mouseY = event.pageY - \$canvas.offset().top;
});

\$win.bind( 'mousedown', function( event ) {
click = true;
});

\$win.bind( 'mouseup', function( event ) {
click = false;
});

// Animation happens by re-rendering everything every refreshRate milliseconds
animate = setInterval( (function() { render( points ); }), refreshRate );

})( jQuery );```
```<!--
Canvas width and height need to be defined explicitly via attributes:

http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#attr-canvas-width

-->
<canvas width="300" height="300"></canvas>

<p>move your mouse | click and hold</p>```