This is the 9th day of my participation in the Novembermore Challenge.The final text challenge in 2021

preface

If you stare at the sun all the time, the sun will make you blind. — Lucretius

introduce

In this issue, we will talk about the perspective method, a core principle of a Canvas to make fake 3D, that is, it mainly uses the perspective phenomenon of near big and far small to show the three-dimensional sense of objects. We will do a simple case to analyze how to use the mouse wheel to achieve perspective. Let’s start with the Kangkang effect:

If you have a lot of objects, and each object controls its zoom ratio and gets close enough to go through it, it’s a hassle, and we need a more scientific way to control it. Next, let’s take a case to uncover the secrets.

The body of the

1. Basic interface

class Application {
    constructor() {
        this.canvas = null;            / / the canvas
        this.ctx = null;               / / environment
        this.w = 0;                    / / wide scene
        this.h = 0;                    / / the scene
        this.textures = new Map(a);/ / texture set
        this.spriteData = new Map(a);// Sprite data
        this.alpha = 1;                / / transparency
        this.r = 300;                  // Solar radius
        this.x = 0;                    // Solar x coordinates
        this.y = 0;                    // The sun's Y-axis
        this.z = 0;                    // Solar z-axis coordinates
        this.deep = 100;               / / stadia
        this.init();
    }
    init() {
        / / initialization
        this.canvas = document.getElementById("canvas");
        this.ctx = this.canvas.getContext("2d");
        window.addEventListener("resize".this.reset.bind(this));
        this.reset();
        this.textures.set("sun".`.. /assets/sun.png`);
        this.load().then(this.render.bind(this));
    }
    load() {
        // Load the texture
        const { textures, spriteData } = this;
        let n = 0;
        return new Promise((resolve, reject) = > {
            if (textures.size == 0) resolve();
            for (const key of textures.keys()) {
                let _img = new Image();
                spriteData.set(key, _img);
                _img.onload = () = > {
                    if(++n == textures.size) resolve(); } _img.src = textures.get(key); }})}reset() {
        // Screen changes recalculate width height and xy coordinates
        this.w = this.canvas.width = this.ctx.width = window.innerWidth;
        this.h = this.canvas.height = this.ctx.height = window.innerHeight;
        this.x = this.w / 2;
        this.y = this.h / 2;
    }
    render() {
        / / the main rendering
        this.draw();
        this.step();
        this.bindWheel();
    }
    draw(){
        / / to draw
        this.drawSun();
        this.drawBackground();
    }
    bindWheel(){
        // Bind the wheel event
    }
    drawSun(){
        // Draw the sun
    }
    drawBackground(){
        // Draw the background
    }
    step(delta) {
        / / redraw
        const { w, h, ctx } = this;
        requestAnimationFrame(this.step.bind(this));
        ctx.clearRect(0.0, w, h);
        this.draw(); }}window.onload = new Application();
Copy the code

We’ll take the canvas and give it a 2D environment, give it width and height, then load the images and store the loaded images in spriteData as sprites to use at any time. Then we haven’t drawn anything substantive, but first write the drawing structure, and then redraw the surface frame by frame. When defining variables, you should have noticed the stadia, which is the distance from the viewpoint to the corresponding point. His definition gives the whole 2D world a sense of space.

2. Paint the background color and sun

drawSun(){
    const {w,h,ctx,spriteData,alpha,r,x,y,scale}= this;
    let img = spriteData.get("sun");
    ctx.save();
    ctx.translate(x, y);
    ctx.scale(scale,scale);
    ctx.globalAlpha = alpha;
    ctx.beginPath();
    ctx.drawImage(img, -r / 2, - r / 2, r, r);
    ctx.closePath();
    ctx.restore();
}
drawBackground(){
    const {w, h, ctx } = this;
    ctx.save();
    ctx.fillStyle = "# 000"
    ctx.fillRect(0.0, w, h);
    ctx.restore();
}
Copy the code

The background is drawn as a solid black rectangle, and the sun, which we will find from the image we just saved into spriteData, is drawn in the center of the screen, but remember that its size scale and transparency alpha are controlled from the outside, and we will use them for perspective.

3. Roller events

With all the foreshadowing done, we will complete the use of perspective in this small event.

bindWheel(){
    canvas.addEventListener("wheel".e= > {
        this.z += e.deltaY * 0.05;
        if (this.z > -this.deep) {
            this.alpha =1;
            this.scale = this.deep / (this.deep + this.z);
        }else{
            this.alpha = 0; }}); }Copy the code

You can see we will through the wheel events to change the z axis and z axis will affect the proportion of stadia, further change its size, and we said that the only condition judgment if z coordinate within a specific value, the sun is visible, when he is not in the value of it is through the become invisible, so that every time I need to change the value, z The spatial relationship can be further realized.

conclusion

Do not look at this simple, canvas 2D simulation 3D is a necessary element, very practical. For example, making a 3D particle garden can be done without using WebGL, just using it to simulate the Z axis. The following is a long time ago personal do a cat case, using this method, in the near become large, small distance, if the students ask this cat game why not participate in the cat activities, the answer is THAT I lost the source code…