1. Introduction

I recently decided to write a colorful background animation for my website and learn how to use canvas, so THIS article was born.

Results the preview

The project address

github

2. Write code

2.1. The initialization

First initialize canvas and import star and moon pictures (lazy here, you can also draw them directly with canvas if you are interested).

Let canvas = document.querySelector('#star') const CTX = Canvas.getContext ('2d') // Set canvas to full screen Canvas. Width = window.innerwidth Canvas. Height = window.innerheight // The image of the star const star_img = Document.createelement ('img') star_img. SRC = './images/star.png' // Image of the moon const moon_img = document.createElement('img') Moon_img.src = './images/moon.png' let pockets = [] // Used to hold arrays of stars and moonsCopy the code

We can use ctx.drawImage() to see what the image looks like

2.2. Set star properties

Considering that just having the stars fall would be too monotonous, some elements were added (same with the moon).

Const config = {"star": {"min_size": 10, // star minimum size" max_size": 40, // star maximum size" rot": 0, // random initial rotation Angle 0 does not rotate "min_step": }, "moon": {"min_size": 10, "max_size": 40, "rot": 360, / / random initial rotation Angle (0-360) "min_step" : 0.5, "max_step" : 2, "num" : 20}}Copy the code

2.3. Initialize the stars and moons

Since the properties of the star and moon are the same, initialization can be done with just one initPocket function.

Const initPocket = (temp_type) => {// config[temp_type] = 2.2. For (let I = 0; i < config[temp_type].num; I++) {// xy is the randomly generated coordinates of the stars. Const x = math.random () * Canvas.width const y = math.random () * 300 // The following are the generated star size, rotation, and displacement values // The calculation formula of size and position: minimum value + random value *(maximum value - minimum value), then 2.2 is satisfied. // The rotation Angle is set to [0, star.rot] step size = config[temp_type].min_size + Math.random() * (config[temp_type].max_size - config[temp_type].min_size) rot =  config[temp_type].rot * Math.random() step = config[temp_type].min_step + Math.random() * (config[temp_type].max_step - Push ({type: temp_type, x: x, y: y, size: size, rot: rot, rot_step: rot_step, step: step }) } }Copy the code

After initializing the pockets array with initPocket(‘star’) and initPocket(‘moon’), we can use ctx.drawimage () to see the effect. The config

Ctx.beginpath () for (const pocket of pockets) {ctx.beginPath(); // The xy coordinates of the star are the upper left corner of the star, so the coordinates of the center point should be: (the x coordinate of the star + the radius of the star, the y coordinate of the star + the radius of the star) ctx.translate(pocket. Rotdegree CTX. Rotate (rot.rot * math.pi / 180) // But the stars are still drawn from the top left corner of the star, Ctx.translate (-(pocket. X + pocket. Size / 2), -(pocket. Y + pocket. Size / 2)) // select star/moon image const img = pocket. star_img : // img is the content of the image, 0 0 img.width img.height DrawImage (img, 0, 0, 0); drawImage(img, 0, 0, 0); drawImage(img, 0, 0, 0); Img. Width, img. Height, pocket. X, pocket. Y, pocket.Copy the code

The results are as followsIt can be seen from the figure that the generated image is a rectangle with the range of canvas.width*300. The size of stars is random [10,40] but will not rotate. The size of moon is random [10,40] and random rotation of 0-360 degrees meets 2.2. The config configuration

2.4. Let the stars fall

In fact, this code is similar to the drawing in 2.3. But it uses the pocket. Step property that has not been used.

Const starAnimation = () => { ClearRect (0, 0, canvas.width, canvas.height) // traverse each star or moon similar to 2.3. Ctx.beginpath () ctx.save() ctx.translate(pocket. X + pocket. Size / 2, Pocket. Y + pocket. Size / 2) ctx.rotate(pocket. Rot * math.pi / 180) // Because you need to do a drop. Pocket. Y -= pocket. Step Y > canvas. Height + pocket. Size) {pocket. X = math.random () * canvas. Width pocket Math.random() * 300 } ctx.translate(-(pocket.x + pocket.size / 2), -(pocket.y + pocket.size / 2)) const img = pocket.type == 'star' ? star_img : moon_img ctx.drawImage(img, 0, 0, img.width, img.height, pocket.x, pocket.y, pocket.size, pocket.size) ctx.restore() } }Copy the code

Once the falling animation is done, you just need to execute the starAnimation() method at intervals, such as setInterval. But since we are learning canvas, the use of requestAnimationFrame is essential. The final animation function looks like this:

// interval = ms const runAnimation = (interval) => {let begin_time = new Date().gettime () const update = () =>  { requestAnimationFrame(update) let cur_time = new Date().getTime() if (cur_time - begin_time >= interval) { starAnimation(ctx, pockets) begin_time = cur_time } } requestAnimationFrame(update) }Copy the code

Finally runAnimation(60) will fall.

3. Summary

My complete code is available on Github. Incidentally also added up and down around four methods of movement, as well as support while moving while rotating and so on. This project is a practice of learning canvas by myself. Please forgive me for many shortcomings. The above –