[译]NEET 的 CSS 动画演出教程 第一讲

Author Avatar
Equim 2018年3月14日
  • 在其它设备中阅读本文章
Read: 10 minWords: 2,451Last Updated: 18-03-18Written in: AsciiDocLicense: CC-BY-NC-4.0

译者按

我最早认识 yuki540 正是通过他的作品共依存,被里面那些华丽的动画效果所折服,难以相信这竟然完全是 HTML/CSS/JS 实现的,在我眼中简直就是一个淳朴的静画系 MAD,于是就果断勾(p)搭(y)了一波。

据他自己所说,他最初是看到了一些动画的官方网站之后很是喜欢,于是就打开 devtools 一点一点地模仿,这样学习起 HTML 和 CSS 的。

他确实是不会英文呐,所以我也在翻译方面帮了一些忙吧。这次看到他出了有关 CSS 动画的系列教程,很是兴奋,于是赶忙问了一下翻译的事,对方也爽快地答应了。

我原本是想先翻译成英文,再找另一位朋友英译汉的,但是读了部分原文之后感到,对方的语言风格我很难学得来,因此决定先直接翻译到中文。即便如此光是第一讲都还是用了我不少时间。

在这个教程出来之前,我已经自己试着 inspect 了一下他的作品。可以看得出的是,整个动画以 stage 为单位,每个 stage 内部的内部完全由 CSS 实现,然后再由 JS 进行 stage 之间的调度(可能是这样),具体要做起来难度也真的不小。希望我的翻译能将这些技术更进一步地推广开吧。

你说我一个后端怎么翻译起前端的东西来了呢?

开场白

其实我本想完全以 Mirai Akari[1] 的身份来写文章的,但是想到可能会让一些人生气就暂且停下了。↓

我感觉以 NEET 的身份来教学怎么也不会有趣,所以在读教程的时候就请把我当成美少女吧。

好,再来一遍。

哈喽,我是 yuki540 哟!

考虑到这大概很有必要,我会在此讲解迄今为止我所做的 CSS 动画作品中使用到的演出模式[2]

真正要做的其实都可以用简单的 CSS 基础知识来实现,所以我觉得大家在 10 秒内就能理解了吧!

本教程将不会用到 Sass 或 pug 之类的东西,从头到尾完全使用纯 HTML 和 CSS。

那么,现在就赶紧开始吧!

这次的动画

↑ 这次要讲解的演出方式是我经常使用的「幻灯片动画[3]

该演出在共依存中就有用到。考虑到它既简单又灵活,这次我们就一起做做看吧。

讲解

首先让我们看看完成后的效果,是这样的

好,看完了呢。那么就请大家打开编辑器一起写代码吧!

写下标记

首先从基础的 HTML 标记开始。

<main id="root">
  <div id="screen">
    <section class="images">
      <div class="image"></div>
      <div class="image"></div>
      <div class="image"></div>
      <div class="image"></div>
    </section>
    <section class="paint"></section>
  </div>
</main>

一如既往地简单呢。(这个 #root 只是习惯性的)

将其大致分解一下的话

  • #screen 为幻灯片的根基

  • .images 为图片列表的元素

  • .paint 为最初盖住整个幻灯片的元素

(说明得不好请谅解)[4]

赋予样式

写完标记之后,下一步就是为它添加样式了。

首先从 #root#screen 开始。

html, body {
  margin: 0;
  padding: 0;
}
#root {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  min-width: 1100px; min-height: 650px;
  background-color: #eee;
}

#screen {
  position: absolute;
  left: calc(50% - 330px);
  top: calc(50% - 235px);
  width: 650px; height: 450px;
  background-color: #fff;
  border: solid 10px #fff;
  box-shadow: 0 0 20px #444;
  overflow: hidden;
}

将作为全局框架的 #root 扩充到整个画面,然后把 #screen 放置到正中央。

如果你不想用 calc 的话,可以替换成 left: 50%; margin-left: -330px;

接下来是图片列表的样式

.images {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
}

.images .image {
  position: absolute;
  top: 0; left: 0;
  width: 0%; height: 100%;
  overflow: hidden;
}
.images .image:after {
  content: "";
  display: block;
  position: absolute;
  top: 0; left: 0;
  width: 650px; height: 450px;
  background-size: cover;
  background-position: center;
}
.images .image:nth-child(1):after { background-image: url(./images/1.png); }
.images .image:nth-child(2):after { background-image: url(./images/2.png); }
.images .image:nth-child(3):after { background-image: url(./images/3.png); }
.images .image:nth-child(4):after { background-image: url(./images/4.png); }

放进你自己喜欢的 4 张图!

尽管 .images 本身只能适配到 #screen 的大小,但请留意

  • .imagewidth0%

  • .image 含有 overflow: hidden 属性

  • .image:after 的大小是用 px 而不是 % 指定的

这三点。

为了像刚刚的幻灯片那样在更改 width 时保持住里面图片的形状,必须要让 .image 的子元素(因为会很麻烦所以用了虚元素) .image:afterwidth 的值保持不变。

假如我们用 % 来指定大小的话,因为它会适配到父元素(.image)的 width,所以每当父元素(.image)的 width 变化的时候,子元素(.image:after)中的图也会跟着动起来。

20180225101922
Figure 1. 指定 % 的情况

20180225102106
Figure 2. 指定 px 的情况

仅仅指定 px 是不够的。为了在子元素比父元素还大的时候能显示出溢出的部分,还要设定 overflow: hidden 属性。

接着是 .paint 的样式

.paint {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background-color: #444;
}

完啦。.paint 的作用只是在最开始时盖住整体。

添加动画

准备工作已经做好,现在就让我们来做期待已久的动画吧!

大家了解 @keyframes {}animation 的用途与写法吗?

虽然知道的人应该很多,这里还是统一进行一个简单的讲解。

对于 CSS 动画,如果只是想单纯地动一下(比如悬停的时候变一下颜色之类的),一般会用 transition 属性来做,但对于像我个人主页中那样长时间的复杂动画来说就不好使了。

于是 animation 属性就粉墨登场了。

animation 属性是像下面这样子写的。

.demo {
  animation: fadeout 0.5s ease 0s forwards;
}

@keyframes fadeout {
  0% { opacity: 1; }
  100% { opacity: 0; }
}

这是一个让某个页面中的元素在 0.5 秒左右渐渐变成透明然后消失的动画(fadeout)。

animation 属性的各个参数如下。

animation: [关键帧名] [动画长度] [缓冲方式] [动画开始时间] [动画结束后将如何保持属性]

尽管还有很多别的选项,但在这里上面这些就足够了。

然后就是至关重要的 @keyframes {} 了。

它可以通过指定介于 0% ~ 100% 之间(也可用 from to 代替)的属性来创建动画。

可以理解为是动画编辑中的关键帧。通过各个精细的中间点来构成复杂的动画。

如果你还是不太明白的话,可以参考一下这个

.paint 的动画

好。那我们先将把整个幻灯片覆盖住的 .paint 的消去动画做了吧。

@keyframes fadeout_paint {
  0% { /* 初始状态 */
    transform: translate(0, 0) scale(1);
    width: 100%; height: 100%;
    border-radius: 0;
  }
  30% { /* 变成小球状 */
    transform: translate(305px, 205px) scale(1);
    width: 40px; height: 40px;
    border-radius: 50%;
  }
  50% {
    transform: translate(305px, 205px) scale(1.3);
    width: 40px; height: 40px;
    border-radius: 50%;
  }
  70% { /* 像是被绑起来一样地弹动 */
    transform: translate(305px, 205px) scale(1);
    width: 40px; height: 40px;
    border-radius: 50%;
  }
  100% { /* 从左侧出画 */
    transform: translate(-40px, 205px) scale(1);
    width: 40px; height: 40px;
    border-radius: 50%;
  }
}

这个写法稍微复杂了一些,请认真地看一遍。

  • 0% ~ 30% 这段将其变成一个小小的球。

  • 30% ~ 70% 这段轻微地放缩小球的 scale,让它看起来像是被绑着一样。

  • 70% ~ 100% 这段用了 translate 使其从左侧出画。

在使用大量动画的时候,请尽可能多地指定像刚刚那样的 translatescale

接下来,我们将动画注册到 .paint 上。

/*** 画面显现时的动画 ***/
.paint { animation: fadeout_paint 1s ease 0.5s forwards; }

这样就在画面显现 0.5 秒后指定了 1 秒的动画。

然后,使用 forward 来让动画在结束之后保持其在 100% 的状态。

.image 的动画

.image 很简单。让 width 从 0% 开始变化到 100% 即可。

@keyframes show_image {
  0%   { width: 0%; }
  100% { width: 100%; }
}

接着为各个 .image 注册动画。

/*** 幻灯片的动画 ***/
.images .image:nth-child(1) { animation: show_image 0.6s ease 1.5s forwards; }
.images .image:nth-child(2) { animation: show_image 0.6s ease 1.7s forwards; }
.images .image:nth-child(3) { animation: show_image 0.6s ease 1.9s forwards; }
.images .image:nth-child(4) { animation: show_image 0.6s ease 2.1s forwards; }

.paint 的动画结束后,各个 .image 的动画会以 0.2 秒的间隔依次进行。

好!这样就完成了!

请刷新一下浏览器看看效果吧!

是的!完成啦!你真是个天才!

所有的代码都能在这里找到。

结语

我并不会英语,甚至连日语都说不好了。

如果你读起来觉得很累的话还请谅解…[footnote:我翻译得也真的好累啊!也谅解一下我吧!]

如果有「这里好难懂!」或者「希望能说明一下这个!」之类的问题的话,可以来我的 twitter 问我。

做 CSS 动画需要非常用心地去调整 @keyframes,自己的努力也很重要,所以请不停地继续去尝试修改参数吧!

若是能帮助大家对 CSS 动画产生新的认识的话,我真的很高兴!

每周日更新,大概是海螺小姐[5]那样大感觉吧。

下回见!


1. ミライアカリ,中文暂译「未来之光」。是一位虚拟 YouTuber,见ミライアカリとは (ミライアカリとは) [単語記事] - ニコニコ大百科Miraiakari_百度百科
2. 演出パターン。
3. スライドショー,slideshow。
4. 翻译得不好也请谅解(
5. サザエさん。一部有足足七十余年历史的番剧,每周日更新。见海螺小姐 - 维基百科,自由的百科全书

知识共享许可协议
本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。

本文链接:https://ekyu.moe/article/neet-s-css-animation-lecture-1/