技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> JavaScript --> 使用canvas绘制时钟

使用canvas绘制时钟

浏览:2812次  出处信息

准备工作

在HTML中指定一个区域放置时钟:

<div id="clock" style="position: relative;"></div>

时钟的一些外观设定:

var width = 260; // 桌布宽度
var height= 260; // 桌布高度
var dot = {
  x : width / 2,
  y : height / 2,
  radius : 6
}; // 圆点位置、半径
var radius = 120; // 圆半径
var borderWidth = 6; // 圆边框宽度

创建<canvas>元素:

var clock = document.getElementById('clock');
var clockBg = document.createElement('canvas');
var clockPointers = document.createElement('canvas');
  
clockPointers.width = clockBg.width = width;
clockPointers.height = clockBg.height = height;
clockPointers.style.position = 'absolute';
clockPointers.style.left = 0;
clockPointers.style.right = 0;

clock.appendChild(clockBg);
clock.appendChild(clockPointers);

这里要创建两个<canvas>元素,目的在于把时钟的圆盘跟指针分离开。这是因为指针要根据当前时间擦除重绘,如果放置在一个<canvas>中,擦除的时候就会把圆盘也给擦掉了。

绘制圆盘

但凡要在<canvas>中绘图,都要先获得其上下文,对应的接口是 canvas.getContext

var bgCtx = clockBg.getContext('2d');

目前canvas.getContext接口的唯一一个合法参数是'2d',将来应该会支持3D绘图。

先来绘制最外面的圆框:

bgCtx.beginPath();
bgCtx.lineWidth = borderWidth;
bgCtx.strokeStyle = '#000';
bgCtx.arc(dot.x, dot.y, radius, 0, 2 * Math.PI, true);
bgCtx.stroke();
bgCtx.closePath();

绘图的流程其实都是类似的:

  1. 调用 context.beginPath() 新建路径;
  2. 设置颜色等样式;
  3. 调用路径函数生成路径;
  4. 画线(stroke)或者填充(fill);
  5. 调用 context.closePath() 关闭路径;

上面用到的的 context.arc 接口可以生成圆弧路径,其详细说明参见此处

用类似的方法,画出圆点:

bgCtx.beginPath();
bgCtx.fillStyle = '#000';
bgCtx.arc(dot.x, dot.y, dot.radius, 0, 2 * Math.PI, true);
bgCtx.fill();
bgCtx.closePath();

此时,结果如下图所示:

时钟圆框和圆点

绘制刻度

最复杂的地方就是画刻度了,这里要先复习一下数学中的三角函数

三角函数

刻度的起始位置就是圆框上的一个点,第一步就是要知道这个点的坐标。上图中:

sinθ = AC / AO
cosθ = OC / AO

其中AO即为圆半径,而θ的值则根据刻度而定。0是π/2,3是0,6是3π/2,9是π:

三角函数坐标

由此可得到刻度起始点的位置为:

x = 圆点横坐标 + AO * cosθ
y = 圆点纵坐标 + AO * sinθ

同理可算出刻度结束点的位置为(结束点相当于在一个半径为圆框半径-刻度长度的圆上):

x = 圆点横坐标 + (AO - 刻度长度) * cosθ
y = 圆点纵坐标 + (AO - 刻度长度) * sinθ

于是,这程序可以写了:

for (var i = 0, angle = 0, tmp, len; i < 60; i++) {
  bgCtx.beginPath();
  
  // 突出显示能被5除尽的刻度
  if (0 === i % 5) {
    bgCtx.lineWidth = 5;
    len = 12;
    bgCtx.strokeStyle = '#000';
  } else {
    bgCtx.lineWidth = 2;
    len = 6;
    bgCtx.strokeStyle = '#999';
  }
  
  tmp = radius - borderWidth / 2; // 因为圆有边框,所以要减去边框宽度
  bgCtx.moveTo(
    dot.x + tmp * Math.cos(angle),
    dot.y + tmp * Math.sin(angle)
  );
  tmp -= len;
  bgCtx.lineTo(dot.x + tmp * Math.cos(angle), dot.y + tmp * Math.sin(angle));
  bgCtx.stroke();
  bgCtx.closePath();
  
  angle += Math.PI / 30; // 每次递增1/30π
}

画好刻度后,结果应该是这样:

时钟刻度

画指针

先得获取指针<canvas>的上下文:

var ptxContext = clockPointers.getContext('2d');

由于画指针的操作每隔一秒都要执行一次,所以这里就写成一个函数,方便传给setInterval调用:

function updatePointers() {
  ptCtx.clearRect(0, 0, width, height);  // 清掉原来的指针
  
  // 获取当前时间
  var now = new Date();
  var h = now.getHours();
  var m = now.getMinutes();
  var s = now.getSeconds();
  
  // 算出时分秒指针现在应指向圆的几分之几处
  h = h > 12 ? h - 12 : h;
  h = h + m / 60;
  h = h / 12;
  m = m / 60;
  s = s / 60;
  
  drawPointers(s, 2, 92); // 画秒针
  drawPointers(m, 4, 82); // 画分针
  drawPointers(h, 6, 65); // 画时针
}

drawPointers函数的实现是:

// angle是角度,lineWidth是指针宽度,length是指针长度
function drawPointers(angle, lineWidth, length) {
  angle = angle * Math.PI * 2 - Math.PI / 2;
  
  ptCtx.beginPath();
  ptCtx.lineWidth = lineWidth;
  ptCtx.strokeStyle = "#000";
  ptCtx.moveTo(dot.x, dot.y);
  ptCtx.lineTo(dot.x + length * Math.cos(angle), dot.y + length * Math.sin(angle));
  ptCtx.stroke();
  ptCtx.closePath();
}

这里主要也是用到三角函数,就不

建议继续学习:

  1. Canvas学习教程 : Canvas介绍    (阅读:3108)
  2. 使用JavaScript和Canvas开发游戏    (阅读:2578)
  3. HTML5 Canvas(画布)教程    (阅读:2551)
  4. 使用JavaScript和Canvas开发游戏(一)    (阅读:2247)
  5. Canvas高级特性    (阅读:2159)
  6. 使用JavaScript和Canvas开发游戏(三)    (阅读:2092)
  7. 云标签,关键字图排版 html5 canvas版(一)    (阅读:2084)
  8. 使用JavaScript和Canvas开发游戏(五)    (阅读:1806)
  9. 使用JavaScript和Canvas开发游戏(二)    (阅读:1707)
  10. 使用逻辑时钟重述paxos协议    (阅读:1497)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1