Canvas is used to draw images and animations on web pages. It can be understood as a canvas on which to build the desired effect.

Canvas can draw dynamic effects. In addition to common regular animations, it can also adopt the concept of particles to realize complex dynamic effects. In this paper, ordinary dynamic effects and particle effects are respectively used to achieve a simple clock.

Ordinary clock

Ordinary dynamic effect is to use canvas API to achieve regular patterns and animations.

The effect

The effect is relatively simple, the main analysis of the scale and pointer Angle offset.

Draw the calibration

This example is the hour scale drawing: there are 12 hours on the dial, math.pi is 180 degrees, and each hour occupies 30 degrees. .save() means to save the current state of canvas environment and draw on this basis. After the drawing is complete, return to the path state and properties that you saved previously.

For the minute scale, change the Angle and style.

  // Hour time scale
  offscreenCanvasCtx.save();
  for (var i = 0; i < 12; i++) {
    offscreenCanvasCtx.beginPath();
    // Scale color
    offscreenCanvasCtx.strokeStyle = '#fff';
    // Scale width
    offscreenCanvasCtx.lineWidth = 3;
    // Occupy 30° per hour
    offscreenCanvasCtx.rotate(Math.PI / 6);
    // Start drawing position
    offscreenCanvasCtx.lineTo(140.0)
    // End drawing position;
    offscreenCanvasCtx.lineTo(120.0);
    // Draw the path
    offscreenCanvasCtx.stroke();
  }
  offscreenCanvasCtx.restore();
Copy the code

Pointer to

Take the second hand as an example: get the number of seconds of the current time and calculate the corresponding offset Angle

  var now = new Date(),
    sec = now.getSeconds(),
    min = now.getMinutes(),
    hr = now.getHours();
  hr = hr > 12 ? hr - 12 : hr;
  
  / / second hand
  offscreenCanvasCtx.save();
  offscreenCanvasCtx.rotate(sec * (Math.PI / 30)); . offscreenCanvasCtx.stroke();Copy the code

Particle dynamic effect

Canvas can be used to draw complex and irregular animations. Particle effects can be used to achieve complex, random, dynamic effects.

Particle refers to every pixel in the imageData imageData. After obtaining each pixel, add attributes or events to interact with particles in the region to achieve dynamic effects.

The effect

Particles to obtain

Take the following image as an example. The effect is to first render the image on the canvas and then get every pixel in the region where the text is located.

  let image = new Image();
  image.src='.. /image/logo.png';
  let pixels=[]; // Store pixel data
  let imageData;
  image.width = 300;
  image.height = 300
  // Render the image and get the pixel information in the area
  image.onload=function(){
    ctx.drawImage(image,(canvas.width-image.width)/2,(canvas.height-image.height)/2,image.width,image.height);
    imageData=ctx.getImageData((canvas.width-image.width)/2,(canvas.height-image.height)/2,image.width,image.height); // Get chart pixel information
 // Draw the image
  };
Copy the code

Pixel information

The image is 300 by 300, with 90,000 pixels, each with 4 bits, and holds RGBA data.

Particle rendering

  function getPixels(){
    var pos=0;
    var data=imageData.data; //RGBA's one-dimensional array data
    // The height and width of the source image are 300px
    for(var i=1; i<=image.width; i++){for(var j=1; j<=image.height; j++){ pos=[(i- 1)*image.width+(j- 1)] *4; // Get the pixel position
        if(data[pos]>=0) {var pixel={
            x:(canvas.width-image.width)/2+j+Math.random()*20.// Resets the location information for each pixel
            y:(canvas.height-image.height)/2+i+Math.random()*20.// Resets the location information for each pixel
            fillStyle:'rgba('+data[pos]+', '+(data[pos+1]) +', '+(data[pos+2]) +', '+(data[pos+3]) +') '} pixels.push(pixel); }}}}function drawPixels() {
    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("2d");
    ctx.clearRect(0.0,canvas.width,canvas.height);
    var len = pixels.length, curr_pixel = null;
    for (var i = 0; i < len; i++) {
      curr_pixel = pixels[i];
      ctx.fillStyle = curr_pixel.fillStyle;
      ctx.fillRect(curr_pixel.x, curr_pixel.y, 1.1); }}Copy the code

Particle clock

Render text clock

  function time() {
    ctx.clearRect(0.0,canvas.width,canvas.height)
    ctx.font = "150 px blackbody";
    ctx.textBaseline='top';
    ctx.fillStyle = "Rgba (245245245,0.2)";
    ctx.fillText(new Date().format('hh:mm:ss'),(canvas.width-textWidth)/2,(canvas.height-textHeight)/2,textWidth,textHeight);
  }
Copy the code

The effect

To obtain the particle

The concept of text conversion particle is the same as above. Obtain the pixels of the selected area, select them according to the filtering conditions and store them in an array. Redraw it after traversing it.

  function getPixels(){
    let imgData = ctx.getImageData((canvas.width-textWidth)/2,(canvas.height-textHeight)/2,textWidth,textHeight);
    let data = imgData.data
    pixelsArr = []
    for(let i=1; i<=textHeight; i++){for(let j=1; j<=textWidth; j++){ pos=[(i- 1)*textWidth+(j- 1)] *4; // Get the pixel position
        if(data[pos]>=0) {var pixel={
            x:j+Math.random()*20.// Resets the location information for each pixel
            y:i+Math.random()*20.// Resets the location information for each pixel
            fillStyle:'rgba('+data[pos]+', '+(data[pos+1]) +', '+(data[pos+2]) +', '+(data[pos+3]) +') '}; pixelsArr.push(pixel); }}}}Copy the code

ImgData stores pixel information in the selected area, with each pixel occupying 4 bits and RGBA 4 bits of information. Filtering the fourth bit of each pixel, this code saves all pixels with non-zero opacity into the array pixelsArr.

X and Y record the position information of the particle. In order to produce the motion effect in the effect drawing, 0-20 pixels of offset position are added to each particle. During each redrawing, the offset position is randomly generated to produce the motion effect.

Particles to redraw

After obtaining the particles, you need to clear the original text on the canvas and redraw the particles onto the canvas.

  function drawPixels() {
    // Clear the canvas and repaint it
    ctx.clearRect(0.0,canvas.width,canvas.height);
    for (let i in pixelsArr) {
      ctx.fillStyle = pixelsArr[i].fillStyle;
      let r = Math.random()*4ctx.fillRect(pixelsArr[i].x, pixelsArr[i].y, r, r); }}Copy the code

The style of particle redrawing is the original color and transparency when filtering pixels, and the size parameter R is defined when each particle is drawn on the canvas, and the value of r is a random number from 0 to 4. The resulting particle size is random.

Real-time refresh

The page refresh time is required in real time after the particle is captured and successfully redrawn. Here by the window. The requestAnimationFrame (the callback) method.

  function time() {... getpixels();// Get particles
    drawPixels(); // redraw particles
    requestAnimationFrame(time);
  }
Copy the code

Window. RequestAnimationFrame (the callback) method tells the browser you want to perform the animation and request the browser before the next redraw call the specified function to update the animation. This method takes as an argument a callback function that is called before the browser redraws.

This method does not need to set the time interval, and the call frequency adopts the system time interval (1s).

The documentation is explained here

The effect

conclusion

This paper mainly realizes the dynamic effect of clock through two different ways, among which the particle clock has more maneuverability. More dynamic effects will be implemented for particle systems in the future canvas series.

Spread the word

This article is published in Front of Mint Weekly. Welcome to Watch & Star.

Welcome to the discussion. Give it a thumbs up before we go. ◕ ‿ ◕. ~