This is an old post, the old blog has been deactivated, the post has been moved to nuggets and republished.

There’s a lot of deliberate avoidance of math in development, and you know how boring math is. At ordinary times, CSS3 is used to write animation as far as possible. Timer-function is optional. At most, you can adjust cubic- Bezier to find the one that looks comfortable. But how to make the animation more smooth, write more close to the nature of the animation, to be honest, I didn’t think much about before.

Every time a motion designer asks, “Can I do this or that?” OF course I say no. So for a long time, I envied programmers who could draw cool animations on canvas.

You know what? It’s not immovable.

Today I’m going to share something about trigonometry, something I would have loved if someone had taught me when I was in preschool.

Trigonometric functions

Trigonometry is a cliche (it’s called Old School in hip-hop circles) that follows us from junior high to college, with so many formulas and theorems that it takes a lot of time just to get through exams. So let’s do a quick review to make sure you remember the basics.

The Pythagorean theorem

The Pythagorean theorem says that for a right triangle, the sum of the squares of the two sides of a right triangle equals the square of the hypotenuse.

Common trigonometric functions

I think the textbook only keeps sines, cosines, and tan, and the rest can be obtained by transformation.

Sin theta is equal to a over h cosine theta is equal to b over h tan theta is equal to a over bCopy the code

Polar coordinates and the unit circle

In cartesian cartesian coordinates, any point (x, y) can be transformed into a polar representation (r, θ), where

R = math.sqrt (x^2 + y^2) θ = math.atan2 (y, x)Copy the code

A unit circle is defined as a circle with a radius of unit length. The abscissa of any point on the circle is the cosine of the corresponding Angle, and the ordinate of any point is the sine of the corresponding Angle.

Simple image transformation to sine curve as an example, simple transformation of the function, get different results.

Sine curve formula: y = A sine (Bx + C) + D

A controls the amplitude. The larger A value is, the larger the peaks and troughs are; the smaller A value is, the smaller the peaks and troughs are; The B value will affect the period, the larger the B value, the shorter the period, the smaller the B value, the longer the period. C value will affect the left and right movement of the image. If C value is positive, the image will move to the left; if C value is negative, the image will move to the right. D controls up and down movement.

This formula is very useful, and if the following code is confusing to you, be sure to check the comments.

After a quick review and making sure you remember the basics, what does front-end code look like when you combine something that was once so familiar?

Common application scenarios

The image application

The most intuitive use is to use trigonometric functions to draw Wave curves

for (let x = 0; x < width; x++) {
  const y = Math.sin(x * a) * amplitude
}
Copy the code

Then combined with trigonometric function offset so that the left and right become troughs, the middle become peaks, you can get graceful ripples.

for (let x = 0; x < width; x++) {
  const radians = x / width * Math.PI * 2
  const scale = (Math.sin(radians - Math.PI * 0.5) + 1) * 0.5
  const y = Math.sin(x * 0.02 + xSpeed) * amplitude * scale
}
Copy the code

The same is true of the previous popular article on nuggets, using two sinusoidal functions to draw curves, fill followed by Stagger animation, can get a very cool 🌊 effect.

If combined with mouse position + LERP animation, can achieve nuts home page of the same animation.

Most of the code for this article is available on my Codepen home page.

SlowInSlowOut

Sines and cosines have a natural tendency to slow in and out, and to go from -1 to 1 and back to -1 over a period, which is ideal for simulating some physical effects. Because in the real world, cars start slowly, speed up, slow down, slow down again until they go to zero, and sudden changes are very unpleasant. The pendulum ball on the left is a linear uniform swing, and the pendulum ball on the right is optimized by using trigonometric functions. Obviously the effects designer on the left will hit people.

Just use sine or cosine times the maximum Angle to get the SlowInSlowOut between the maximum Angle of the swing.

ctx.rotate(Math.cos(t / 180 * Math.PI) * Math.PI * 0.25)
Copy the code

The Angle control

During development, we often had to deal with angles, such as showing the red dot of Notification in the upper left corner of the avatar (45deg), using the mouse to control rotation, and so on.

Math.atan2(y, x) can be used to calculate the Angle radian value between (x, y) and the positive X-axis.

function getCurrentDegree () {
  const deltaX = mouse.x - window.innerWidth * 0.5
  const deltaY = mouse.y - window.innerHeight * 0.5
  return Math.atan2(deltaY, deltaX) * 180 / Math.PI
}
Copy the code

In addition, trigonometry related animation does not need to be written in JS, such as the following DEMO, using compass dependency, can also be flexible to control the animation in a specific Angle (do not write the coordinates of each point!! No way to maintain later)

  @import "compass";

  .checkbox:checked{~button {
      $per: 180 / 4;
      @for $i from 1 through 6{&:nth-of-type(#{$i}) {
          $angle: $per * ($i - 1) * 1deg + 180deg;
          $x: cos($angle) * $d;
          $y: sin($angle) * $d;

          transform: translate($x.$y) rotate(0deg); }}}}Copy the code

The source code

Case Study

These are the most frequently used scenarios, and a case study to review.

Two days ago, I saw a hot recommendation on the home page of Codepen. The author used CSS animation to realize a walking animation, which was quite novel. However, after a closer look, the animation of footsteps really felt awkward, so he wanted to use trigonometry to optimize it.

Draw the header:

  drawHead (t) {
    ctx.save()
    ctx.beginPath()
    ctx.translate(0.Math.sin(t) * 4)
    ctx.arc(80, -35.35.0.2 * Math.PI)
    ctx.fill()
    ctx.closePath()
    ctx.restore()
  }
Copy the code

I’ll give each method a period parameter t, from 0 to 2 PI, to keep all the periodic motions in sync.

The body and shadows are pretty much the same. Skip the step animation.

There are two feet, according to the principle should be lifted to the foot of the completion of the movement, the other parts have completed a complete cycle, so when drawing feet, t needs to be divided by 2. Then the first foot and the second foot differ by half the period of the foot itself, and you can simply replace t with t + math. PI to animate the second foot.

  drawFeet (t) {
	 t = t / 2
    ctx.translate(Math.cos(t) * -50.0)

    // The other foot
    ctx.translate(Math.cos(t + Math.PI) * -50.0)}Copy the code

Half of the period of the footstep animation itself is on the ground. You can judge the sin value by judging that the change in the Y-axis direction is not made if the sin value is less than 0.

    ctx.translate(Math.cos(t) * -50.Math.sin(t) > 0 ? Math.sin(t) * -35 : 0)
Copy the code

And that’s not all. I’m going to do rotate in the first half of the cycle just to make the foot more realistic.

    if (t < Math.PI) {
      ctx.rotate(Math.sin(t) * Math.PI / 180 * -5)}Copy the code

The end result looks like this:

The source code

conclusion

You don’t Need jQuery. You don’t Need jQuery. You can’t stop chasing new scripts, so while learning new frameworks and skills, it’s important to remember the basics.

Well, today’s share here, I hope a collection of so many effects, you can use trigonometric functions more handy next time.

Most of the above code can be seen on my Codepen home page.

A link to the

  • Trigonometric graph
  • Realization principle of water wave diagram