Some lessons from Canvas

Because there are fewer classes recently, I spent more time on Codepen, so I could learn some excellent works. Yesterday, I saw a dazzling starry sky. Let me show you the effect first.

Source is surprisingly short, but a total of more than one hundred lines, the logic of the code is written in simple, the main idea is different stars orbit around the center of rotation, followed by the larger the radius of stars the more we close on the vision, because the center is the farthest point, so apoapsis should rotation rate was the fastest, the clearer and more. It didn’t take a lot of time to read this code, and the first reading was still logical.

  • It is the author of the source code there is a comment, or very necessary, here quoted.

// Thanks @jackrugile for the performance tip! https://codepen.io/jackrugile/pen/BjBGoM // Cache gradient

Let’s reference the code below the comment again

var canvas2 = document.createElement('canvas'), ctx2 = canvas2.getContext('2d'); canvas2.width = 100; canvas2.height = 100; var half = canvas2.width/2, gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half); Gradient2. AddColorStop (0.025, '# FFF); Gradient2. AddColorStop (0.1, 'an HSL (' + +' hue, 61%, 33%) '); Gradient2. AddColorStop (0.25, 'an HSL (' + +' hue, 64%, 6%) '); gradient2.addColorStop(1, 'transparent'); ctx2.fillStyle = gradient2; ctx2.beginPath(); ctx2.arc(half, half, half, 0, Math.PI * 2); ctx2.fill();Copy the code

This code means to draw a gradient on the new canvas, corresponding to the stars in the sky. Combined with the author’s comments, the purpose is to put the invariant elements in an off-screen canvas, and then reference them in the drawImage in the main canvas to reduce drawing. It is also a strategy for performance tuning. In fact, for students with a little experience, this is also a very common skill, here specially, but also hope to give some advice to new students.

  • The second thing is color

I believe most front-end enthusiasts are the same as me. They are all computers and have no understanding of colors. After a deep analysis of the author’s code, there are many interesting tricks, and you can feel the author’s interesting imagination.

The stars will twinkle, how to highlight the stars twinkle? Canvas has the property of shadowBlur, which is similar to the box-shadow in CSS. Of course, you can use this method to highlight flicker, but this effect is not good! The author’s method is clever. The idea is to use radial gradients and put code in them.

gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half); Gradient2. AddColorStop (0.025, '# FFF); Gradient2. AddColorStop (0.1, 'an HSL (' + +' hue, 61%, 33%) '); Gradient2. AddColorStop (0.25, 'an HSL (' + +' hue, 64%, 6%) '); gradient2.addColorStop(1, 'transparent');Copy the code

Personally, I think this code is a stroke of genius. There is another point here, which is the author’s setting of the body background color

	body {
 		 background: #060e1b;
  		 overflow: hidden;
	}
Copy the code

Here, # 060E1B is converted to HSL (217, 64%, 6%), including HSL (217, 64%, 6%) for fillRect. This color is the third color of the gradient.

Why did the author choose the four colors of the gradient? From the top down

# FFF White HSL (217, 61%, 33%) Dark blue sky HSL (217, 61%, 6%) more dark blue due to reduced brightness RGBA (0,0,0) // Note note, Transparent used to be rgba(0,0,0,0);Copy the code

The first color white is easy to understand, is the light of the stars, the second color is the bright background color, the third color is dark because there is less light, and finally gradually becomes dark. A lot of people will say what’s the use of rgba(0,0,0,0) at the end?

This is in conjunction with the code that follows

ctx.globalCompositeOperation = 'source-over'; CTX. GlobalAlpha = 0.8; ctx.fillStyle = 'hsla(' + hue + ', 64%, 6%, 1)'; ctx.fillRect(0, 0, w, h) ctx.globalCompositeOperation = 'lighter';Copy the code

After tiled the background with hSLA (‘ + Hue + ‘, 64%, 6%, 1), the author used globalCompositeOperation = ‘lighter’ to blend the stars with the background colors. In the end the transparent completely melts into the background.

While in HSL (217, 61%, 6%) -> rgba(0,0,0,0) changes?

We convert HSL (217, 61%, 6%) to RGB to RGB (6, 14, 25), which is very close to rgba(0,0,0).

Let’s put a transition diagram for # FFF -> rgba(0,0,0,0).

It’s going to be dark, and then it’s going to be light, because it’s going to be transparent at the end, and this is the base color. So we can get HSL (217, 61%, 6%) -> rgba(0,0,0,0) change, which is the darker background color -> background color change, because the two colors are similar, really not much difference.

The author at the beginning of drawing with CTX. GlobalCompositeOperation = ‘source – over; To avoid too many stars, we used ctx.globalAlpha = 0.8 to tile the background color so that the frames with stars would have a little bit of afterglow, as if the stars had dimmed. All great ideas.

So in the future we can use the above method to make flashing objects, such as fireworks, lasers and so on

Put this to use

After being inspired, I wrote a demo in the afternoon, or the first effect picture.

Here the luminous scheme is from the front of the scheme, hey hey, the author feels pretty good, there is a ** ‘dark sky low, bright stars with’ ** feeling, good to give you analysis of some of my trick. Here are some good points to share with you, because there are a lot of elements here, definitely not the way the previous code is organized.

The way I organize myself

var Render = {
	  startCount: 100,
     starList: [],
     cacheCanvas: {}
     init: () => {},
     drawFigure: () => {}
}
	
var Star = () => {};
Star.prototype.draw = () => {}
Copy the code

Render controls the entire animation on the screen, init method is used to generate stars, grass, street lights, etc. DrawFigure is used to animate, cancheCanvas is used to cache immutable objects like stars, etc.

Let me show you how I drew the stars, so you can see what I’m doing, my stars are moving horizontally, so I have to think about stars flying off the screen, and once they fly off the screen, I have to fill in the stars.

  • Generation of stars

    Corresponding init method

      for (var i = 0; i < this.startCount; i++) {
          this.starList.push(new Star(random(w), random(0, h), 			this.radius));
    	}
    Copy the code
  • Draw a star

    Corresponding to drawFigure method

    ctx.globalCompositeOperation = 'source-over'; CTX. GlobalAlpha = 0.8; ctx.fillStyle = 'hsla(' + hue + ', 64%, 6%, 1)'; ctx.fillRect(0, 0, w, h); ctx.globalCompositeOperation = 'lighter'; for (var i = 0; i < this.starList.length; I ++) {if (this.starlist [I].draw()) {this.starlist.splice (I, 1); this.starList.push(new Star(random(w), random(h), this.radius, 1)); }}Copy the code
  • The movement of stars

    Draw method corresponding to STAR

    This.x = this.x + 0.5 * math.random () * math.random (); var twinkle = random(10); If (twinkle == 1 &&this. Alpha < 0) {this. Alpha += 0.05; } if (twinkle == 2 && this. Alpha > 1) {this.alpha -= 0.05; } ctx.globalAlpha = this.alpha; ctx.drawImage(Render.cacheCanvas.star, this.x - this.radius / 2, this.y - this.radius / 2, this.radius, this.radius); return this.x > w || this.y > h ? true : falseCopy the code

    The grass in the animation is drawn with bezier curves, and there’s no trick to this, you have to do it yourself, and we’re going to make the grass sway with the wind and the trick here is to rotate the canvas to the root of the grass, and then rotate the canvas and paste the code.

     	ctx.save();
      ctx.translate(this.x, this.y);
      ctx.rotate(this.theta);
      ctx.globalCompositeOperation = 'source-over';
    Copy the code

As for desk lamp and moon is oneself a little bit of painting, a little bit of tune, there is no shortcut. A Canvas is a canvas on which you can use your endless imagination. After school, visit Codepen more, learn other people’s excellent works, improve their own.