CSS 动画实战:使用 CSS3 实现 Apple Watch 上的呼吸灯动画效果

4,358 阅读4分钟
原文链接: svgtrick.com

在Apple watch上新上了一个呼吸灯的应用,主界面有一个呼吸的动画。这篇文章,就来讲讲如何使用CSS来实现下这个呼吸的动画效果,如下图所示:

实现圆圈

第一件事情就是先要实现静态的UI。从上图可以看出整个动画其实是由六个圆圈组成,如果按正常的布局来实现的话,要使用6个div结构。不过如果使用伪元素的话,比如 ::before和::after不仅可以减少div节点,还可以使html结构保持足够的简单。当然我们这里还是按正常的方法来实现。

<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>

然后就来写样式,每个圆的尺寸是125px。因为动画中的每个圆都是彼此叠加的,所以这里需要使用绝对定位来实现UI布局。

.circle {
  border-radius: 50%;
  height: 125px;
  position: absolute;
  transform: translate(0, 0);
  width: 125px;
}

需要注意的是,我们这里使用transform方法中的translate属性来实现动画,比起使用top,right来性能更加高效,动画也更加顺滑。

首先是设置圆圈的背景颜色,先把它设置为白色的背景,然后调整下它的透明度:

body {
  background: #000;
}

.circle {
  background: #fff;
  height: 125px;
  width: 125px;
  border-radius: 50%;
  position: absolute;
  opacity: 0.75;
  transform: translate(0, 0);
}

demo地址

调整布局

到上一步,你会发现,现在圆圈是在视窗的左上角的。按照最初的设想,是要居中显示的。所以,需要在圆圈结构外面加一层结构把它包裹起来,这样就很容易实现居中的视觉效果。

添加一个.watch-face类,宽高和圆圈一样。

<div class="watch-face">
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
</div>

然后使用,flex来实现元素的居中视觉效果。

body {
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

编写动画

在编写动画前,需要花点时间把圆圈定位在它们应该在的位置。这里推荐使用nth-child这个选择器来选择需要定位的元素,这样就不需要给每个元素定义一个类了。

.circle:nth-child(1) {
  transform: translate(-35px, -50px);
}

/* Skipping 2-5 for brevity... */

.circle:nth-child(6) {
  transform: translate(35px, 50px);
}

至于怎么来确定圆圈具体的位置,这个就要自己一点一点来调了,最后的效果如下所示:

demo地址

因为动画也是用transform来做的,所以需要把之前用来布局用的transform移除,一起写入到动画的keyframes中去:

@keyframes circle-1 {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(-35px, -50px);
  }
}

/* And so on... */

因为每一个圆圈的动画都是不一样的,所以我们还是需要使用:nth-child选择器来给每一个圆圈指定对应的动画。

.circle:nth-child(1) {
  animation: circle-1 4s ease alternate infinite;
}

/* And so on... */

需要注意的是animation-timing-function我们指定的是ease,这样可以使动画看起来更加顺滑。animation-direction设置为alternate,这样使动画来回运动。animation-iteration-count设置为inifinite,使动画一直循环播放。

demo地址

修改视觉

基本动画完成,接下里为了和Apple watch中的动画更接近,还需要调整下圆圈的颜色。

从Apple watch中可以看到,左边的圆圈是浅浅的绿色,右边是浅蓝色。选择奇数的圆圈赋予浅绿色,偶数的圆圈赋予浅蓝色。

.circle:nth-child(odd) {
  background: #61bea2;
}

.circle:nth-child(even) {
  background: #529ca0;
}

最后,要记得把之前定义的.circle元素的白色背景颜色删除掉。

demo地址

在文章的评论中,有小伙伴们指出可以使用mix-blend-modescreen来代替opacity。这样可以使圆圈的颜色相互融合在一起。

缩放和旋转动画

还记得我们添加的.watch-face这个结构么?我们就使用它来创建缩放和旋转动画。

@keyframes pulse {
  0% {
    transform: scale(.15) rotate(180deg);
  }
  100% {
    transform: scale(1);
  }
}

然后给.watch-face元素来指定动画。

.watch-face {
  height: 125px;
  width: 125px;
  animation: pulse 4s cubic-bezier(0.5, 0, 0.5, 1) alternate infinite;
}

为了使动画运动起来更加的自然,可以把animation-timing-function的值替换为cubic-bezier曲线。

最后,把代码全部整合起来,就完成了文章开头介绍的动画效果。

demo地址

本文主要是从Recreating the Apple Watch Breathe App Animation这篇文章整理而来,有删减,有疏漏或者理解不到位的地方,还请多多指教!