Happy Pi Day 🎉 Smooth animations with Math.sin!
Tags: javascript, beginners, math
Published: 2020-03-14 17:33:15

Pi Day is celebrated on March 14th around the world 🎉 

Pi (often represented by Greek letter `π`) is the symbol used in mathematics to represent a specific constant value: the ratio of the circumference of a circle to its diameter, which is approximately `3.14159`.

In this article we'll play with `π` value and create a simple animation using JavaScript to make an octopus floating in the sea 🐙 (see the Pen <a href='https://codepen.io/astagi/pen/bGdvJzz'>Octopus 🐙👨🏻‍💻</a> on <a href='https://codepen.io'>CodePen</a>)

## The sine function

In JavaScript `π` value is accessible from the `Math` module using `Math.PI` constant. Before using trigonometric functions to animate things like `sine` (`Math.sin` in JavaScript), we need a method to convert degrees values from 0 to 360 to radians

```js
function degreeToRad(angle) {
  return angle * (Math.PI / 180);
}
```

```js
degreeToRad(180) === Math.PI
degreeToRad(360) === Math.PI * 2
degreeToRad(90) === Math.PI / 2
```

In a right angled triangle, the sine of an angle is the length of the side opposite the angle divided by the length of the hypotenuse.

```
sin (θ) = opposite / hypotenuse
```

<img src="https://1.bp.blogspot.com/-sudtLSniE9I/XTL00UgAP1I/AAAAAAAAH8E/eU7PZ07A8IcIwLFaudNwXKt3zK4jNFbUgCLcBGAs/s1600/tri.png" width="400px">

```js
Math.sin(Math.PI / 2) === 1
```

To see `Math.sin` in action let's try to create a simple script to graphically represent `sine` function. 

We need a canvas to draw the function

```html    
<canvas id="sinCanvas" height="360" style="border: 1px solid black;"></canvas>
```

In the JavaScript code set the canvas width fullscreen 

```js
var canvas = document.getElementById("sinCanvas");
canvas.width = window.innerWidth;
var ctx = canvas.getContext("2d");
```

And then calculate `Math.sin(x)` where `x` is a value from 0 to 360 degrees converted to radians using our beloved function `degreeToRad` (ignore value 180, it's just an offset for the canvas)

```js
var x = 0, y = 0;

for ( x = 0; x <= 360; x += 1 ) {
  ctx.moveTo(x, y * 180 + 180);
  y = Math.sin(degreeToRad(x));
  ctx.lineTo(x, y * 180  + 180);
  ctx.stroke();
}
```

<img src="https://github.com/astagi/octopus-animation/blob/master/assets/sin.png?raw=true&random=1" width="400px">

A sine wave (or sinusoid) is now easy to generate, multiplying 360 by a value representing cycles (4 in this case)

```js
for ( x = 0; x <= 360 * 4; x += 1 )
```

<img src="https://github.com/astagi/octopus-animation/blob/master/assets/sinwave.png?raw=true&random=1" width="400px">

You can also adjust the frequency multiplying `x` by a value 

```js
y = Math.sin(degreeToRad(x * 10));
```

<img src="https://github.com/astagi/octopus-animation/blob/master/assets/freq.png?raw=true&random=1" width="400px">

(I omit the code to add extra elements to canvas, for more check the [full code on Github](https://github.com/astagi/octopus-animation))

## Smooth animations with Math.sin

In this section we'll try to make an octopus taken from the [Lotrèk 404 page](https://www.lotrek.it/notexistentpage) floating in the sea!

As you can see from the previous section, sine waves are a good choice for creating cyclic smooth animations: we can use a full sine wave that goes from 0 to π × 2 and generate a movement that goes from -1 to 1 and back smoothly.

Setup the octopus 🐙 image and position

```html
<img id="myOctopus" src="./octopus_01.png">
```

```js
var marginTopBase = -350

var octopus = document.getElementById("myOctopus");
octopus.style.position = 'relative';
octopus.style.marginTop = marginTopBase;
octopus.style.marginLeft = -40;
```
Then set the desired `frequency` of the final animation and the `pixelOffset` (`Math.sin` results between -1 and 1 will be multiplied by this value)

```js
var frequency = 10;
var pixelOffset = 10;
```

The animation will live in an interval where variable `animationCycle` is incremented and the marginTop of our octopus is recalculated with `Math.sin` to make the animation smooth

```js
var animationCycle = 1;

window.setInterval( function() {
  octopus.style.marginTop = marginTopBase - Math.sin(
      degreeToRad(animationCycle * frequency)
  ) * pixelOffset + 'px';
  animationCycle += 1;
}, 100 );
```

See the Pen <a href='https://codepen.io/astagi/pen/bGdvJzz'>Octopus 🐙👨🏻‍💻</a> on <a href='https://codepen.io'>CodePen</a>

Check the [full code on Github](https://github.com/astagi/octopus-animation). More info about Pi [here](https://www.piday.org/learn-about-pi/)