前言

以前写过相关的文章 angular2 学习笔记 ( animation 动画 )。但在项目种很少用到 Web Animation。

体会不到它的精髓,目前的感觉是,它对比 CSS Animation 更好控制,比如它有 play、pause 这些功能。

缺点就是需要把 Styles 逻辑写到 JS 里,管理可能扣点分数。

参考

MDN – Using the Web Animations API

web animations api

【转载】Web Animation API 从入门到上座

使用Web Animations API让动画效果做加法

定义

先学会用 CSS Animation 再学 Web Animation 会方便很多。

const keyframes: Keyframe[] = [
{ fontSize: '16px', color: 'red', offset: 0 },
{ fontSize: '32px', color: 'yellow', offset: 0.5 },
{ fontSize: '48px', color: 'blue', offset: 1 },
];
const options: KeyframeAnimationOptions = {
duration: 3000,
fill: 'forwards',
easing: 'ease'
}; const animation = h1.animate(keyframes, options);

和 CSS Animation 写法差不多. Keyframes 定义 percentage 和 Style。

注意属性要用 camelCase 哦,比如 fontSize。offset 就是 percentage,CSS 30% 这里就是 0.3。

options 负责 duration、delay、fill 等等. duration 不支持 "100s" 这种写法哦,只可以用 number 表示 millisecond。

另外,easing 的默认是 linear 这和 CSS Animation 默认 ease 不同。

当调用 .animate() 后动画就开始了。

还有一种以 style 属性出发的 keyframes 写法,它长这样:

const keyframes2: PropertyIndexedKeyframes = {
fontSize: ["16px", "32px", "48px"],
color: ["red", "yellow", "blue"],
offset: [0, 0.5, 1],
};

只是换一个写法而已,功能是完全一样的。

pause, play, reverse, cancel, finish, currentTime

pause, play, reverse, cancel 是 Web Animation 常见的操作手法。例子说明:

HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./bundle.js" defer></script>
</head>
<body>
<div class="container">
<div class="box-wrapper">
<div class="box"></div>
</div>
<div class="btn-wrapper">
<button class="play">Play</button>
<button class="pause">Pause</button>
<button class="reverse">Reverse</button>
<button class="cancel">Cancel</button>
</div>
</div>
</body>
</html>

CSS Style

* {
padding: 0;
margin: 0;
box-sizing: border-box;
} body {
display: grid;
place-items: center;
height: 100vh;
.container {
width: 700px;
outline: 1px solid black;
padding: 3rme;
.box-wrapper {
outline: 1px solid black;
.box {
width: 100px;
height: 100px;
background-color: pink;
}
}
.btn-wrapper {
padding-block: 1rem;
display: flex;
gap: 3rem;
justify-content: center;
button {
background-color: pink;
padding: 1rem;
border-width: 0;
cursor: pointer;
display: inline-block;
min-width: 128px;
font-size: 1.5rem;
border-radius: 4px;
}
}
}
}

JavaScript

const box = document.querySelector(".box")!;

let animation = box.animate(
[
{ offset: 0, transform: "translateX(0)" },
{ offset: 1, transform: "translateX(600px)" },
],
{
duration: 3000,
fill: "forwards",
}
);
animation.pause(); document.querySelector(".play")!.addEventListener("click", () => {
animation.play();
}); document.querySelector(".pause")!.addEventListener("click", () => {
animation.pause();
}); document.querySelector(".reverse")!.addEventListener("click", () => {
animation.reverse();
}); document.querySelector(".cancel")!.addEventListener("click", () => {
animation.cancel();
}); animation.addEventListener("finish", () => {
console.log("finish");
}); animation.addEventListener("cancel", () => {
console.log("cancel");
});

长相

Autoplay

当定义好 animation() 后, 它会立刻执行。

pause

定义好后,立刻 pause 它,可以阻止执行。

一旦调用 pause,不管 animation 执行到哪一个环节,它都会立刻停在原地。

play

play 有 2 个用法:

  1. 当 resume 用, 在 pause 之后调用 play, animation 就会 "继续"

  2. 在结束之后, 调用 play, 它有 "re-play" 的效果. (注: 如果 animation 跑到一半, 调用 play 是没有任何效果的哦. 这点和 reverse 不同)

reverse

reverse 有点小复杂。

顺序

首先它改变了 keyframes 执行的顺序,比如例子中是左到右移动,reverse 后就变成右到左。

另外,play 是依赖这个顺序的,所以当 reverse 后,play 的执行顺序也不一样了。

执行

reverse 还带有执行的功能,类似 play 那样,甚至比 play 强。任何时候调用 reverse 都会有效果 (play 在 animation 执行中调用是无效的)

  1. reverse as re-play

  2. reverse as resume

  3. reverse in anytime

    注意看一次调用 reverse, box 从左边跳到了右边, 因为一开始的方向是左到右, reverse 后变成了右到左.

cancel

一调用 cancel,element 就立刻跳回到最开始的原位。

另外 cancel 不会改变顺序,比如调用了 reverse 变成了逆序,再调用 cancel 后它依然是逆序。

finish

调用 finish 方法,animation 会直接跳到结尾的样式,就好像你突然把 duration set 成 0,直接一步到位。

currentTime

currentTime 会返回当前执行的时间 millisecond,比如说 duration 是 10 秒。

console.log(animation.currentTime);

animation 一开始的时候,如果我们 pause,这时 currentTime 会返回 0。

然后我们 play,五秒后 currentTime 会返回 5000。

11 秒后 currentTime 会返回 10000,因为 duration 是 10 秒,所以上限是 10000。

然后我们 cancel,currentTime 会返回 null。

currentTime 除了可以 get,也可以 set。

animation.currentTime = 5000;

它的效果是直接跳去 5 秒后,本来要十秒后才 finish 的,变成只需要 5 秒。

onFinish, onCancel, finished

顾名思义 animation 顺利结束就会触发 finish,如果你 pause 它就不会。resume 之后跑完了就触发。

每一次 re-play / reverse 只要是执行完 finish 都会再触发。

onCancel 只有在调用 cancel() 才会触发,而 cancel() 是不会触发 finish 的。

finished 是 onFinish 的 Promise 版,搭配 async 写起来代码比较整齐。

player.play();
await player.finished;
player.reverse();
await player.finished;
console.log('done');

不过如果要 handle cancel 写起来就未必好看了,它需要使用 try catch

player.play();
try {
await player.finished;
console.log('handle finished');
}
catch {
console.log('handle cancelled');

playbackRate

playbackRate 用来调整 animation 的速度,比如 define 的时候 set duration: 10000 (十秒)。

后来想加快就可以改变 playbackRate 值,比如 10 表示加快十倍,duration 就变成一秒了。

const options: KeyframeAnimationOptions = {
duration: 10000, // 原本是十秒
fill: 'forwards',
};
const player = box.animate(keyframes, options);
player.updatePlaybackRate(10); // 加快十倍

commitStyles

fill: 'forwards' 会 lock 着相关的 styles,这不一定是我们期望的,使用 commitStyles 它会把 animation apply 到 inline styles,

这样我们就可以 cancel animation 释放 'forwards' 的 lock。

const box = document.querySelector<HTMLElement>('.box')!;

const keyframes: Keyframe[] = [{ backgroundColor: 'red' }, { transform: 'translate(100px, 200px)' }];
const options: KeyframeAnimationOptions = {
duration: 3000,
fill: 'forwards',
}; const player = box.animate(keyframes, options);
window.setTimeout(async () => {
player.play();
await player.finished; // 因为 fill 是 forwards 所以 animation styles 会保留但同时会 lock 着
player.commitStyles(); // 把 forwards 的 animation styles apply to inline styles
player.cancel(); // cancel animation unlock forwards
}, 1000);

Composite modes

参考:CSS-Tricks – Additive Animation with the Web Animations API

提醒:Composite modes 目前 IOS 还不支持哦。

有三种 composite modes:

  1. replace (也是默认 mode)

    const box = document.querySelector<HTMLElement>('.box')!;
    box.style.width = '100px';
    box.animate([{ width: '100px', composite: 'replace' }], {
    duration: 1000,
    fill: 'forwards',
    });

    假设我有一个 div,width 是 100px

    animate 也是 set width to 100px

    结果就是什么效果也没有,最终 div 依然是 100px。

  2. add

    box.animate([{ width: '100px', composite: 'add' }], {
    duration: 1000,
    fill: 'forwards',
    // composite: 'add' // 如果全部属性都要 add mode,也可以在这里设置
    });

    把它换成 add mode 就不同了,animation 100px 会加在原本的 100px 之上,

    div 会从 100px 变成 200px,最终 width 是 200px。

  3. accumulate

    accumulate mode 和 add mode 类似,只有在一些特别的属性 (e.g. transform) 上能看出区别。
    首先,我们有一个 box,它被 translateX 50px 然后再 rotate

    const box = document.querySelector<HTMLElement>('.box')!;
    box.style.transform = 'translateX(50px) rotate(45deg)';

    效果

    红框是原本的位置。
    接着我们添加 animation

    box.animate([{ transform: 'translateX(50px)', composite: 'add' }], {
    duration: 1000,
    fill: 'forwards',
    });

    最终 transform 是 translateX(50px) rotate(45deg) translateX(50px)


    改成使用 composite: 'accumulate'

    box.animate([{ transform: 'translateX(50px)', composite: 'accumulate' }], {
    duration: 1000,
    fill: 'forwards',
    });

    最终 transform 是 translateX(100px) rotate(45deg)。

    区别是 add 是在 transform 结尾添加 translateX(50px),而 accumulate 是累加 50px 到原本的 translateX。

    我们知道 transform 是讲究顺序的,上面两句会有不同的执行效果

    add 的执行是:往右边移动 50px -> 旋转 45 度 -> 再移动 50px (由于 rotate 后方向不同了,所以不再是往右边移动,而是往右下方移动)

    accumulate 的执行是:往右边移动 100px -> 旋转 45 度

DOM – Web Animation API的更多相关文章

  1. 【翻译】CSS Animations VS the Web Animations API:案例学习

    原文地址:CSS Animations vs the Web Animations API: A Case Study May 03, 2017 css, javascript 上周我写了我如何使用C ...

  2. Web Animations API (JS动画利器)

    原文地址:→传送门 写在前面 之前学习了CSS animation/setTimeout/setInterval/requestAnimationFrame等,这些都可以用在某种场景下的小动画,也可以 ...

  3. Web NFC API

    W3C Editor's Draft 29 December 2014 This version: http://www.w3.org/2012/nfc/web-api/ Latest publish ...

  4. Web Audio API之手把手教你用web api处理声音信号:可视化音乐demo

    1.Web Audio API 介绍 Web Audio API 提供了在Web上控制音频的一个非常有效通用的系统 ,这些通用系统通俗的讲就是我们可以利用Web Audio API提供的各种方法操作各 ...

  5. html fragment & html template & virtual DOM & web components

    html fragment & html template & virtual DOM https://developer.mozilla.org/en-US/docs/Web/API ...

  6. Web Animations API & SVG & requestAnimationFrame

    Web Animations API WWAPI https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API https:/ ...

  7. 使用Web存储API存取本地数据

    使用Web存储API TODO:本文由 赤石俊哉 翻译整理,您可以将本文自由地用于学习交流.如需用于其他用途请征得作者的同意. 原文链接:Using the Web Storage API - Moz ...

  8. JavaScript入门⑥-WEB浏览器API

    JavaScript入门系列目录 JavaScript入门①-基础知识筑基 JavaScript入门②-函数(1)基础{浅出} JavaScript入门③-函数(2)原理{深入}执行上下文 JavaS ...

  9. JS学习-Web Workers API接口

    Web Workers API接口 通过使用Web Workers,Web应用程序可以在独立于主线程的后台线程中,运行一个脚本操作.这样做的好处是可以在独立线程中执行费时的处理任务,从而允许主线程(通 ...

  10. HTML5权威指南--Web Storage,本地数据库,本地缓存API,Web Sockets API,Geolocation API(简要学习笔记二)

    1.Web Storage HTML5除了Canvas元素之外,还有一个非常重要的功能那就是客户端本地保存数据的Web Storage功能. 以前都是用cookies保存用户名等简单信息.   但是c ...

随机推荐

  1. 常用IDE(开发工具)

    一.开发工具 Visual Studio Microsoft Visual Studio(简称VS)是微软公司提供的IDE,可以在VS上编写C.C++.C#等多种语言的项目,所写的代码适用于微软支持的 ...

  2. oeasy教您玩转vim - 90 - # 语法定义syntax

    ​ 内容查找 grep 回忆 我们这次研究了一下配色方案 murphy虽然配色好看 但是对于java的支持并不好 我们对于murphy进行了修改 增加了String.StorageClass颜色的定义 ...

  3. 改善中国打开GitHub网站的速度

    您可以采取以下措施来改善您在中国打开GitHub网站的速度:1. 使用VPN:通过连接到VPN服务器,您可以避免中国政府对GitHub网站进行的封锁,从而获得更快的访问速度.2. 使用加速器:国内有很 ...

  4. docker 安装 centos8 mysql8 java tomcat

    docker 安装 centos8  mysql8  java tomcat 一,首先在window10系统安装docker,这里就不再描述了. 二,启动docker下载安装centos8镜像 注意: ...

  5. 【MySQL】Windows-5.7.30 解压版 下载安装

    1.Download 下载 mysql官网: https://dev.mysql.com/ 找到download点击进入下载页面: https://dev.mysql.com/downloads/ 找 ...

  6. 家务机器人(人形机器人)—— Mobile ALOHA: Your Housekeeping Robot

    项目地址: https://mobile-aloha.github.io/ 演示视频地址: https://www.youtube.com/watch?v=HaaZ8ss-HP4 论文地址: http ...

  7. 进程的CPU绑定是否有意义 —— 进程的 CPU 亲和性

    好多年前就学习过 进程的 CPU 亲和性这个概念,说直白些就是CPU的进程绑定,也就是指定某个进程绑定到某个CPU核心上,以此提高进程切换时缓存的命中率,加快进程的运算速度. 虽然在编程的时候中会遇到 ...

  8. 国产计算框架mindspore在gpu环境下编译分支r1.3,使用suod权限成功编译并安装,成功运行——(修复部分bug,给出具体编译和安装过程)—— 第二部分:源码编译及编译后文件安装、运行

    前文: 国产计算框架mindspore在gpu环境下编译分支r1.3,使用suod权限成功编译并安装,成功运行--(修复部分bug,给出具体编译和安装过程)-- 第一部分:依赖环境的安装 我们已经进行 ...

  9. 从baselines库的common/vec_env/vec_normalize.py模块看方差的近似计算方法

    在baselines库的common/vec_env/vec_normalize.py中计算方差的调用方法为: RunningMeanStd 同时该计算函数的解释也一并给出了: https://en. ...

  10. .gitignore文件的使用方法(学习总结版)—— .gitignore 文件的配合用法

    本文紧接前文: .gitignore文件的使用方法(学习总结版) ============================================= 本文主要讨论前文中所说的一个操作,即: . ...