One canvas animation code file per week

In our last post on Canvas Animation of the Week — from 2D to 3D, we discussed how complex it is to achieve 3D effects on a 2D plane. But for some simple 3D effects, using webGL not only feels like overkill, but browser compatibility is also a big issue. Therefore, we considered to simulate the EFFECT of 3D in 2D canvas as a demotion scheme in our project. Maybe you are skeptical about imitating 3D effects in 2D canvas. Here I will give you a small demo to let you have an intuitive feeling about the 3D effects simulated by canvas.

Is not very lifelike, stereo effect is good! I remember some time ago taobao home page had a simple 3D effect (but I didn’t find it, but I had the impression), thought it used webGL. In fact, canvas can be simulated completely. Now let’s introduce the 3D environment construction.

Coordinate system

The previous part of the animation content is two-dimensional because all of our animations are based on a two-dimensional coordinate system. To achieve 3d animation, in addition to the X and y axes, we need another coordinate axis – the Z axis. However, canvas does not have this innate coordinate axis. So, we need to manually set this axis.

In the setting of the coordinate axis, we have two choices, as shown in the figure below:

The first one is called the left hand coordinate system (the index finger, middle finger and thumb of the left hand are perpendicular, with the thumb pointing outward), and the second one is called the right hand coordinate system (the index finger, middle finger and thumb of the right hand are perpendicular, with the thumb pointing outward). The difference between them is shown here, the z axis points in different directions. Taking the right hand coordinate as an example, reflecting the behavior of the object (if we only consider the size of the object), as the object moves in the positive direction of the Z axis, we see the object getting smaller and smaller. As shown in the first illustration, when the object is moving in a negative direction. We could see objects getting bigger and bigger, creating a sensation of flying towards us. In addition, we use the right-handed coordinate system by default in this article.

2. Perspective

2.1 concept

Call it depth of field, call it perspective. Perspective is one of the most important concepts in 3D scenes. If you have used three.js, you will have noticed that there is one parameter in camera, perspective. Another scenario you’re familiar with is perspective in CSS3. If you understand any of these, the concept of perspective is easy to understand.

The role of the perspective is to determine whether objects are near or far from us. Because in two dimensions, we only need two coordinates to determine the position of an object on the plane. But, in three dimensions, that doesn’t work, two objects might have the same x coordinate, the same y coordinate. But as long as the z coordinates are different, we can’t tell if they’re on top of each other.

So, how to embody perspective in 2 – dimensional plane? Imagine that the basketball gets bigger when it flies at you from a distance (if we only consider one element here — the size of the basketball), and smaller when you throw it! Ok, that’s the idea. In a 2-dimensional plane, we want something to feel like it’s coming towards us, so we magnify it, and the same effect of moving away is to make it smaller.

Except let it change its size. Another important point is that when an object is moving away until it disappears, in order to simulate the three-dimensional vanishing effect, we must move the x and y coordinates of the object towards the vanishing point. The vanishing point you can think of as the car going off into the distance, and eventually it will gradually become a black dot and disappear on the horizon, and that black dot is the vanishing point.

So in conclusion, we need to do two things in perspective:

2.2 the formula

From the concept above we learned that in order to create perspective, we need to do two things. The following figure shows a side view. The human eye represents the observation point, and the blue sphere represents the object on the screen. The distance between the human eye and the screen is FL, and there is a distance z value between the object and the screen (this value does not exist during imaging and reflects the change of the object size).

The relationship between the size of the object and fl and Z is as follows:

Scale = fl/(fl + z) = 1 / (1 + z/fl)Copy the code

The FL value is like the Perspective value we set in CSS3. Similarly, this is a value that we set ourselves, so it doesn’t matter if it’s 200,300,500. From the formula, we can conclude that the value of scale is generally in the range of (0,1.0), and this value will later be used in the scale of the object and the proportion of the vanishing point. Consider two extreme cases: when the Z-axis is infinitely large (i.e., the positive continuous motion toward the Z-axis), the value of scale tends to zero. As z gets closer to -fl, scale gets really big, kind of sticking it in our eyes.

Taking the ball we used earlier as an example, in the draw method we define

context.scale(this.scaleX, this.scaleY)Copy the code

When the scaling scale is determined, on the one hand we determine the change in the size of the sphere, on the other hand we multiply the coordinates of the object by this scale to get the new coordinates of the object.

If fl=200, then the z coordinate of the object is 0, and scale=1.0 is obtained from the formula, then the size of the object remains the same, and the position of the object remains the same. If z=200, then scale=0.5. The object is going to be half its original size, and we’re going to multiply its current coordinates times the scale to get the new position. If the original is (200,300), then the new coordinate is (100,150). The specific effect is shown below:

3. Code implementation

Let’s start with the renderings

Here, we let the position of the ball move with the mouse, and control the distance of the ball on the Z-axis through the up and down keys of the keyboard.


   Copy the code

The code is relatively simple. First, we set the object’s 3D coordinates xpos,ypos,zpos, which default to 0. Then set the focal length fl = 250, and finally set the vanishing point (vpX, vpY). The important thing to note here is that we set the vanishing point as the center of the canvas. If we don’t do this, the objects will converge towards the top left corner of the canvas (0,0), which is not what we want.

Next, in the animation loop we calculate the scale according to the formula, then apply it to the ball’s scale, and finally calculate the new position of the object. One important thing to note here is that we have added a judgment condition (zpos > -fl) to the outer layer so that when the object is too big and outside the canvas we don’t draw it anymore.

This section is the core of the entire 3D effect, and all subsequent effects are based on it. So make sure you understand!