-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CSS Animation Worklet #24
Comments
首先,我们看下 Animation Worklet 是怎么扩展 timelines 的。来看个例子 控制动画的时间线在 index.html 里<div id="demo1"></div>
<script>
if('animationWorklet' in CSS) {
async function init() {
await CSS.animationWorklet.addModule('my_aw.js'); // 加载 Animation Worklet
new WorkletAnimation(
'hellworld', // aw的名字,在my_aw.js里定义的
new KeyframeEffect(
document.querySelector('#demo1'),
[
{
transform: 'translateX(0)'
},
{
transform: 'translateX(500px)'
}
],
{
delay: 2000,
duration: 5000,
iterations: Number.POSITIVE_INFINITY
}
),
document.timeline
).play();
}
init();
}else{
console.warn('您的浏览器暂不支持 Animation Worklet');
}
</script> 每个文档都有个 当调用 在 my_aw.js 里// 定义了一个名字是 hellworld 的 Animation Worklet
registerAnimator('hellworld', class {
animate(currentTime, effect) {
effect.localTime = currentTime;
}
});
在函数体内,我们只是简单的将 |
接下来,我们继续改造代码,来看看在 Animation Worklet 里还能做什么。 自定义时间线在上面的示例中,我们只是通过 animate(currentTime, effect) {
let minIn = -1, maxIn = 1,
minOut = 0, maxOut = 3000; // 映射到时间范围[minOut, maxOut]
let v = Math.sin(currentTime * 2 * Math.PI / maxOut); // Math.sin()
effect.localTime = (v - minIn)/(maxIn - minIn) * (maxOut - minOut) + minOut;
} 传参数Animation Worklet 也支持传参数。具体代码如下: 在 index.html 里 new WorkletAnimation(
'sin',
new KeyframeEffect(...),
document.timeline,
{ maxOut: 5000 } // 1.传参
).play(); 在 my_aw.js 里 registerAnimator('sin', class {
// 2.接收参数 options
constructor(options = {}) {
this.maxOut = options.maxOut || 3000;
}
animate(currentTime, effect) {
let minIn = -1, maxIn = 1,
minOut = 0,
maxOut = this.maxOut; // this.maxOut
let v = Math.sin(currentTime * 2 * Math.PI / maxOut);
effect.localTime = (v - minIn)/(maxIn - minIn) * (maxOut - minOut) + minOut;
}
}); |
有状态的动画之前我们有提到,Animation Worklet(简称 AW)想要解决的关键问题之一就是有状态的动画。也就是说它要能保持住状态。 但是,Worklet 的核心功能之一是它们可以迁移到不同的线程,甚至可以被销毁以节省资源,这样就会破坏 AW 的状态。 为了防止状态丢失,AW 提供了一个钩子,在 Worklet 被销毁之前调用,在那儿可以返回状态对象。等下次再重新创建时,AW 的构造函数会接收到这个状态对象(初始创建时,值是 undefined)。 具体代码如下: registerAnimator('randomspin', class {
// 2. 接收状态参数,第二个参数 state
constructor(options = {}, state = {}) {
this.direction = state.direction || (Math.random() > 0.5 ? 1 : -1);
}
animate(currentTime, effect) {
effect.localTime = 2000 + this.direction * (currentTime % 2000); // this.direction
}
// 1. 钩子函数 destroy(),返回想要保存的状态信息
destroy() {
return {
direction: this.direction
};
}
}); 最终的效果及代码见 animation-worklet-state。每次刷新页面时,动画的方向都是重新生成的。为了让再次刷新页面之后动画的运动方向不变,我们保存了
|
上面介绍的动画都是 time-driven 的,下面我们来看个 scroll-driven 的动画实例。 滚动驱动的动画它的使用非常简单:
具体代码如下: 在 index.html 里 new WorkletAnimation(
'scrollDriven',
new KeyframeEffect(...),
// document.timeline, // 不要它了,换成 ScrollTimeline
new ScrollTimeline({
scrollSource: document.querySelector('#scroll-area'),
orientation: "vertical", // "horizontal" or "vertical".
timeRange: 3000
})
).play();
在 my_aw.js 里 registerAnimator('scrollDriven', class {
animate(currentTime = 0, effect) {
effect.localTime = currentTime;
}
}); 最终的效果是:当滚动文本框时,红色的色块也会跟着动。如下: |
简介
CSS Animation Worklet API 是 CSS Houdini 的一部分。关于 Houdini 的介绍,可查看 #23。
这个 API 扩展了 Web 动画堆栈。具体来说:
举几个例子,大家来感受下什么是 有状态 的动画。
比如 Chrome 的顶部地址栏(点此链接查看动画效果),它的显隐不仅取决于滚动位置,还取决于滚动方向。i.e. 当上拉页面向下滚动时,它就隐藏了;当下拉页面向上滚动时,它又回来了,且不管是否有没有滚动到页面的顶部。
比如视差滚动,目前在 Web 上实现不太容易,详见 Performant Parallaxing。
比如自定义滚动条样式,让猫作为滚动条,要么需要我们自己监听滚动事件,然后还要确保动画流畅又不耗性能;要么实现起来不容易。
有了 Animation Worklet API,我们就可以非常直接且简单地控制此类动画效果了。
https://developers.google.com/web/updates/2018/10/animation-worklet
The text was updated successfully, but these errors were encountered: