Skip to content

看Hilo如何描绘HTML5互动世界——补间动画

jiangC edited this page Apr 21, 2016 · 3 revisions

在电影里或者荧屏上,我们经常看到下面的特写镜头。

_ _

这种特写镜头(除了最后的效果部分)和我们的今天要说的补间动画有些相似。在实际操作时,有些场景下我们没有必要刻画游戏物体每一帧的位置颜色等其他信息。 而是使用一种计算方法,来替我们告诉这些游戏对象在每一帧里应该做怎样的变换。这一类动画我们可以宽泛的称之为补间动画。技术描述上可能很宽泛,比如叫transition,缓动,过渡等等。

有哪些工具和方法

CSS3 transition

CSS3提供transition的方式来对物体做缓动,例如我们想改变一个标签的宽度值:

div
{
	width:100px;
	transition: width linear 2s;  
}

假设一个div元素的当前宽度为300px,我们想让这个div在2秒内做从300px到100px的线性渐变。我们就可以指定一个div的元素的transition 属性值为width,即对物体的宽度做过渡(transition)。

transition 属性是一个简写属性,用于设置四个过渡属性:

transition-property transition-duration transition-timing-function transition-delay

transition-property属性指定了需要对哪些属性做过渡(transition),后文中会提到。transition-duration指定了过渡效果的时间,而 transition-timing-function则指定过渡的计算方式,CSS3可以使用预设的几种过渡函数,也可以直接使用贝塞尔曲线函数。下面是可选的几种枚举值:

描述
linear 规定以相同速度开始至结束的过渡效果(等于 cubic-bezier(0,0,1,1))。
ease-in 规定以慢速开始的过渡效果(等于 cubic-bezier(0.42,0,1,1))。
ease-out 规定以慢速结束的过渡效果(等于 cubic-bezier(0,0,0.58,1))。
ease-in-out 规定以慢速开始和结束的过渡效果(等于 cubic-bezier(0.42,0,0.58,1))。
cubic-bezier(n,n,n,n) 在 cubic-bezier 函数中定义自己的值。可能的值是 0 至 1 之间的数值。

那么触发过渡(transition)的条件是什么呢?可以是css触发:

div:hover
{
	width:300px;
}

也可以使用js来触发:

document.querySelector("div#id").style.width = "300px";

通过任意可能的方式改变div元素的宽度值即可触发这种过渡效果。

另外,如果想延缓动画触发的时间,可以设置transition-delay的值,单位为秒(s)。

利用脚本实现一个补间动画

tween

CSS3的过渡(transition)接口简单,在做一些简单的动画时比较实用。但是在需要一些逻辑控制的场景下,脚本控制更适合游戏动画的逻辑设计。

function easeInCubic(t) {
    return Math.pow(t, 3);
}

var el = document.querySelector('#easeOutCubic');
var t = 0;
var step = 0.01;
var startValue = 0;
var endValue = 100;
function easeIn(){
    t += step;
    var blue = startValue + easeInCubic(t) * (endValue - startValue);
    
    el.style.backgroundColor = 'rgb(100,100,' + blue + ')';
	
    requestAnimationFrame(easeIn);
};

easeIn();

过渡函数

上面的代码描述了缓入(ease-in)的动画效果,实际上是利用了Y= X^3(Cubic) 的部分弧线效果,如下图红线标注部分。

_2016_04_05_16_45_32

示例代码作用对象为UI元素的背景颜色值(Blue), 我们可以控制步长step来控制颜色变化的速度。

easeInCubic 通过控制输入当前(迭代)步长或时间来确定输出值,如下图 :

_2016_04_05_16_46_51

除了Y = X^ 3这条曲线可以模拟出ease-out的效果,诸如 Y = X ^ k 类型的曲线,如Y = X ^ 4(Quart) ,Y = X ^ 5 (Quint),另外,三角函数和指数函数也可以做到类似的效果。过渡函数详细的分类

Alt text

实际上上文提到的CSS3的过渡函数接口cubic-bezier(n,n,n,n) 也是一种过渡函数的表达方式,如下图,P1,P2是2个控制点,两个点的坐标对应cubic-bezier(n,n,n,n)四个参数:

_2016_04_05_17_03_29

cubic-bezier(n,n,n,n)只能设置两个控制点的位置,显然,它能所表达的过渡动画种类不如脚本表达的丰富。

Hilo提供的过渡动画接口

看完CSS3的过渡(transition)接口和原生脚本实现,我们再来看看Hilo里提供的补间动画接口——Tween (点这里查看详细Api文档)

ticker.addTick(Hilo.Tween);//需要把Tween加到ticker里才能使用

var obj = {x:5, y:10, alpha: 0};
Hilo.Tween.to(obj, {
    x:100,
    y:20,
    alpha:0
}, {
    duration:1000,
    delay:500,
    ease:Hilo.Ease.Quad.EaseIn,
    onUpdate: function(ratio,tween){
		console.log(tween.target.x,tween.target.y,tween.target.alpha);
	},
    onComplete:function(){
        console.log("complete");
    }
});

在做过渡动画时,Hilo需找指定一个补间对象,这个对象可以是Hilo的游戏对象,如View类型对象。也可以是普通对象,通过修改普通对象的属性值在onUpdate中间接修改游戏本体对象,如示例代码。

onUpdate会根据ticker的指定的帧率重复执行。在动画完成后onComplete 会被调用。

另外,Hilo的过渡动画可以进行过渡动画组合调用, 使用link就能将一组过渡动画关联起来。

var box1 = boxes[0], box2 = boxes[1];

Tween.to(box1, {y:100}, {
    duration: 1000
}).link(Tween.to(box2, {y:100}, {
    duration: 1000
}));

使用这种关联,我们可以对多个对象做连续的过渡动画。Demo1地址Demo2地址Demo3地址,效果如下图所示:

tween

tween

tween3 (大图,建议打开demo3直接观看)

可被补间动画描述的属性

开题的两组慢镜头,除了镜头后半部分物体发生的形变,前半部分镜头都对运动物体的位置做了缓动。除了位置,我们还会经常对哪些属性做缓动处理呢?

实际上,和尺寸、位置及颜色(color)相关的数值属性都是可以做缓动的。但是CSS3在做过渡动画时会有一些属性限制,而Hilo是可以对所有的属性做过渡动画的。

CSS3 可以做过渡效果的属性:

| 属性名称 | 类型 | | :-------- | --------:| :------: | | background-color | color | | background-image | only gradients | | background-position | percentage, length | | border-bottom-color | color | | border-bottom-width | length | | border-color | color | | border-left-color | color | | border-left-width | length | | border-right-color | color | | border-right-width | length | | border-spacing | length | | border-top-color | color | | border-top-width | length | | border-width | length | | bottom | length, percentage | | color | color | | crop | rectangle | | font-size | length, percentage | | font-weight | number | | grid-* | various | | height | length, percentage | | left | length, percentage | | letter-spacing | length | | line-height | number, length, percentage | | margin-bottom | length | | margin-left | length | | margin-right | length | | margin-top | length | | max-height | length, percentage | | max-width | length, percentage | | min-height | length, percentage | | min-width | length, percentage | | opacity | number | | outline-color | color | | outline-offset | integer | | outline-width | length | | padding-bottom | length | | padding-left | length | | padding-right | length | | padding-top | length | | right | length, percentage | | text-indent | length, percentage | | text-shadow | shadow | | top | length, percentage | | vertical-align | keywords, length, percentage | | visibility | visibility | | width | length, percentage | | word-spacing | length, percentage | | z-index | integer | | zoom | number |

Reference