用 CSS3 和 jQuery 制作老式时钟

Avatar of Toby Pitman
Toby Pitman

DigitalOcean 为您的旅程的每个阶段提供云产品。立即开始使用 价值 $200 的免费积分!

大家好,我叫 Toby Pitman,Chris 让我写一篇关于我前段时间在论坛上发布的一项实验的文章。这一切都是从我浏览 WebKit 博客 开始的,我 看到一篇关于 新的 CSS3 动画的文章,其中最吸引我眼球的是“旋转”动画。我开始思考,在网页上你能旋转什么东西(这可是十倍于动画 GIF 的效果!)。然后我灵机一动 - 时钟的指针会旋转! bingo!

CSS3 transform: rotate

transform: rotate; 是 CSS 3 的一项新功能,它可以让你... 好吧,旋转东西。Transform 还可以让你缩放、倾斜和平移(移动)网页上的对象。所有这些都可以通过 Transition 属性进行动画化(包括缓动和持续时间)。

听起来很熟悉?这确实应该很熟悉,因为我们现在正在使用 jQuery 等框架来为网页上的元素添加动画。与 jQuery 一样,你可以使用 Transition 为几乎任何值得动画化的 CSS 属性添加动画。想想 :hover 效果,你应该就能得到一些想法。它远没有 jQuery 或 Mootools 等框架强大,但仍然可以实现一些很酷的效果。我敢肯定 John Resig 不会为此失眠的!

重要提示: 此演示仅在 Firefox 3.1+ 和 Safari 3+(以及其他基于现代 WebKit 的浏览器,如 Chrome)中有效。

而且,它永远不会在 IE6 中起作用... 好的,我们开始吧!

查看演示 下载文件

图形

首先,我们需要一些图形来制作我们的时钟界面。我们有一个表盘和三根指针。所有活动部件都在 Photoshop 中以 600px 高度和 30px 宽度进行了切片,并且垂直居中,因为默认情况下,rotate 属性会从元素的中心“旋转”。如果你想设置旋转点,可以使用“transform-origin”。

我在这里使用了一个通用的时钟样式,但如果你喜欢,也可以选择使用米老鼠时钟。所有活动部件都是 PNG 图片,这使得这种效果成为可能。

HTML 标记

时钟的标记是一个简单的无序列表。每个列表项都包含一个活动部件,并赋予一个相关的 id。这里就是它。

<ul id="clock">	
  <li id="sec"></li>
  <li id="hour"></li>
  <li id="min"></li>
</ul>

注意: 论坛帖子 中的标记略显笨拙,因为它在指针上具有真实的投影。我已经为这个演示精简了一些代码,而论坛上的代码保持原样。

CSS

#clock {
  position: relative;
  width: 600px;
  height: 600px;
  margin: 20px auto 0 auto;
  background: url(clockface.jpg);
  list-style: none;
}

#sec, #min, #hour {
  position: absolute;
  width: 30px;
  height: 600px;
  top: 0px;
  left: 285px;
}

#sec {
  background: url(sechand.png);
  z-index: 3;
}
   
#min {
  background: url(minhand.png);
  z-index: 2;
}
   
#hour {
  background: url(hourhand.png);
  z-index: 1;
}

CSS 也非常简单。由于活动部件具有相同的尺寸和起始位置,我们可以将它们一起声明,避免重复自己,使 CSS 更简洁。<ul> 被赋予了相对定位,允许我们在其中绝对定位时钟指针。

注意: 旋转不会影响布局,旋转后的对象会像一个绝对定位的元素一样,脱离正常文档流。

那么 CSS3 相关的内容在哪里呢?嗯,我们将使用一些简单的 jQuery 来应用它。

jQuery JavaScript

  1. 获取时钟的计时信息。
  2. 计算并注入每个元素的 CSS 样式(旋转角度)。
  3. 定期更新 CSS 样式信息。

需要注意的是,jQuery 在使用这些新的 CSS3 属性方面没有任何问题。此外,由于样式是动态分配的,而不是从样式表中分配的,因此此时钟仍然符合 CSS2.1 的验证标准!

获取时间

你们中有些人(我之前就是!),可能会将日期和时间信息与 PHP 等同起来,当我开始做这个项目时,PHP 是我的第一个想法,但后来我发现 JavaScript 也有自己的内置功能来获取日期和时间数据。请注意,在 JavaScript 中,时间是本地机器时间,而不是服务器时间。

我们将使用 Date() 语法来获取此信息,并将其分配给一个变量。我们可以通过将 GetSeconds()GetMinutes()GetHours() 附加到 Date() 语法来获取每根指针的特定数据,例如以下示例。

var seconds = new Date().getSeconds();

上面的代码将返回一个介于 0 到 59 之间的数字,并将其存储在变量“seconds”中。

获取角度

接下来,我们要计算每根指针的角度。对于秒针和分针,它们每旋转一周有 60 个刻度,我们只需将 360 除以 60,得到 6。这意味着,对于每秒或每分钟,我们都需要将指针旋转 6 度。我们将把这个公式存储在另一个变量中。对于秒针,它将如下所示。

var sdegree = seconds * 6;

时针的场景有所不同。因为它每旋转一周有 12 个刻度,所以每个小时的角度是 30 度。即 360/12=30。现在,如果时钟的时针以小时为单位移动,那就简单了,但事实并非如此。它是根据分钟值以更小的幅度移动的。比如 4:30 时,时针将位于 3 和 4 之间的中间位置。那么我们该如何实现呢?以下是代码。

var hdegree = hours * 30 + (mins / 2);

基本上,我们将加上当前分钟数除以 2 的结果,这将得到一个介于 0.5 到 29.5 之间的数字(“rotate”可以处理所有浮点数),这将使指针位于任意给定的 30 度(小时)刻度之间。

示例

2.40 将是   2 * 30 = 60 度
  + 40 / 2 = 20 度
    ——— ———-
    hdegree = 80 度

我以为时钟在超过 12 时会爆炸,因为它会超过 360,但它运行正常。

所以现在我们已经弄清楚了数学运算,让我们注入新的 CSS。

设置样式

以下是用样式表表示的 CSS3 旋转。

#sec {
   -webkit-transform: rotate(45deg);
   -moz-transform: rotate(45deg);
   -ms-transform: rotate(45deg);
   -o-transform: rotate(45deg);
   transform: rotate(45deg);
}

以下是 jQuery 注入的代码(注意:从 jQuery 1.8 开始,在使用 .css() 函数时会自动应用正确的供应商前缀。旧版本的 jQuery 需要手动应用前缀)。

$("#sec").css({
  "transform": "rotate(45deg)"
});

我们在这里遇到的问题是将变量“sdegree”(它保存我们的角度)放到这个语法中,以替换 (45deg)。起初,我只是尝试将变量放在括号之间,但它无法识别。为了使它起作用,我们需要在另一个名为“srotate”的变量中构建一个“字符串”,并完全替换第二个参数。以下是我们实现它的方法。

var srotate = "rotate(" + sdegree + "deg)";

现在 jQuery 将被写入为以下代码。

$("#sec").css({ "transform": srotate });

将所有内容组合在一起(及时!)

整个 jQuery 代码如下所示。

$(function() {
 
      setInterval( function() {
      var seconds = new Date().getSeconds();
      var sdegree = seconds * 6;
      var srotate = "rotate(" + sdegree + "deg)";
      
      $("#sec").css({ "transform": srotate });
          
      }, 1000 );
      
      setInterval( function() {
      var hours = new Date().getHours();
      var mins = new Date().getMinutes();
      var hdegree = hours * 30 + (mins / 2);
      var hrotate = "rotate(" + hdegree + "deg)";
      
      $("#hour").css({ "transform": hrotate});
          
      }, 1000 );

      setInterval( function() {
      var mins = new Date().getMinutes();
      var mdegree = mins * 6;
      var mrotate = "rotate(" + mdegree + "deg)";
      
      $("#min").css({ "transform" : mrotate });
          
      }, 1000 );
 
});

请注意,我们使用了 JavaScript setInterval,因此该函数每秒钟运行一次。获取时间数据的变量必须位于函数内部,这样它们才能更新。否则,它们只会加载页面时获取一次数据,这将导致一个非常糟糕的时钟。

我们的时钟现在应该可以工作了(在 Safari 和其他现代浏览器中)。

其他方案

Flash 是最明显的选项,但如果你没有 ActionScript 技术,我建议你放弃它。这甚至可以通过 PHP 使用 GD 图像库来旋转指针来实现,但这对我来说太难了。

顺便说一下,Soh Tanaka 在几天后偶然发布了这个:CSS 时钟。他的时钟使用 JavaScript 添加类和精灵图像来表示指针。

**更新 2012 年 11 月:**Daniel Bakan 有一篇非常类似的文章,“如何为 iOS 设备编写全屏 Web 应用程序”,其中他也制作了一个老式时钟。如果你对此非常感兴趣,那也值得一看。

结论

所以这就是它了,朋友们,新的 CSS3 属性 transform:rotate 的一个真正的(也许是唯一的)实际应用。我个人迫不及待地想要看到上下颠倒和左右颠倒的网站(是的,你甚至可以旋转 HTML 标签!虽然 看看这对 Safari 的影响)以及我最喜欢的旋转/缩放漫画报纸博客帖子。

所以,继续吧,尝试一些新的 CSS3 功能!