• Canvas 绘制一个像素风电子时钟


    想法是在 Canvas 上绘制由小方块组成的数字。

    第一步是实现绘制小方块的方法,先画出一个边长为 5 的 10x10 个方块,使用两个 for 循环很简单就能完成。

    1 for (let i = 0; i < 10; i++) {
    2     for (let j = 0; j < 10; j++) {
    3         context.fillRect(5 * i, 5 * j, 5, 5);
    4     }
    5 }

     效果如下:

     

    但是这样一大块黑色不是很好看,可以把小方块的边长减一 ,有显示网格的效果,即: context.fillRect(5 * i, 5 * j, 4, 4);

     效果如下:

     

    接下来就是把数字转换成像素风,我的想法是创建一个数组,用 0 和 1 来表示是否填充,然后遍历数组。

    如 1 为: ["0010", "0110", "0010", "0010", "0111"] ,下图所示方便理解:

     

    为之前的循环增加一个判断,遍历字符串的索引判断是否要在相应位置绘制小方块。

    x,y 是整个数字的原点(数字的左上角)。

    1 function draw_single_word(context, x, y, numberList) {
    2     for (let i = 0; i < numberList.length; i++) {
    3         for (let j = 0; j < numberList[i].length; j++) {
    4             if (numberList[i][j] === "1") {
    5                 context.fillRect(x + 5 * y + j, 5 * i, 4, 4);
    6             }
    7         }
    8     }
    9 }

      显示效果:

    类似的其他数字也可以显示,还可以加上冒号和破折号。

     1 function pixelNumber(number) {
     2     let _number = number;
     3     switch (_number) {
     4         case "0":
     5             _number = ["1111", "1001", "1001", "1001", "1111"];
     6             break;
     7         case "1":
     8             _number = ["0010", "0110", "0010", "0010", "0111"];
     9             break;
    10         case "2":
    11             _number = ["1111", "0001", "1111", "1000", "1111"];
    12             break;
    13         case "3":
    14             _number = ["1111", "0001", "1111", "0001", "1111"];
    15             break;
    16         case "4":
    17             _number = ["1001", "1001", "1111", "0001", "0001"];
    18             break;
    19         case "5":
    20             _number = ["1111", "1000", "1111", "0001", "1111"];
    21             break;
    22         case "6":
    23             _number = ["1111", "1000", "1111", "1001", "1111"];
    24             break;
    25         case "7":
    26             _number = ["1111", "0001", "0001", "0001", "0001"];
    27             break;
    28         case "8":
    29             _number = ["1111", "1001", "1111", "1001", "1111"];
    30             break;
    31         case "9":
    32             _number = ["1111", "1001", "1111", "0001", "1111"];
    33             break;
    34         case ":":
    35             _number = ["0", "1", "0", "1", "0"];
    36             break;
    37         case "-":
    38             _number = ["000", "000", "111", "000", "000"];
    39             break;
    40         case ".":
    41             _number = ["0", "0", "0", "0", "1"];
    42             break;
    43         case " ":
    44             _number = ["0", "0", "0", "0", "0"];
    45             break;
    46     }
    47     return _number;
    48 }
    pixelNumber(number)

    如下所示为数字 1-9 和 0

     

     多个字符的话,可以遍历字符逐一调用刚才的 draw_single_word 函数画出。

    只要在每个字符的 X 轴坐标上增加上一个字符的宽度,就可以防止几个字符重叠在一起。为了让字符不显得太挤,我增加了一个格子的宽度。

    需要注意的是,我设置的 “:” 和 “-” 字符宽度只有三格,因此要在循环外创建 width 函数。

    1 function draw_words(context, x, y, text) {
    2     let width = 0;
    3     for (let i = 0; i < text.length; i++) {
    4         let numberList = pixelNumber(text[i]);
    5         draw_single_word(context, x + width, y, numberList);
    6         width += (numberList[0].length + 1) * 5;
    7     }
    8 }

     效果如下:

     

     现在可以获取当前时间,并将字符绘制出来,获取当前时间的函数:

     1 function getTime() {
     2     let date = new Date();
     3     let year = date.getFullYear();
     4     let month = zeroNumber(date.getMonth() + 1); // 注意月份默认从 0 开始,所以加一才是正确的
     5     let day = zeroNumber(date.getDate());
     6     let hour = zeroNumber(date.getHours());
     7     let minutes = zeroNumber(date.getMinutes());
     8     let seconds = zeroNumber(date.getSeconds());
     9     return {
    10         date: year + "-" + month + "-" + day,
    11         time: hour + ":" + minutes + ":" + seconds
    12     }
    13 }

     为了美观,我创建了一个 zeroNumber 函数来给不足十的数字前加一个零。

    1 function zeroNumber(number) {
    2     number = number < 10 ? "0" + number : number;
    3     return number;
    4 }
    zeroNumber(number)
     

     最后,使用 requestAnimationFrame 函数让它动起来。

    1 function time_animate() {
    2     ctx_animate.clearRect(0, 0, 200, 60);
    3     draw_words(ctx_animate, 0, 0, getTime().time);
    4     window.requestAnimationFrame(time_animate);
    5 }
    6 time_animate();

     

    其实修改一下,也可显示其他东西,比如字母和简单符号。

    最后贴一下我左上角的时间的代码,这是最初的版本,可能有些许问题,顺便说一句,IE不支持 class 。

      1 class PixelTime {
      2     constructor(canvas) {
      3         this.canvas = canvas;
      4         this.context = this.canvas.getContext("2d");
      5         this.dateShow = 1; // 是否显示年
      6         this.timeShow = 1; // 是否显示时间
      7         this.pixelSide = this.canvas.width < 102 ? 2 : Math.floor(this.canvas.width / 51);
      8     }
      9     /**
     10      * 确定字符的点阵数组。
     11      */
     12     pixelNumber(number) {
     13         switch (number) {
     14             case 0:
     15                 number = ["1111", "1001", "1001", "1001", "1111"];
     16                 break;
     17             case 1:
     18                 number = ["0010", "0110", "0010", "0010", "0111"];
     19                 break;
     20             case 2:
     21                 number = ["1111", "0001", "1111", "1000", "1111"];
     22                 break;
     23             case 3:
     24                 number = ["1111", "0001", "1111", "0001", "1111"];
     25                 break;
     26             case 4:
     27                 number = ["1001", "1001", "1111", "0001", "0001"];
     28                 break;
     29             case 5:
     30                 number = ["1111", "1000", "1111", "0001", "1111"];
     31                 break;
     32             case 6:
     33                 number = ["1111", "1000", "1111", "1001", "1111"];
     34                 break;
     35             case 7:
     36                 number = ["1111", "0001", "0001", "0001", "0001"];
     37                 break;
     38             case 8:
     39                 number = ["1111", "1001", "1111", "1001", "1111"];
     40                 break;
     41             case 9:
     42                 number = ["1111", "1001", "1111", "0001", "1111"];
     43                 break;
     44             case ":":
     45                 number = ["0", "1", "0", "1", "0"];
     46                 break;
     47             case "-":
     48                 number = ["000", "000", "111", "000", "000"];
     49                 break;
     50             case ".":
     51                 number = ["0", "0", "0", "0", "1"];
     52                 break;
     53             case " ":
     54                 number = ["0", "0", "0", "0", "0"];
     55                 break;
     56         }
     57         return number;
     58     }
     59 
     60     /**
     61      * 绘制点阵。
     62      */
     63     drawPixelWord(x, y, words) {
     64         let width = 0;
     65         for (let i = 0; i < words.length; i++) {
     66             let word = parseInt(words[i]) || words[i] === "0" ? parseInt(words[i]) : words[i];
     67             word = this.pixelNumber(word);
     68             for (let r = 0; r < word.length; r++) {
     69                 for (let c = 0; c < word[r].length; c++) {
     70                     if (word[r][c] === "1") {
     71                         let side = this.pixelSide - 1;
     72                         this.context.save();
     73                         this.context.translate(x + width + this.pixelSide * 2, y + this.pixelSide * 2);
     74                         this.context.fillRect(c * (side + 1), r * (side + 1), side, side);
     75                         this.context.restore();
     76                     }
     77                 }
     78             }
     79             width += (1 + word[0].length) * this.pixelSide;
     80         }
     81     }
     82 
     83     /**
     84      * 给个位数前面加个零,如:01
     85      * @param number {number}
     86      * @returns {number}
     87      */
     88     zeroNumber(number) {
     89         number = number < 10 ? "0" + number : number;
     90         return number;
     91     }
     92 
     93     /**
     94      * 获取当前时间。
     95      * @returns {{date: string, time: string}}
     96      */
     97     getTime() {
     98         let date = new Date();
     99         let year = date.getFullYear();
    100         let month = this.zeroNumber(date.getMonth() + 1); // 月份默认从 0 开始
    101         let day = this.zeroNumber(date.getDate());
    102         let hour = this.zeroNumber(date.getHours());
    103         let minutes = this.zeroNumber(date.getMinutes());
    104         let seconds = this.zeroNumber(date.getSeconds());
    105         return {
    106             date: year + "-" + month + "-" + day,
    107             time: hour + ":" + minutes + ":" + seconds
    108         }
    109     }
    110 
    111     drawTime() {
    112         this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    113         let now = this.getTime();
    114         if (this.dateShow && this.timeShow) {
    115             this.drawPixelWord(0, 0, now.date);
    116             this.drawPixelWord(this.pixelSide * 14, this.pixelSide * 6, now.time);
    117         } else if (this.dateShow) {
    118             this.drawPixelWord(0, 0, now.date);
    119         } else if (this.timeShow) {
    120             this.drawPixelWord(0, 0, now.time);
    121         }
    122     }
    123 }
    PixelTime
  • 相关阅读:
    Python网络爬虫与信息提取(二)—— BeautifulSoup
    Linux文件系统概述
    XML简介
    JSON数据格式
    SQL*Loader之CASE8
    SQL*Loader之CASE9
    SQL*Loader之CASE10
    SQL*Loader之CASE11
    Oracle工具之DBNEWID
    Oracle常用函数汇总
  • 原文地址:https://www.cnblogs.com/jmtm/p/11686175.html
Copyright © 2020-2023  润新知