生动的动画

2016-06-06

BEARYAN

WXG - 基础产品部 - 设计中心 - UI开发一组

什么是动画?

“会动的画面”

如何让静止的画面动起来?

定义每一帧(逐帧动画)

定义关键帧(关键帧动画)

如何让动画更生动?

"Animation" 一词源自于拉丁文字根anima,意思为“灵魂”,动词animate是“赋予生命”的意思。 所以动画也可以理解为使用绘画的手法,创造生命运动的艺术。

Frank Thomas & Ollie Johnston

迪士尼的元老们帮我们总结了动画的十二条动画法则

符合现实

SLOW IN & SLOW OUT
慢进 & 慢出

任何物体自静止开始动作,是渐快的加速运动,从运动状态到静止状态,则是呈渐慢的减速运动

ARCS
弧形运动轨迹

凡任何会动的生物,其组成的任何部分之运动轨迹皆为平滑的弧形曲线

FOLLOW THROUGH & OVERLAPPING
动作惯性 & 动作重叠

没有任何一种物体会突然停止,物体的运动是一个部分接着一个部分的

强调

EXAGGERATION
夸张

利用挤压和伸展的效果、夸大的肢体动作、或是以加快或放慢动作来加乘角色的情绪及反应

SQUASH & STRETCH
挤压 & 拉伸

以特体形状的变形,强调瞬间的物理现角。

ANTICIPATION
预备动作

加入一反向的动作以加强正向动作的张力,
借以表示下一个将要发生的动作。

APPEAL
吸引力

当设计角色时,能够以造型或独特的姿态让观众直觉角色的属性,藉以提高观众对于角色的印象,例如高矮胖瘦可分别代表不同个性的角色。

外界因素

SECONDARY ACTION
附属动作

当角色在进行主要动作时,附属于角色的一些配件,或是触须、尾巴等部分,会以附属动作来点缀主要动作的效果

STAGING
表演及呈像方式

角色的仪态、及表演方式,配合适当的摄影机运动,
使能够有效的表达角色的特性及故事中的讯息

STRAIGHT AHEAD & POSE TO POSE
逐帧画法 & 关键帧画法

前者根据连续的动作依序制作每一格画面;后者是先定义关键的主要动作,而后再制作关键动作间的画格。

TIMING
时间控制

一段动作发生所需的时间,这是掌控动画节奏的最基本观念。

SOLID DRAWINGS
纯熟的手绘技巧

这是在传统手绘动画领域里,对于动画师的基本需要,然而在电脑动画领域,手绘已不再是动画师的工作内容。

符合现实

慢进慢出弧形运动惯性与重叠


强调

夸张、挤压拉伸预备动作、吸引力


外界因素

附属动作、呈像方式、逐帧\关键帧画法时间控制、手绘技巧

与前端的结合

前端动画技术

  • CSS Transition
  • CSS Animation
  • SVG Animation
  • Canvas
  • JS Animation

CSS Transition


.demo img{
left: 0;
transition:
    left .5s ease-in-out,
    transform .5s cubic-bezier(0.68, -0.55, 0.265, 1.55) 1s
;
}
.demo:hover img{
img{
    left: 700px;
    transform: scale(1.5)
}
}
                

timing-function

时间函数

Transition并不适用于做动画

  • 需要事件触发
  • 一次性,不能自动重复
  • 只能定义开始状态和结束状态
  • 一条规则,只能定义一个属性的变化

CSS Animation


.bear-crazy{
animation: bear-crazy 100ms ease-in-out; // name duration timing-function
animation-iteration-count: infinite; // 播放次数
animation-direction: alternate; // 下个周期播放方向,normal
}
                        

keyframes


@keyframes bear-crazy {
10% {
    transform: translate(-10px, -19px) rotate(6deg);
    opacity: 0.47
}
20% {
    transform: translate(-11px, 10px) rotate(5deg);
    opacity: 0.82
}
/* ... */
0%, 100% { /* 0%和100%一致是为了循环 */
    transform: translate(0, 0) rotate(0);
}
}
                        

timing-function是作用于每两关键帧之间



img{
animation: animation-demo2 2s cubic-bezier(0.86, 0, 0.07, 1) infinite alternate;
}
@keyframes animation-demo2{
0%{ transform: translateX(0px); }
50%{ transform: translateX(430px); }
100%{ transform: translateX(850px); }
}
                        

SVG Animation

<path d="M318.0094050899985......" />
<image>
<animateTransform
    attributeName="transform" type="rotate"
    from="0" to="360"
    dur="3s" repeatCount="indefinite"
    calcMode="spline" keyTimes="0;1" keySplines="0.86 0 0.07 1" // timing-function
/>
<animateMotion
    path="M318.0094050899985......"
    dur="3s" repeatCount="indefinite"
    calcMode="spline" keyTimes="0;1" keySplines="0.86 0 0.07 1"
/>
</image>
《超级强大的SVG SMIL animation动画详解》

——张鑫旭

SVG 画线动画

stroke-dasharray

用stroke-dasharray控制着path的实与虚。

<line stroke-dasharray="5, 5"></line>
<line stroke-dasharray="5, 10"></line>
<line stroke-dasharray="10, 5"></line>
<line stroke-dasharray="5, 1"></line>
<line stroke-dasharray="1, 5"></line>
<line stroke-dasharray="0.9"></line>
<line stroke-dasharray="15, 10, 5"></line>
<line stroke-dasharray="15, 10, 5, 10"></line>
<line stroke-dasharray="15, 10, 5, 10, 15"></line>
<line stroke-dasharray="5, 5, 1, 5"></line>

stroke-dashoffset

stroke-dashoffset定义着dash开始的位置

<line stroke-dashoffset="0"></line>
<line stroke-dashoffset="1"></line>
<line stroke-dashoffset="2"></line>
<line stroke-dashoffset="3"></line>
<line stroke-dashoffset="4"></line>
<line stroke-dashoffset="5"></line>
<line stroke-dashoffset="6"></line>
<line stroke-dashoffset="7"></line>
<line stroke-dashoffset="8"></line>
<line stroke-dashoffset="9"></line>

transition + stroke-dashoffset

100 -> 0

100 -> 200

为啥不用负数

在IOS上的表现和Android/PC不一样

DEMO

Canvas

一帧帧地显示,从而实现动画

window.requestAnimationFrame()

API

Canvas画线



var easingFunc = easing.easeInOutCubic; // timing-function
var path2d = new Path2D("M165.50942211 ...");
ctx.setLineDash([pathLength]);
ctx.lineDashOffset = pathLength;

function draw(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.lineDashOffset = parseInt(pathLength * (1 - easingFunc(timePos)));
ctx.stroke(path2d);
requestAnimationFrame(draw);
}
draw();

JS Animation

实现更复杂的timing-function

mo.js

欣赏

链接

较受欢迎的库

SVG/DOM
Velocity.js
SVG.JS
Snap.Svg
Canvas
Create.js
Paper.js
three.js
Phaser.js
Easing
mo.js

Q & A

Thanks!