Laws are created and discovered, and memory is the derivation and extraction of laws

Recently, I have been learning front-end visualization and doing some interesting demos. When learning canvas, I remembered that the first task assigned to us by the computer graphics teacher in college was to draw a clock. At that time, we used c# to draw, but now we find it more convenient to draw by using the command method of canvas. I will record and share it here.

  • Consider what a clock is made of:
  1. The dial
  2. The time scale
  3. The hour hand
  4. Minute hand
  5. The second hand
  • So let’s design a class that provides the following methods:
  1. Create the dial
  2. Drawing scale
  3. Draw the hour hand
  4. Draw a minute hand
  5. Draw the second hand
  6. Draw by second
  • Class is as follows:
// clock.ts This file requires TSC compilation
class Clock {
  / / dial canvas
  canvas = null;
  // Draw context
  context = null;
  // Time scale text
  timeText = [ "XII"."I"."II"."III"."IV"."V"."VI"."VII"."VIII"."IX"."X"."XI" ];
  // Time scale Angle
  timeTheta = Array.from({ length: 12 }, (_, i) = > (i / 12) * 2 * Math.PI);
  // Dial width
  width = 100;
  // Dial height
  height = 100;
  // constructor
  constructor(el) {
    this.initClockBoard(el);
    this.width = this.canvas.width;
    this.height = this.canvas.height;
    this.start();
  }
  // Initialize the dial
  initClockBoard(el){}// Initialize the timescale
  drawTimeText(){}// Draw the time needle
  drawTimeCircle(r = 100, color = "blue", theta = -0.5 * Math.PI){}// Draw the second hand
  drawSecondCircle(size = 200, color = 'blue'){}// Draw the minute hand
  drawMinuteCircle(size = 180,color = 'yellow'){}// Draw an hour hand
  drawHourCircle(size = 150,color = 'red'){}// The timer draws the time to walk
  drawTimer(){}/ / starter
  start(){}}Copy the code

Thus, we can create a clock by passing the Canvas element directly to initialization:

const clock = new Clock('canvas')
Copy the code

The corresponding HTML is simpler:


<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>candbox</title>
    <style>
      canvas {
        width: 256px;
        height: 256px;
        border: 1px solid # 333;
      }
    </style>
    <script src="clock.js"></script>
  </head>
  <body>
    <canvas width="512" height="512"></canvas>
    <script src="index.js"></script>
  </body>
</html>
Copy the code

Now let’s take a look at how simple each method is. Right

Initialize the dial

The dial only needs to load the canvas:

// Initialize the dial
  initClockBoard(el) {
    this.canvas = document.querySelector(el);
    this.context = this.canvas.getContext("2d");
  }
Copy the code

Of course, more strict judgment can be made on the input parameters here, and the canvas obtained more can be standardized, which is omitted here

Initialize the time scale

The time scale is to bisect a disk from 1 to 12. Let’s divide the Angle 2π of the whole circle into 12 parts and draw them in 12 positions the same distance from the dot:


// Initialize the timescale
  drawTimeText() {
    this.context.save();
    this.context.clearRect(0.0.this.width, this.height);
    this.context.translate(this.width / 2.this.height / 2);
    this.timeText.forEach((text, i) = > {
      this.context.save();
      this.context.rotate(this.timeTheta[i]);
      this.context.font = "20px Arial";
      this.context.fillStyle = "black";
      this.context.fillText(text, 0, -220);
      this.context.restore();
    });
    this.context.restore();
  }
Copy the code
Drawing time needle

Here we simply use the sector as the needle representation, drawing the sector is also relatively simple:

  // Draw the time needle
  drawTimeCircle(r = 100, color = "blue", theta = -0.5 * Math.PI) {
    this.context.save();
    this.context.beginPath();
    this.context.arc(this.width / 2.this.height / 2, r, -0.5 * Math.PI, theta);
    this.context.lineTo(this.width / 2.this.height / 2);
    this.context.fillStyle = color;
    this.context.fill();
    this.context.restore();
  }
Copy the code
Draw the second hand hour hand

We only need to draw the hour hand through the previous method of drawing the time hand, and we need to provide the length, color and Angle of each hour hand. The Angle can be converted according to the time ratio. Two points need to be paid attention to:

  1. When drawing the hour hand, the system is 24 hours, but the dial is 12 hours, so when the time is greater than 12, you need to do the corresponding conversion
  2. The dial and scale need to be redrawn when the time is carried

Details are as follows:

// Draw the second hand
  drawSecondCircle(size = 200, color = 'blue') {
    const second = new Date().getSeconds();
    const secondTheta = -0.5 * Math.PI + (second / 60) * 2 * Math.PI;
    if (second === 0) {
      this.context.clearRect(0.0.this.width, this.height);
      this.drawTimeText();
    }
    this.drawTimeCircle(size, color, secondTheta);
  }
  // Draw the minute hand
  drawMinuteCircle(size = 180,color = 'yellow') {
    const minute = new Date().getMinutes();
    const minuteTheta = -0.5 * Math.PI + (minute / 60) * 2 * Math.PI;
    if (minute === 0) {
      this.context.clearRect(0.0.this.width, this.height);
      this.drawTimeText();
    }
    this.drawTimeCircle(size, color, minuteTheta);
  }
  // Draw an hour hand
  drawHourCircle(size = 150,color = 'red') {
    const hour = new Date().getHours();
    const hourTheta =
      -0.5 * Math.PI +
      (hour / 12 > 1 ? hour / 12 - 1 : hour / 12) * 2 * Math.PI;
    if (hour === 0) {
      this.context.clearRect(0.0.this.width, this.height);
      this.drawTimeText();
    }
    this.drawTimeCircle(size, color, hourTheta);
  }
Copy the code
Draw time walk

RequestAnimationFrame () {return arrow () {return arrow () {return arrow () {return arrow () {return arrow ();

  // The timer draws the time to walk
  drawTimer() {
    this.drawTimeText();
    this.drawSecondCircle();
    this.drawMinuteCircle();
    this.drawHourCircle();
    requestAnimationFrame(() = > {
      this.drawTimer();
    });
  }
Copy the code
Start the function

Use the frame function to call the timewalk function

  / / starter
  start() {
    requestAnimationFrame(() = > {
      this.drawTimer();
    });
  }
Copy the code

A final look at the results:

The attached code