Canvas学习-时钟绘制

朱雀 2021-08-02 12:08 592阅读 0赞

Canvas学习-时钟绘制

1. 绘制时钟外边框

  • 创建画布



备注:该容器就是绘制图形的画布。

  • 绘制圆环

    var dom = document.getElementById(‘clock’); //获取元素
    var ctx = dom.getContext(‘2d’); //上下文
    var width = ctx.canvas.width; //上下文的宽度
    var height = ctx.canvas.height; //上下文的高度
    var r = width / 2; //半径

    // 绘制圆环
    function drawBackground() {

    1. ctx.translate(r, r); //确定坐标远点
    2. ctx.beginPath(); //开始画图
    3. ctx.lineWidth = 10; // 设置线条粗细
    4. ctx.arc(0, 0, r-5, 0, 2 * Math.PI, false); //绘制圆形
    5. ctx.stroke(); //绘制

    }
    drawBackground();


2.绘制时钟内容

  1. // 绘制小时数
  2. var hourNumbers = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
  3. ctx.font = '18px Arial';
  4. ctx.textAlign = 'center';
  5. ctx.textBaseline = 'middle';
  6. hourNumbers.forEach(function (number, i) {
  7. var rad = 2 * Math.PI / 12 * i;
  8. var x = Math.cos(rad) * (r - 30);
  9. var y = Math.sin(rad) * (r - 30);
  10. ctx.fillText(number, x, y);
  11. })

备注:在绘制小时数的时候,我们应该确定数字与对应弧度的关系,建立数组,填充数字。


3. 绘制小时数对应的圆点

  1. // 绘制小时数对应的点
  2. for (var i = 0; i < 60; i++) {
  3. var rad = 2 * Math.PI / 60 * i;
  4. var x = Math.cos(rad) * (r - 18);
  5. var y = Math.sin(rad) * (r - 18);
  6. ctx.beginPath();
  7. if (i % 5 === 0) {
  8. ctx.fillStyle = "#000";
  9. ctx.arc(x, y, 2, 0, 2 * Math.PI, false);
  10. } else {
  11. ctx.fillStyle = "#ccc";
  12. ctx.arc(x, y, 2, 0, 2 * Math.PI, false);
  13. }
  14. ctx.fill();
  15. }

备注:绘制圆点的时候,我们需要区分整点数与非整点数之间的区别,填充不同的背景颜色。


4.绘制是真分针秒针

  1. // 画时针
  2. function drawHour(hour, minute) {
  3. ctx.save();
  4. ctx.beginPath();
  5. var rad = 2 * Math.PI / 12 * hour;
  6. var mrad = 2 * Math.PI / 12 / 60 * minute;
  7. ctx.rotate(rad + mrad);
  8. ctx.lineWidth = 6;
  9. ctx.lineCap = 'round';
  10. ctx.moveTo(0, 10);
  11. ctx.lineTo(0, -r / 2);
  12. ctx.stroke();
  13. ctx.restore();
  14. }
  15. // 画分针
  16. function drawMinute(minute, second) {
  17. ctx.save();
  18. ctx.beginPath();
  19. var rad = 2 * Math.PI / 60 * minute;
  20. var srad = 2 * Math.PI / 60 / 60 * second;
  21. ctx.rotate(rad + srad);
  22. ctx.lineWidth = 3;
  23. ctx.lineCap = 'round';
  24. ctx.moveTo(0, 10);
  25. ctx.lineTo(0, -r + 30);
  26. ctx.stroke();
  27. ctx.restore();
  28. }
  29. // 画秒针
  30. function drawSecond(second) {
  31. ctx.save();
  32. ctx.beginPath();
  33. ctx.fillStyle = '#c14543';
  34. var rad = 2 * Math.PI / 60 * second;
  35. ctx.rotate(rad);
  36. ctx.moveTo(-2, 20);
  37. ctx.lineTo(2, 20);
  38. ctx.lineTo(1, -r + 18);
  39. ctx.lineTo(-1, -r + 18);
  40. ctx.lineTo(0, -r + 30);
  41. ctx.fill();
  42. ctx.restore();
  43. }

备注:绘制分针的时候,我们需要考虑到分针对其的影响,所以需要计算分针数引起时针的弧度改变。在绘制分针的时候,同样需要考虑秒针对分针的影响。


4. 画中心点

  1. // 画中心点
  2. function drawDot() {
  3. ctx.beginPath();
  4. ctx.fillStyle = '#FFFFFF';
  5. ctx.arc(0, 0, 3, 2 * Math.PI, false)
  6. ctx.fill();
  7. }

5. 最终绘制方法

  1. function draw() {
  2. ctx.clearRect(0, 0, width, height);
  3. var now = new Date();
  4. var hour = now.getHours();
  5. var minute = now.getMinutes();
  6. var second = now.getSeconds();
  7. drawBackground();
  8. drawHour(hour, minute);
  9. drawMinute(minute, second);
  10. drawSecond(second);
  11. drawDot();
  12. ctx.restore();
  13. }
  14. draw();
  15. setInterval(draw, 1000);

备注:在绘制图形的时候,我们需要注意一下几点:

  • 绘制之前,我们需要清除画布,避免图形的叠加。
  • 主要保存画布之前的状态,还原状态,避免影响。
  • 利用定时器,每隔一秒钟,重新绘制图片。

6. 效果图

在这里插入图片描述


7. 代码

  1. var dom = document.getElementById('clock'); //获取元素
  2. var ctx = dom.getContext('2d'); //上下文
  3. var width = ctx.canvas.width; //上下文的宽度
  4. var height = ctx.canvas.height; //上下文的高度
  5. var r = width / 2; //半径
  6. // 绘制圆环
  7. function drawBackground() {
  8. ctx.save();
  9. ctx.translate(r, r); //确定坐标远点
  10. ctx.beginPath(); //开始画图
  11. ctx.lineWidth = 10; // 设置线条粗细
  12. ctx.arc(0, 0, r - 5, 0, 2 * Math.PI, false); //绘制圆形
  13. ctx.stroke(); //绘制
  14. // 绘制小时数
  15. var hourNumbers = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
  16. ctx.font = '18px Arial';
  17. ctx.textAlign = 'center';
  18. ctx.textBaseline = 'middle';
  19. hourNumbers.forEach(function (number, i) {
  20. var rad = 2 * Math.PI / 12 * i;
  21. var x = Math.cos(rad) * (r - 30);
  22. var y = Math.sin(rad) * (r - 30);
  23. ctx.fillText(number, x, y);
  24. })
  25. // 绘制小时数对应的点
  26. for (var i = 0; i < 60; i++) {
  27. var rad = 2 * Math.PI / 60 * i;
  28. var x = Math.cos(rad) * (r - 18);
  29. var y = Math.sin(rad) * (r - 18);
  30. ctx.beginPath();
  31. if (i % 5 === 0) {
  32. ctx.fillStyle = "#000";
  33. ctx.arc(x, y, 2, 0, 2 * Math.PI, false);
  34. } else {
  35. ctx.fillStyle = "#ccc";
  36. ctx.arc(x, y, 2, 0, 2 * Math.PI, false);
  37. }
  38. ctx.fill();
  39. }
  40. }
  41. // 画时针
  42. function drawHour(hour, minute) {
  43. ctx.save();
  44. ctx.beginPath();
  45. var rad = 2 * Math.PI / 12 * hour;
  46. var mrad = 2 * Math.PI / 12 / 60 * minute;
  47. ctx.rotate(rad + mrad);
  48. ctx.lineWidth = 6;
  49. ctx.lineCap = 'round';
  50. ctx.moveTo(0, 10);
  51. ctx.lineTo(0, -r / 2);
  52. ctx.stroke();
  53. ctx.restore();
  54. }
  55. // 画分针
  56. function drawMinute(minute, second) {
  57. ctx.save();
  58. ctx.beginPath();
  59. var rad = 2 * Math.PI / 60 * minute;
  60. var srad = 2 * Math.PI / 60 / 60 * minute;
  61. ctx.rotate(rad + srad);
  62. ctx.lineWidth = 3;
  63. ctx.lineCap = 'round';
  64. ctx.moveTo(0, 10);
  65. ctx.lineTo(0, -r + 30);
  66. ctx.stroke();
  67. ctx.restore();
  68. }
  69. // 画秒针
  70. function drawSecond(second) {
  71. ctx.save();
  72. ctx.beginPath();
  73. ctx.fillStyle = '#c14543';
  74. var rad = 2 * Math.PI / 60 * second;
  75. ctx.rotate(rad);
  76. ctx.moveTo(-2, 20);
  77. ctx.lineTo(2, 20);
  78. ctx.lineTo(1, -r + 18);
  79. ctx.lineTo(-1, -r + 18);
  80. ctx.lineTo(0, -r + 30);
  81. ctx.fill();
  82. ctx.restore();
  83. }
  84. // 画中心点
  85. function drawDot() {
  86. ctx.beginPath();
  87. ctx.fillStyle = '#FFFFFF';
  88. ctx.arc(0, 0, 3, 2 * Math.PI, false)
  89. ctx.fill();
  90. }
  91. function draw() {
  92. ctx.clearRect(0, 0, width, height);
  93. var now = new Date();
  94. var hour = now.getHours();
  95. var minute = now.getMinutes();
  96. var second = now.getSeconds();
  97. drawBackground();
  98. drawHour(hour, minute);
  99. drawMinute(minute, second);
  100. drawSecond(second);
  101. drawDot();
  102. ctx.restore();
  103. }
  104. draw();
  105. setInterval(draw, 1000);

8. 思考

如果画布放大,那么图像会怎么样呢?显然,因为其中部分数据大小是固定写死的,必然出现不协调的地方,此时我们必须考虑到,数据的比例问题。修改思路如下:在宽度、文字大小部分,我们需要采用相对大小。


9. 代码优化

优化思路:首先确定比例,var rem = width/ 200; //比例(因为初始样式的数据是按照200为基准的) ,然后在对应的数字大小部分乘上该比例即可。修改后的代码如下:

  1. var dom = document.getElementById('clock'); //获取元素
  2. var ctx = dom.getContext('2d'); //上下文
  3. var width = ctx.canvas.width; //上下文的宽度
  4. var height = ctx.canvas.height; //上下文的高度
  5. var r = width / 2; //半径
  6. var rem = width/ 200; //比例(因为初始样式的数据是按照200为基准的)
  7. // 绘制圆环
  8. function drawBackground() {
  9. ctx.save();
  10. ctx.translate(r, r); //确定坐标远点
  11. ctx.beginPath(); //开始画图
  12. ctx.lineWidth = 10 * rem; // 设置线条粗细
  13. ctx.arc(0, 0, r - ctx.lineWidth/2, 0, 2 * Math.PI, false); //绘制圆形
  14. ctx.stroke(); //绘制
  15. // 绘制小时数
  16. var hourNumbers = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
  17. ctx.font = 18* rem + 'px Arial';
  18. ctx.textAlign = 'center';
  19. ctx.textBaseline = 'middle';
  20. hourNumbers.forEach(function (number, i) {
  21. var rad = 2 * Math.PI / 12 * i;
  22. var x = Math.cos(rad) * (r - 30* rem);
  23. var y = Math.sin(rad) * (r - 30* rem);
  24. ctx.fillText(number, x, y);
  25. })
  26. // 绘制小时数对应的点
  27. for (var i = 0; i < 60; i++) {
  28. var rad = 2 * Math.PI / 60 * i;
  29. var x = Math.cos(rad) * (r - 18* rem);
  30. var y = Math.sin(rad) * (r - 18* rem);
  31. ctx.beginPath();
  32. if (i % 5 === 0) {
  33. ctx.fillStyle = "#000";
  34. ctx.arc(x, y, 2* rem, 0, 2 * Math.PI, false);
  35. } else {
  36. ctx.fillStyle = "#ccc";
  37. ctx.arc(x, y, 2* rem, 0, 2 * Math.PI, false);
  38. }
  39. ctx.fill();
  40. }
  41. }
  42. // 画时针
  43. function drawHour(hour, minute) {
  44. ctx.save();
  45. ctx.beginPath();
  46. var rad = 2 * Math.PI / 12 * hour;
  47. var mrad = 2 * Math.PI / 12 / 60 * minute;
  48. ctx.rotate(rad + mrad);
  49. ctx.lineWidth = 6* rem;
  50. ctx.lineCap = 'round';
  51. ctx.moveTo(0, 10* rem);
  52. ctx.lineTo(0, -r / 2);
  53. ctx.stroke();
  54. ctx.restore();
  55. }
  56. // 画分针
  57. function drawMinute(minute, second) {
  58. ctx.save();
  59. ctx.beginPath();
  60. var rad = 2 * Math.PI / 60 * minute;
  61. var srad = 2 * Math.PI / 60 / 60 * second;
  62. ctx.rotate(rad + srad);
  63. ctx.lineWidth = 3* rem;
  64. ctx.lineCap = 'round';
  65. ctx.moveTo(0, 10* rem);
  66. ctx.lineTo(0, -r + 30* rem);
  67. ctx.stroke();
  68. ctx.restore();
  69. }
  70. // 画秒针
  71. function drawSecond(second) {
  72. ctx.save();
  73. ctx.beginPath();
  74. ctx.fillStyle = '#c14543';
  75. var rad = 2 * Math.PI / 60 * second;
  76. ctx.rotate(rad);
  77. ctx.moveTo(-2* rem, 20* rem);
  78. ctx.lineTo(2* rem, 20* rem);
  79. ctx.lineTo(1, -r + 18* rem);
  80. ctx.lineTo(-1, -r + 18* rem);
  81. ctx.fill();
  82. ctx.restore();
  83. }
  84. // 画中心点
  85. function drawDot() {
  86. ctx.beginPath();
  87. ctx.fillStyle = '#FFFFFF';
  88. ctx.arc(0, 0, 3* rem, 2 * Math.PI, false)
  89. ctx.fill();
  90. }
  91. function draw() {
  92. ctx.clearRect(0, 0, width, height);
  93. var now = new Date();
  94. var hour = now.getHours();
  95. var minute = now.getMinutes();
  96. var second = now.getSeconds();
  97. drawBackground();
  98. drawHour(hour, minute);
  99. drawMinute(minute, second);
  100. drawSecond(second);
  101. drawDot();
  102. ctx.restore();
  103. }
  104. draw();
  105. setInterval(draw, 1000);

10. 代码下载

链接:canvas学习代码下载

发表评论

表情:
评论列表 (有 0 条评论,592人围观)

还没有评论,来说两句吧...

相关阅读