# Interactive Water Ripple Tutorial

## Introduction

This tutorial explains how to create a water ripple effect which responds when the user taps the canvas. Use a series of radial gradients to simulate small waves of water.

The water effect draws concentric circles on the canvas, in response to user taps. The circles are composed of radial gradients with alpha transparency. Draw the largest circles first and then the smaller circles. Transparency maximizes the color from the smaller circles in the center.

The water example doesn't take into account `scroll` events. If users scroll the window up or down, tap locations are incorrect. Learn to respond to `scroll` events with the Drag a Sprite tutorial. If you're unfamiliar with radial gradients see the Introduction to Radial Gradients Tutorial.

## Coordinates in Response to Taps

When the user taps the canvas calculate the offset. `onclick` event parameters provide the X and Y coordinates of the browser window, not the canvas. Therefore use the canvas's bounding box to calculate offsets.

Offsets from the bounding box are saved:

```var bb = canvas.getBoundingClientRect();

nXOffset =  bb.left;

nYOffset = bb.top;
```

When the user taps the canvas, calculate the X and Y position within the canvas:

```nX = e.pageX - nXOffset;

nY = e.pageY - nYOffset;
```

Use the `nX` and `nY` coordinates when drawing each gradient circle. The variable `CIRCUM` equals the circumference of a full circle calculated with `Math.PI*2`.

```gradient = context.createRadialGradient(
nX,
nY,
0,
nX,
nY,
);

...

context.arc(
nX,
nY,
0,
CIRCUM
);

```

## Particles

When the Web page loads function `radWater(n)` executes for each gradient in an array of gradients. The array is named `arrayWater`. Variable `N_PARTICLE_LENGTH` is a number which determines the number of water ripples to create. The following listing creates an array filled with radial gradients representing water.

```for(var i = 0; i < N_PARTICLE_LENGTH; i++)
{
arrayWater.push(
i
)
);
}
```

Each particle contains the properties `rgbEnd,rgbMid` and `nRadius`. Property `rgbEnd` is a `String` with the ending `stop` color and opacity for the gradient. Property `rgbMid` is a `String` with the middle `stop` color and opacity for the gradient. Property `nRadius` is the radius of the circle. Property `nRadius` increases gradually as the animation runs. The function `radWater(n)` creates one radial gradient.

Function `radWater(n)` is listed below.

```function radWater(
n
)
{

var j = n % 2;

aCircleDimensions[n]
);

switch(j){

// The lighter color
case 0:

// The end stop:
this.rgbEnd = new String(
"rgba(64, 64, 255, 0.1)"
);

// The middle stop:
this.rgbMid = new String(
"rgba(64, 64, 255, 0.8)"
);
break;

case 1:

// The darker color
this.rgbEnd = new String(
"rgba(0, 0, 34, 0.1)"
);

this.rgbMid = new String(
"rgba(0, 0, 34, 0.8)"
);
break;
}

}
```

The function `drawConcentricCircles()` iterates over the `Array` of radial gradient ripples. `drawConcentricCircles()` creates a gradient from the `rgbEnd` and `rgbMid` stop color properties of each particle. `drawConcentricCircles()` draws an arc with the `nRadius` property of each particle, then increments `nRadius`, for the next loop of the animation. See the drawConcentricCircles() source code.

## Tips

The water ripple effect looks great on personal computers, however it runs rather slowly on older Androids. Decrease the number of gradients for faster playback.

Reducing the number of water ripples displays the most dramatic performance improvement. Unfortunately the water doesn't look as realistic with too few ripples. However with modifications to the colors, timing, and gradient diameters, the effect could look good with fewer gradients, as well.

## Stop Programmatically

Code stops the animation after a specified number of loops. It's important to have a stopping point on any loop with JavaScript. It's especially important to run short loops, with processor intensive animation and alpha values.

If code is going to stop the timer in a function, it's usually best to stop the timer first. Then perform any other clean up operations. Running the timer, can use up processing time.

## Photoshop

The Interactive Water Ripple Example was prepared with Photoshop to select colors for the circles of water. It's easier to pick colors by eye. It's also faster for JavaScript to use prepared colors. You can calculate colors dynamically with code, but the processing might slow down mobile devices.

## Summary

This tutorial explained how to create a water ripple effect which responds when the user taps the canvas. Use a series of radial gradients to simulate small waves of water.

The water effect draws concentric circles on the canvas in response to taps on the canvas. The circles are composed of radial gradients with alpha transparency. Draw the largest circles first and then the smaller circles. Transparency maximizes the color on smaller circles in the center. See the Interactive Water Ripple Source code for more details.

The water example doesn't take into account `scroll` events. If users scroll the window up or down, tap locations are incorrect. Learn to respond to `scroll` events with the Drag a Sprite tutorial. If you're unfamiliar with radial gradients see the Introduction to Radial Gradients Tutorial.

See more HTML5 examples below. Have fun and love learning!