本文翻译自https://www.sitepoint.com/how...
在本文中,我将介绍Velocity.js
,这是一个快速,高性能的JavaScript动画引擎。当您浏览完所有的demo时,您可以使用Velocity.js创建自己的动画,并使您的网站更具互动性和用户友好性。本文所讲内容不使用jQuery。
Velocity.js功能概览
Velocity.js是一个功能强大的库,它将DOM置于你的指尖!它的动画涵盖:
CSS动画属性的数值,包括颜色
Transform(变换)
SVG属性
滚动事件,相对于页面或页面中的容器元素
淡入淡出动画
一般来说,Velocity一次可以操控一个数值属性值的动画。
例如,如果要沿X和Y坐标移动元素,则不能使用translate['10px', '15px']
。 相反,应该将translate
属性与其相应的轴结合在一起,如:translateX:'10px',translateY:'15px'
。
Velocity有一个功能称为forcefeeding
,它可以让你同时指定两个值。 将在本文后面介绍这个功能。
配置项
Velocity的配置项在制作动画时给予了相当的灵活性。
以下是本文的demo中将会看到的配置项:
Durantion:每个动画持续的时间,测量单位为毫秒。
Easing:Velocity支持大多数的easing类型。
ease
,ease-in
,ease-out
,ease-in-out
,贝塞尔曲线,甚至是很酷的物理弹簧效果。 可以在这个demo中查看弹簧效果:https://codepen.io/mengmengpr...。Loop:动画应该重复的次数。如果将此选项设置为true,它将无限期运行。
Delay:动画开始之前的延迟时长。
全部的配置项可以在Velocity的官网查看,此处也附上Velocity中文网站。
语法
如果你使用jQuery,Velocity.js可以轻松上手。 事实上,Velocity与jQuery具有相同的API:
下载Velocity,引入你的项目,然后将$.animate()
替换成$.velocity()
但是,你也可以不用jQuery来使用Velocity,并且本文中的demo也将不使用jQuery。语法与使用jQuery的方式有所不同:
Velocity(element, {property: value}, {option: optionValue});
要在同一个元素上链接另一个动画,只需在之前的velocity后再添加一个:
Velocity(element1, {property: value}, {option: optionValue});
Velocity(element1, {property: value}, {option: optionValue});
要将动画同时应用于多个元素,只需将所有元素存储到变量中,并将Velocity应用于该变量,无需通过循环实现:
const elements = document.querySelectorAll('<div>');
Velocity(elements, {property: value}, {option: optionValue});
对于选项值单位,你可以使用px,%,rem,em,vw/vh和deg。如果不添加单位,Velocity将提供适当的单位,通常为px。
forcefeeding
功能:传递初始值
这个功能可以让你不用Velocity.js查询DOM以获取元素的初始值,而使用以下语法自行设置:
Velocity(element, {
translateX: [endValue, startValue],
backgroundColor: [endValue, easing, startValue]
}, {
//options here
});
在上面的代码中,translateX
和backgroundColor
分别设置了一个数组:
第一个值代表动画的结束状态。
第二个值(可选)是特定属性的
easing
选项。第三个值即是指定动画的起始状态。
你可以去这里阅读更详细的forcefeeding
。
控制Velocity.js动画
您可以使用以下语法停止,暂停,反向以及恢复元素上的所有Velocity调用:
停止:
Velocity(elem, 'stop')
;暂停:
Velocity(elem, 'pause')
;反向:
Velocity(elem, 'reverse')
;恢复:
Velocity(elem, 'resume')
;
根据这些基本指导,你可以开始进入一些实际的例子。
Demo: 掉落的小球
我们从一个由顶部落下的球开始。
const ball = document.querySelector('.ball');
Velocity(ball, {
translateY: '200px'
}, {
easing: [2000, 15],
durantion: 3000
});
上面的代码选择了一个class为ball的HTML元素,它在Y轴上移动200px,持续3秒。随着小球的下落不断加速,并在最后得到弹性。
你可以使用Velocity的弹簧效果快速实现此功能,通过向velocity的easing
选项传递一个数组:第一个数组项表示张力,第二个表示摩擦。
高张力值会增加总速度和波峰(默认值为500),较低的摩擦值会增加振动速度(默认值为20)。
为了好玩,我们让球的背景颜色从蓝色的初始值变成深色。 要设置背景颜色的初始值,您需要使用Velocity.js的forcefeeding
:
Velocity(ball, {
translateY: '130px',
backgroundColor: ['#222', '#043d99']
}, {
easing: [2000, 15],
duration: '3000'
});
具体实现效果点此看看:
https://codepen.io/mengmengpr...
Demo:按钮控制的弹簧小球
接下来的这个demo,目标是创建一个动画序列:
小球从顶端落下
当小球撞击地面的时候样式有所挤压
当小球反弹回来的时候样式恢复正常
这个动画会一直循环
你可以通过一个按钮控制动画的循环和停止
实现这种动画需要将各种各样的片断连在一起,并使用按钮来整体控制它们的动画。
理想的工具将是一个时间表,它将涵盖所有的片断,并可以控制所有片断的开始和结束。Velocity.js没有原生的时间轴,但有几个解决方案:
使用Tweene - 这是一个动画代理,是一个可以使用很多Javascript动画库的包装器,包括Velocity.js。Tweene需要Velocity使用jQuery,本文未使用jQuery,所以暂不考虑。
JavaScript的
requestAnimationFrame()
。这是一个原生API,用于在浏览器环境中运行任何平滑,高效的动画,例如CSS,画布等。目前除了Opera Mini外,所有主流浏览器都支持。
将片断分割成函数
为了保持代码整洁,可以根据你需要的动画场景构建一个函数。 然后,只需要在主函数中调用这些函数,主函数包含requestAnimationFrame()
方法。
const changeBallPosition = (elem, propVal, easingVal, durationVal) => {
Velocity(elem, {
translateY: propVal
}, {
easing: easingVal,
duration: durationVal
});
};
const changeBallWidth = (elem, propVal, easingVal, durationVal) => {
Velocity(elem, {
scaleX: propVal
}, {
easing: easingVal,
duration: durationVal
});
};
上面的代码片段包含了如何编写ES6箭头函数的示例。
每个函数使用const
关键字存储在常量中。如果需要在整个程序中存储需要更新的值,请改用let
。
可以看到,每个功能都调用了Velocity来让小球进行特定的移动。注意,要移动球并更改其宽度,代码没有分别更改CSS的top
和width
。相反,它改变了translate
和scale
的值,从而带来更好效的动画效果。
下面是有计时器的主函数。在主函数里调用以上函数:
let animationFrameId;
const launchBall = (elem) => {
changeBallPosition(elem, '130px', 'easeInQuart', 300);
changeBallWidth(elem, 1.2, 'linear', 50);
changeBallWidth(elem, 1, 'linear', 50);
changeBallPosition(elem, '-10px', 'easeOutQuart', 300);
changeBallWidth(elem, 1, 'linear', 50);
animationFrameId = requestAnimationFrame(() => {
launchBall(elem);
});
};
注意全局变量animationFrameId
。后面将需要在cancelAnimationFrame()
中用这个变量停止动画。
要使球运动,需要在按钮的点击事件中调用launchBall()
函数,我们需要把小球这个变量传递给函数:
btnPlay.addEventListener('click', function () {
launchBall(ball);
this.enabled = true;
btnStop.disabled = false;
});
注意,在这个点击函数的回调中用了this
关键字,这里的this
指向被点击的按钮。如果使用箭头函数,this
关键字将引用全局的window
对象。简而言之,不要在动态上下文的回调函数中使用箭头函数。
为了让小球停止,需要一个新的函数:
const removeAnimFrame = () => {
if (animationFrameId) {
cancelAnimationFrame(animationFrameID);
}
}
在这里,你通过传递animationFrameId
来调用cancelAnimationFrame()
,animationFrameId
包含一个对小球循环动画的引用。
停止动画的点击事件:
btnStop.addEventListener('click', function () {
removeAnimFrame();
Velocity(ball, 'stop', true);
this.disabled = true;
btnPlay.disabled = false;
});
有趣的是,调用Velocity的stop()
方法时用了一个额外的布尔值。这是清除动画队列所必需的。如果你不用这个参数,点击停止按钮,球不会立即停止动画。等所有排队的Velocity调用完成执行,它才会停止动画。
具体实现效果请看如下demo:
https://codepen.io/mengmengpr...
中文版下已经出炉,点击这里直达。