译者注:本文内容为 Clocks - CSS Animation 的译文

译者在编写文章过程中写了 一份最终效果(iOS7 风格)源代码 供大家参考

时钟

这是关于时间的。在本文中,我们将接受创建和设置时钟动画的挑战,使用简单的CSS动画和JavaScript来触发它们。

这是我们使用HTML,CSS,SVG背景和一些JavaScript创建的时钟。我们将使用CSS动画或过渡进行任何移动,并依靠JavaScript来设置初始时间并添加基本的CSS变换。

HTML

要开始使用,我们需要一些HTML。

<article class="clock"><div class="hours-container"><div class="hours"></div></div><div class="minutes-container"><div class="minutes"></div></div><div class="seconds-container"><div class="seconds"></div></div>
</article>
复制代码

我最初的方法是为每只指针使用三个元素。然后我回去把每个包装在一个容器元素中。虽然简单的HTML可以用于基本的CSS动画,但是当我们想要定位指针并为它们制作动画时,我们还需要包含元素。

钟面

我们将从一个基本的时钟设计开始,圆脸,简单的小时,分钟和秒针。

.clock {border-radius: 50%;background: #fff url(/images/posts/clocks/ios_clock.svg) no-repeat center;background-size: 88%;height: 20em;padding-bottom: 31%;position: relative;width: 20em;
}.clock.simple:after {background: #000;border-radius: 50%;content: "";position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);width: 5%;height: 5%;z-index: 10;
}
复制代码

你可以在这里获得SVG背景。我还添加了一个伪元素来向中心添加一个纯黑色圆圈。然后可以根据需要将时钟的指针放在该伪元素后面。

我们现在应该有这样的结果。

在添加指针之前,我们需要放置容器。

.minutes-container, .hours-container, .seconds-container {position: absolute;top: 0;right: 0;bottom: 0;left: 0;
}
复制代码

这会将每个容器堆叠在时钟之上。接下来我们创造指针。

时针

每只指针都被赋予absolute属性值并放置在十二点钟位置。我们将从时针开始。

.hours {background: #000;height: 20%;left: 48.75%;position: absolute;top: 30%;transform-origin: 50% 100%;width: 2.5%;
}
复制代码

我正在使用百分比来简化时钟缩放。这是一项复杂的工作,但能让它们更容易适应视图或缩小手机。我们还将transform-origin属性设置为指针的底部,以便以后可以旋转。

分针

分针跟时针类似,但更长更细。

.minutes {background: #000;height: 40%;left: 49%;position: absolute;top: 10%;transform-origin: 50% 100%;width: 2%;
}
复制代码

秒针

秒针再次变细,但也进一步向下设置,使其比中心延伸得更远。为此,transform-origin为80%。这使得20%的手伸出中心。

.seconds {background: #000;height: 45%;left: 49.5%;position: absolute;top: 14%;transform-origin: 50% 80%;width: 1%;z-index: 8;
}
复制代码

动画

停止的时钟每天只能正确两次。让我们添加一些动画来让时钟表现得更像真实的东西。

有些时钟会随着每秒跳跃,通常会产生滴答声。有些时钟会随着手的平稳移动而发出呜呜声。我们两个都试试。首先,我们会让双手平稳移动。

我们可以使用一个keyframe来指示手在360度左右移动(暗示0%的起始位置)。

@keyframes rotate {100% {transform: rotateZ(360deg);}
}
复制代码

如果使用animation属性应用于元素,则此关键帧会告诉元素在360度左右设置动画。我们将在指针上使用linear计时功能,使指针平稳移动。

.hours-container {animation: rotate 43200s infinite linear;
}
.minutes-container {animation: rotate 3600s infinite linear;
}
.seconds-container {animation: rotate 60s infinite linear;
}
复制代码

时针设置为每12小时(43,400秒)旋转一次。分针每小时旋转一次,秒针每分钟旋转一次。

把它放在一起,我们现在有运动!

如果你的眼睛非常敏锐,你甚至可以让分针移动。它需要一个小时才能完成一个旋转,十二个小时的时间来完成它的循环。

秒针需要60秒,因此更容易注意到。

添加停顿

通过让秒针在60个单独的动作中全天候移动,我们可以让指针更像普通时钟。实现此目的的一种简单方法是使用steps计时功能。然后每只指针的animation属性变为:

.minutes-container {animation: rotate 3600s infinite steps(60);
}
.seconds-container {animation: rotate 60s infinite steps(60);
}
复制代码

分针和秒针现在分六步走动。浏览器会自动计算这60个步骤中的每个步骤移动的距离。

正确的时间

一切都很好,时间看起来不错,但准确度如何呢?使用一点JavaScript,我们可以让时间对我们的访问者来说是正确的。这是代码:

/** Starts any clocks using the user's local time* From: cssanimation.rocks/clocks*/
function initLocalClocks() {// Get the local time using JSvar date = new Date;var seconds = date.getSeconds();var minutes = date.getMinutes();var hours = date.getHours();// Create an object with each hand and it's angle in degreesvar hands = [{hand: 'hours',angle: (hours * 30) + (minutes / 2)},{hand: 'minutes',angle: (minutes * 6)},{hand: 'seconds',angle: (seconds * 6)}];// Loop through each of these hands to set their anglefor (var j = 0; j < hands.length; j++) {var elements = document.querySelectorAll('.' + hands[j].hand);for (var k = 0; k < elements.length; k++) {elements[k].style.webkitTransform = 'rotateZ('+ hands[j].angle +'deg)';elements[k].style.transform = 'rotateZ('+ hands[j].angle +'deg)';// If this is a minute hand, note the seconds position (to calculate minute position later)if (hands[j].hand === 'minutes') {elements[k].parentNode.setAttribute('data-second-angle', hands[j + 1].angle);}}}
}
复制代码

此功能将时间(小时,分钟和秒)转换为每只指针的相应角度。然后循环遍历每只手并使用rotateZstyle.transform属性应用该角度。

这适用于除Safari或其他需要前缀的浏览器之外的大多数浏览器。为此,我们还使用了style.webkitTransform属性。

然后,将时钟设置为当前系统时间。

对齐秒针和分针

当首次在屏幕上绘制时钟时,在分针需要移动之前不到一分钟。为了实现这一点,我们可以计算出第一分钟结束的时间并手动轻推分针。由于我们使用JavaScript进行第一次移动,我们可以使用setInterval每分钟继续旋转6度。

在我们移动分针之前,我们需要告知我们当前的分钟数。您可能已经注意到这些线条。

if (hands[j].hand === 'minutes') {elements[k].parentNode.setAttribute('data-second-angle', hands[j + 1].angle);
}
复制代码

这些额外的行检查指针是否是“分钟”指针,如果是,则使用秒针的当前角度设置数据属性。

使用此数据属性集,我们可以使用此数据计算何时移动分针。

/** Set a timeout for the first minute hand movement (less than 1 minute), then rotate it every minute after that*/
function setUpMinuteHands() {// Find out how far into the minute we arevar containers = document.querySelectorAll('.minutes-container');var secondAngle = containers[0].getAttribute("data-second-angle");if (secondAngle > 0) {// Set a timeout until the end of the current minute, to move the handvar delay = (((360 - secondAngle) / 6) + 0.1) * 1000;setTimeout(function() {moveMinuteHands(containers);}, delay);}
}/** Do the first minute's rotation*/
function moveMinuteHands(containers) {for (var i = 0; i < containers.length; i++) {containers[i].style.webkitTransform = 'rotateZ(6deg)';containers[i].style.transform = 'rotateZ(6deg)';}// Then continue with a 60 second intervalsetInterval(function() {for (var i = 0; i < containers.length; i++) {if (containers[i].angle === undefined) {containers[i].angle = 12;} else {containers[i].angle += 6;}containers[i].style.webkitTransform = 'rotateZ('+ containers[i].angle +'deg)';containers[i].style.transform = 'rotateZ('+ containers[i].angle +'deg)';}}, 60000);
}
复制代码

添加弹跳

由于我们现在使用JavaScript来移动分针,我们应该删除动画属性。我们可以用过渡替换它,而不是简单地删除它。这是一个为动画添加更多角色的机会。

当JavaScript为手设置新角度时,元素上的CSS转换将告诉浏览器为此新位置设置动画。这意味着JavaScript只处理简单的角度变化,浏览器可以处理它的动画。

在我们这样做之前,我们应该更新代码以使用JavaScript来移动秒针。让我们使用此代码为秒针容器设置动画,每分钟动画60次。

/** Move the second containers*/
function moveSecondHands() {var containers = document.querySelectorAll('.seconds-container');setInterval(function() {for (var i = 0; i < containers.length; i++) {if (containers[i].angle === undefined) {containers[i].angle = 6;} else {containers[i].angle += 6;}containers[i].style.webkitTransform = 'rotateZ('+ containers[i].angle +'deg)';containers[i].style.transform = 'rotateZ('+ containers[i].angle +'deg)';}}, 1000);
}
复制代码

通过JavaScript处理秒针和分针,更新CSS以使用transitions替换animation属性。

.minutes-container {transition: transform 0.3s cubic-bezier(.4,2.08,.55,.44);
}
.seconds-container {transition: transform 0.2s cubic-bezier(.4,2.08,.55,.44);
}
复制代码

这些转换适用于transform属性并使用cubic-bezier定时函数。这个计时功能让秒针有些反弹。

iOS7 风格

我非常喜欢Apple iOS 7中使用的时钟的简单性。他们已经伸长了指针,但我更喜欢较短的版本。

通过设计针部样式并添加带有数字的背景图像,我们可以轻松创建此外观。

这种设计本身就是Hans Hilfiker对瑞士铁路时钟的演变。通过改变一些样式并添加新的背景图像,我们可以使我们的时钟适应这种风格。

如果您想出其他设计,请告诉我。

使用 Moment.js

我计划这篇文章的第一个想法之一是重建酒店钟表场景,三个时钟显示不同的时区。

调整不同时区的最简单方法是使用令人惊叹的Moment.js 时区库。

您可以在此Codepen上查看代码。

浏览器兼容性

现代浏览器可以处理所涉及的CSS过渡和动画。 IE10 +,最近的Chrome和Firefox支持它们没有前缀,Safari需要-webkit前缀。

不要忘记在JavaScript中使用前缀属性。

(完)

本文作者 Thinker

本文如有错误之处,请留言,我会及时更正

觉得对您有帮助的话就点个赞收藏吧!

欢迎转载或分享,转载时请注明出处

阅读原文

时钟——CSS 动画相关推荐

  1. CSS动画篇之炫酷时钟之时钟墙

    通过CSS制作的时钟大家肯定看到的多了,但是像下面这样的时钟是不是很少见,整个时钟是有很多个小的时钟组合而成,每秒通过多个时钟的动画来切换时间,不得不说这个设计是非常的炫酷且有特色. 前言 看到这个动 ...

  2. 时钟插件-CSS动画+jQuery

    使用HTML,CSS,SVG背景和一些jquery创建的时钟.使用CSS动画和过渡进行移动,使用jquery来设置初始时间并添加基本的CSS变换 最终效果展示 首先创建一个div用来展示生成的时钟 & ...

  3. 前端技术周刊 2019-01-07:CSS 动画

    2019-01-07 前端快爆 Chrome 72 已经进入了 beta 阶段.新增:公有类成员的声明和初始化.一些 DevTools 新功能(可视化性能指标.高亮 text nodes.复制节点的 ...

  4. JavaScript(三十七)——移动端、多媒体、CSS动画

    目录 移动端基础 手机浏览器的内核是什么? 四大浏览器内核优缺点 视口viewport rem 多媒体 视频格式 声音格式 CSS动画 CSS中的动画功能 移动端基础 大纲:视图.rem布局.媒体查询 ...

  5. 【前端知识点总结】CSS 基础六 - 常见的CSS动画

    空间(3d)转换 tramsform: 值 ; 移动 tramsform:translate3d(x,y,z); 添加位移属性 transform: translate3d(x轴, y轴, z轴); ...

  6. css动画(详解带图)

    css动画 过渡 过渡 (transition)的作用 常用属性 实例 动画 动画的简介 设置关键帧 动画常用属性 实例 变形 变形(transform)的简介 常用属性(transform) Z轴平 ...

  7. CSS动画效果无限循环放大缩小

    效果图: CSS动画效果无限循环放大缩小 <image class="anima" mode="widthFix" @click="nav&qu ...

  8. 【译】CSS动画 vs JS动画

    原文地址 目前有两个主流的方法在web上创建动画:使用CSS或JS.到底选择哪种方法来实现动画,完全取决于你的项目以及你想要达到的效果. tips: 对于简单的只出现一次的过渡效果,可以采用CSS动画 ...

  9. Vue 中 CSS 动画原理

    下面这段代码,是点击按钮实现hello world显示与隐藏 <div id="root"><div v-if="show">hello ...

最新文章

  1. 物体检测丨从R-CNN到Mask R-CNN
  2. ntfs分配单元大小_万字长文图解 Go 内存管理分析:工具、分配和回收原理
  3. Bootstrap-组件-1
  4. mysql中如何将一个表中的部分记录合并,mysql - 如何从一个表中获取所有产品并从另一个包含多行的表中合并一行? - SO中文参考 - www.soinside.com...
  5. exawear能运行java_VirSCAN.org-多引擎在线病毒扫描网 v1.02,当前支持 47 款杀毒引擎...
  6. PIE工程师是做什么的
  7. 国家开放大学计算机网络技术毕业设计,精编国家开放大学毕业论文:购物网站设计...
  8. oracle用exp定时备份数据库,oracle exp备份数据库
  9. 解析大数据智能分析平台开发
  10. 文档在线翻译网站汇总
  11. io.fabric8.docker-maven-plugin插件使用
  12. 雷蛇公布2018年全年业绩:营收达7.1亿美元 净亏损9790万美元
  13. 老扎克伯格的四位儿女全是人生赢家,到底是怎么教的?
  14. 2023华为机考刷题指南:八周机考速通车
  15. 在 IDEA 中的各种调试技巧,轻松定位 Bug(超级全面)
  16. 《权力的游戏》Python探索性分析
  17. 包含第k元素LIS(dp)
  18. Apache服务器访问权限设置
  19. E+H雷达液位计做干扰抑制曲线(mapping)方法
  20. 不想打工了,手头上仅有5万元,想回农村做养殖,能养什么?

热门文章

  1. 降噪耳机哪个牌子好?2022年高性价比降噪蓝牙耳机
  2. 新法规下,化妆品生产厂商如何构建化妆品ERP系统?
  3. brk16_Linux进程分配内存的两种方式--brk() 和mmap()
  4. 学3D游戏建模真正需要掌握的美术基础,错过血亏!
  5. android中cmd环境怎么安装,如何在CMD中安装ADB命令
  6. 网上开具个人所得税纳税记录
  7. Android捷径接口,捷径接口
  8. myclub对阵计算机等级提示,TOPICS | PES - PRO EVOLUTION SOCCER 2019 Official Site
  9. 最新黄岛主·公众号流量主变现副业项目2.0全套课(完整版)
  10. 一文讲懂SQL分组子句GROUP BY