我想向大家展示如何巧妙地使用 html,CSS 排序动画和 SVG 滤镜把生活中可能最可爱的东西之一 -- 动物画到网页上. 我们将探讨绘制动物的两种技术: 一种使用纯 HTML 和 CSS, 另一种使用内联 SVG 背景图像.
所涉及的动画也很复杂, 因此本教程将重点介绍创建这些动物以及栩栩如生的动作所涉及的不同技术. 放飞你的创意, 自行创作独特和俏皮的动物动画吧.
话不多说, 开始咯!
塑造动物外形
演示使用两种不同的技术来创建动物不同身体部位的形状. 哈士奇使用 CSS border-radius 属性, 狐狸使用内联背景 SVG 图像, 因为后者的形状更复杂.
HTML 标记
两只动物都使用嵌套的 HTML 部分对身体部位进行分组. 分组的概念对于创造逼真的动画效果非常重要 -- 当头部移动时, 眼睛和耳朵也应该保持一起移动, 因为它们是长在头上的.
- <!-- Markup for the fox head -->
- <div class="fox-head">
- <div class="fox-face">
- <div class="fox-ears">
- <div class="fox-ear"></div>
- <div class="fox-ear"></div>
- </div>
- <div class="fox-skull"></div>
- <div class="fox-front"></div>
- <div class="fox-eyes"></div>
- <div class="fox-nose"></div>
- </div>
- </div>
- <!-- Markup for the husky head -->
- <div class="husky-head">
- <div class="husky-ear"></div>
- <div class="husky-ear"></div>
- <div class="husky-face">
- <div class="husky-eye"></div>
- <div class="husky-eye"></div>
- <div class="husky-nose"></div>
- <div class="husky-mouth">
- <div class="husky-lips"></div>
- <div class="husky-tongue"></div>
- </div>
- </div>
- </div>
每个部分均可以独立移动, 并随着其父元素的移动而移动, 这样会产生更逼真的效果. 不知道你发现没有, 尾巴是深深嵌套到其他尾部组件中的. 当每个尾巴部分相对于其母体定位, 然后旋转相同的量时, 就会产生均匀曲线的视觉感.
用 CSS 塑造图形
CSS 的 border-radius 属性大量用来塑造哈士奇的形象. 对于许多元素要素, 需要对每个边界半径进行逐个控制. 例如, 下面是如何构造哈士奇后腿的代码:
- .husky-hind-leg {
- // ...
- border-top-left-radius: 35% 100%;
- border-top-right-radius: 40% 100%;
- }
第一个数字表示曲线从顶部 / 底部边缘开始的深度, 第二个数字表示曲线从左 / 右边缘开始的深度.
其他形状, 如前腿, 不能单独用 border-radius 成形, 需要使用 transform 成形:
- .husky-leg:before {
- transform: skewY(-30deg) skewX(10deg);
- transform-origin: top right;
- }
一旦图形就位, 那么每个元素就能在其父元素中被赋予绝对的基于百分比的位置. 这确保每个身体部位的精确放置以及响应性.
用 SVG 塑造图形
至于狐狸, Sass-SVG 被用来为每个身体部位创建复杂的 SVG 形状. SVG 图像可以用作背景图像, 更好的是, 只要它们是基于 64 或 UTF-8 编码的, 就可以被内联编写(为了最大限度的浏览器支持).
不过, SVG 代码手写起来非常棘手. 我使用 Adobe Illustrator 来创建初始形状:
然后我将每个身体部分保存为 SVG 图像. SVG 代码通过 Sass-SVG 传输到 SCSS 样式表. 例如, 这是狐狸的鼻子:
- .fox-nose:before {
- @include svg((viewBox: (0 0 168 168))) {
- // the nose
- @include svg('path', (
- fill: $color-nose,
- d: 'M83.7,86.7c3.3,0,11.6-3.9,11.6-7.1c0-3.2-9.4-3.2-11.6-3.2c-2.2,0-11.6,0-11.6,3.2 C72.1,82.8,80.4,86.7,83.7,86.7z'
- ));
- // the line connecting the nose to the mouth
- @include svg('path', (
- stroke: $color-nose,
- fill: none,
- d: 'M83.7,102.3V86.7'
- ));
- // the mouth
- @include svg('path', (
- stroke: $color-nose,
- fill: none,
- d: 'M94.5,104.9c0,0-5.2-2.7-10.8-2.7c-5.6,0-10.8,2.7-10.8,2.7'
- ));
- }
- }
这将在 url()中生成一个编码的内联 SVG 字符串, 看起来像这样:
- .fox-nose:before {
- background-image: url("data:image/svg+xml;charset=utf8,
); - }
由于 SVG 是一个背景图像, 因此它可以被转换和动画化, 就像一个 HTML 元素一样. 使用 Sass-SVG,Sass $variables 可用于完全控制 SVG 填充和笔触颜色.
通过内联 SVG 使狐狸响应起来很简单. viewbox 属性值 ((viewBox:(0 0 168 168))) 直接来自 SVG 文件, 但只要保持高 / 宽比率, 那么包含 SVG 背景图像的元素可以是任意大小. 狐狸头部的所有部分都是绝对定位的, 具有与. fox-head 相同的高度和宽度.
"Squigglevision" 和 SVG 滤镜
Squigglevision 是一种通过摆动形状轮廓来模拟手绘动画的动画技术. 这使得像狐狸和哈士奇这样的场景看上去更加动态化和手绘化, 即使动物在不动的时候也是如此.
SVG 有一个称为 < feTurbulence > 的滤镜, 可以给任何应用了此滤镜的地方 "噪声". 结合 < feDisplacementMap > 滤镜以指定像素在每个过滤器中移动的距离.
- <defs>
- <filter id="squiggly-0">
- <feTurbulence id="turbulence" baseFrequency="0.02" numOctaves="3" result="noise" seed="0"/>
- <feDisplacementMap id="displacement" in="SourceGraphic" in2="noise" scale="2" />
- </filter>
- <filter id="squiggly-1">
- <feTurbulence id="turbulence" baseFrequency="0.02" numOctaves="3" result="noise" seed="1"/>
- <feDisplacementMap in="SourceGraphic" in2="noise" scale="3" />
- </filter>
- <filter id="squiggly-2">
- <feTurbulence id="turbulence" baseFrequency="0.02" numOctaves="3" result="noise" seed="2"/>
- <feDisplacementMap in="SourceGraphic" in2="noise" scale="2" />
- </filter>
- <filter id="squiggly-3">
- <feTurbulence id="turbulence" baseFrequency="0.02" numOctaves="3" result="noise" seed="3"/>
- <feDisplacementMap in="SourceGraphic" in2="noise" scale="3" />
- </filter>
- <filter id="squiggly-4">
- <feTurbulence id="turbulence" baseFrequency="0.02" numOctaves="3" result="noise" seed="4"/>
- <feDisplacementMap in="SourceGraphic" in2="noise" scale="1" />
- </filter>
- </defs>
- </svg>
属性的任何元素. 要创建 "squigglevision" 效果, 关键帧动画快速地一次设置一个滤镜
- @keyframes squigglevision {
- 0% {
- -webkit-filter: url('#squiggly-0');
- filter: url('#squiggly-0');
- }
- 25% {
- -webkit-filter: url('#squiggly-1');
- filter: url('#squiggly-1');
- }
- 50% {
- -webkit-filter: url('#squiggly-2');
- filter: url('#squiggly-2');
- }
- 75% {
- -webkit-filter: url('#squiggly-3');
- filter: url('#squiggly-3');
- }
- 100% {
- -webkit-filter: url('#squiggly-4');
- filter: url('#squiggly-4');
- }
- }
注意: 这些 SVG 滤镜目前在 Firefox 中似乎不起作用, 因此可以将这样的滤镜动画视为一种渐进增强处理.
给动物添加动画特效
CSS 关键帧不能为我们提供一种方便的排序和组合动画的方法. 解决这个问题的最好方法是将动画计划 (故事板) 作为时间轴, 并使用预处理器, 如 Sass, 生成关键帧.
例如狐狸, 在概述每个动画应发生的故事板之后, 转换和绝对时间偏移 (秒) 被用于对每个身体部分进行动画处理. 以下是 SCSS 中对狐狸鼻子进行概述的一个例子:
- $animations: (
- // ...
- 'nose': (
- // resting position
- (4s, 5s, 7s): rotateY(-4deg),
- // nose down
- 4.5s: rotateY(-4deg) rotateX(-3deg),
- // fox looks left
- (7.5s, 9s): rotateX(-3deg) rotateY(-28deg) rotateZ(-11deg),
- // fox looks right
- (9.5s, 12s): rotateY(7deg),
- // fox looks straight ahead
- 13s: rotateY(0),
- ),
- // ...
- );
在这里,$animations 是一类 Sass map, 其中键是动画的名称(例如 "nose"). 每个动画名称的值是另一个 map, 其中键是以秒为单位的偏移或偏移列表(例如(7.5s,9s)), 并且值是每个偏移键的 transform 属性.
那么, 我们怎么把这个 map 变成 @keyframe 动画呢? 首先, 设置全局的
animations map 循环为每个动画生成预期的 CSS @keyframe 声明:
- @each $animation-name, $animation in $animations {
- // keyframe declaration
- @keyframes #{$animation-name} {
- @each $offsets, $transform in $animation {
- @each $offset in $offsets {
- // offset declaration block
- #{percentage($offset / $duration)} {
- // transform property
- transform: #{$transform};
- }
- }
- }
- }
- }
这将生成如下所示的关键帧:
- @keyframes nose {
- 14.70588% {
- transform: rotateY(-4deg); }
- 23.52941% {
- transform: rotateY(-4deg); }
- 29.41176% {
- transform: rotateY(-4deg); }
- 41.17647% {
- transform: rotateY(-4deg); }
- 26.47059% {
- transform: rotateY(-4deg) rotateX(-3deg); }
- 44.11765% {
- transform: rotateX(-3deg) rotateY(-28deg) rotateZ(-11deg); }
- 52.94118% {
- transform: rotateX(-3deg) rotateY(-28deg) rotateZ(-11deg); }
- 55.88235% {
- transform: rotateY(7deg); }
- 70.58824% {
- transform: rotateY(7deg); }
- 76.47059% {
- transform: rotateY(0); } }
在不使用 SCSS 的情况下, 这些百分比的计算可能非常繁琐. 它们代表动画的每个步骤中每个所需时间值相对于总 $duration 的百分比偏移量.
然后可以将动画应用于它们各自的身体部位, 例如 animation: nose $duration none infinite;. 每个动画的持续时间都得是一样的, 这样它们可以无缝循环.
逼真的 Easing Curves
制作动画的另一个重要组成部分是看上去要逼真, 所以要为动画的每个部分仔细选择(或创建)Easing Curves. 最为生动的 Easing Curves 是 "正弦曲线"-- 换句话说, 是平滑起伏的 Easing Curves. 这样一来, 自然动作就不会僵硬地起动或停止, animation-timing-function 应该能反映出来.
对于狐狸和哈士奇, 我使用 cubic-bezier(0.645, 0.045, 0.355, 1)(在这里预览). 此曲线 (见下文) 开始略快, 然后平稳地停住. 当然, 最好试验曲线以找到最适合动画的那种.
最后: 在 Chrome 中, 你可以直观地检查所有排序的动画, 以确保它们在正确的时间发生. 你只需打开控制台, 单击 Style 选项卡, 然后单击播放按钮即可:
希望本教程可以帮助启发你创建更多的序列 CSS 动物动画!
自己是一个 6 年的前端开发工程师
这里推荐一下我的前端学习交流扣 qun:784783012 , 里面都是学习前端的, 从最基础的 HTML+CSS+JS[炫酷特效, 游戏, 插件封装, 设计模式] 到移动端 HTML5 的项目实战的学习资料都有整理, 送给每一位前端小伙伴. 2019 最新技术, 从企业招聘人才需求 到怎么学习前端开发, 和学习什么内容都有免费系统分享. 好友都在里面学习交流, 每天都会有大牛定时讲解前端技术!
点击: 加入
来源: http://www.jianshu.com/p/72e541028fdc