复杂web动画,不慌,选择 web Animations API

简介: 说动前端动画,今天说的是第三种 Web Animations API, 也有简称为 WAAPI 的。与纯粹的声明式CSS不同,JavaScript还允许我们动态地将属性值设置为持续时间。 对于构建自定义动画库和创建交互式动画,Web动画API可能是完成工作的完美工具。

1.JPG


前言



说动前端动画,我们熟知的有两种


  1. CSS 动画
  2. (requestAnimation/setTimeout/setInterval + 属性改变) 动画


当然有人可能会说canvas动画,从运动本质了还是第二种。


今天说的是第三种 Web Animations API, 也有简称为 WAAPI 的。


与纯粹的声明式CSS不同,JavaScript还允许我们动态地将属性值设置为持续时间。 对于构建自定义动画库和创建交互式动画,Web动画API可能是完成工作的完美工具。


举两个栗子


落球


点击之后,球体下落

2.JPG

const ballEl = document.querySelector(".ball");
ballEl.addEventListener("click", function () {
            let fallAni = ballEl.animate({
                transform: ['translate(0, 0)', 'translate(20px, 8px)', 'translate(50px, 200px)']
            }, {
                easing: "cubic-bezier(.68,.08,.89,-0.05)",
                duration: 2000,
                fill: "forwards"
            })
});
复制代码


直播的世界消息或者弹幕


这是一个我们项目中一个实际的例子, 直播的弹幕。


我们需要消息先运动到屏幕中间,消息最少需要在停留2秒,如果消息过长,消息还需要 匀速滚动 ,之后再滑出屏幕。


  1. 滑入
  2. 暂停,如果消息过长,消息还需要匀速滚动
  3. 滑出


难点就在于,暂停阶段,消息滚动的时间并不是确定的,需要计算。 这个时候,纯CSS3的动画,难度就有些高了,采用 Web Animations API,天然的和JS亲和,那就简单多了。


先看看效果3.JPG

4.JPG


代码也就简单的分为三段:滑入,暂停,滑出。


因为其天然支持Promise, 代码很简洁,逻辑也很清晰。


async function startAnimate() {
    // 滑入
    const totalWidth = stageWidth + DANMU_WITH;
    const centerX = stageWidth * 0.5 - DANMU_WITH * 0.5;
    const kfsIn = {
        transform: [`translateX(${totalWidth}px)`, `translateX(${centerX}px)`]
    }
    await danmuEl.animate(kfsIn, {
        duration: 2000,
        fill: 'forwards',
        easing: 'ease-out'
    }).finished;
    // 暂停部分
    const contentEl = danmuEl.querySelector(".danmu-content");
    const itemWidth = contentEl.getBoundingClientRect().width;
    const gapWidth = Math.max(0, itemWidth - DANMU_WITH);
    const duration = Math.max(0, Math.floor(gapWidth / 200) * 1000);
    const translateX = duration > 0 ? gapWidth : 0;
    const kfsTxt = {
        transform: [`translateX(0px)`, `translateX(-${gapWidth}px)`]
    };
    await contentEl.animate(kfsTxt, {
        duration,
        delay: 2000,
        fill: 'forwards',
        easing: 'linear',
    }).finished;
    // 滑出
    const kfsOut = {
        transform: [`translateX(${centerX}px)`, `translateX(-${DANMU_WITH}px)`]
    };
    await danmuEl.animate(kfsOut, {
        duration: 2000,
        fill: "forwards",
        easing: 'ease-in'
    }).finished;
    if (danmuEl) {
        stageEl.removeChild(danmuEl);
    }
    isAnimating = false
}
复制代码


web Animations API 两个核心的对象



  1. KeyframeEffect 描述动画属性
  2. Animation 控制播放


KeyframeEffect


描述动画属性的集合,调用keyframesAnimation Effect Timing Properties。 然后可以使用 Animation 构造函数进行播放。


其有三种构建方式,着重看第二种,参数后面说。


new KeyframeEffect(target, keyframes);

new KeyframeEffect(target, keyframes, options)

new KeyframeEffect(source)


当然我们可以显示的去创建 KeyframeEffect, 然后交付给Animation去播放。 但是我们通常不需要这么做, 有更加简单的API, 这就是接后面要说的 Element.animate


看一个KeyframeEffect复用的例子,new KeyframeEffect(kyEffect)基于当前复制,然后多处使用。


const box1ItemEl = document.querySelector(".box1");
const box2ItemEl = document.querySelector(".box2");
const kyEffect = new KeyframeEffect(null, {
    transform: ['translateX(0)', 'translateX(200px)']
},
{ duration: 3000, fill: 'forwards' })
const ky1 = new KeyframeEffect(kyEffect);
ky1.target = box1ItemEl;
const ky2 = new KeyframeEffect(kyEffect);
ky2.target = box2ItemEl;
new Animation(ky1).play();
new Animation(ky2).play();
复制代码

5.JPG


Animation


提供播放控制、动画节点或源的时间轴。 可以接受使用 KeyframeEffect 构造函数创建的对象作为参数。


const box1ItemEl = document.querySelector(".box1");
const kyEffect = new KeyframeEffect(box1ItemEl, {
    transform: ['translateX(0)', 'translateX(200px)']
},
{ duration: 3000, fill: 'forwards' })
const ani1 = new Animation(kyEffect);
ani1.play();
复制代码

6.JPG


常用的方法



Animation 事件监听


监听有两种形式:


  1. event 方式


因其继承于EventTarget,所有依旧有两种形式


animation.onfinish = function() {
  element.remove();
}
animation.addEventListener("finish", function() {
  element.remove();
}
复制代码


  1. Promise形式


animation.finished.then(() =>
  element.remove()
)
复制代码


比如一个很有用的场景,所有动画完成后:


Promise.all( element.getAnimations().map(ani => ani.finished)
 ).then(function() {           
    // do something cool 
  })
复制代码


常用事件回调



便捷的 Element.animate



任何 Element都具备该方法, 其语法:

animate(keyframes, options)


其参数和 new KeyframeEffect(target, keyframes, options)的后两个参数基本一样, 返回的是一个Animation对象。


第一个参数 keyframes


keyframes有两种形式,一种是数组形式,一种是对象形式。


数组形式


一组对象(关键帧) ,由要迭代的属性和值组成。


关键帧的偏移可以通过提供一个offset来指定 ,值必须是在 [0.0, 1.0] 这个区间内,且须升序排列。简单理解就是进度的百分比的小数值。


element.animate([ { opacity: 1 },
                  { opacity: 0.1, offset: 0.7 },
                  { opacity: 0 } ],
                2000);
复制代码


并非所有的关键帧都需要设置offset。 没有指定offset的关键帧将与相邻的关键帧均匀间隔。


对象形式


一个包含key-value键值的对象需要包含动画的属性和要循环变化的值数组


element.animate({
  opacity: [ 0, 0.9, 1 ],
  offset: [ 0, 0.8 ], // [ 0, 0.8, 1 ] 的简写
  easing: [ 'ease-in', 'ease-out' ],
}, 2000);
复制代码


第二个参数 options



new KeyframeEffect(target, keyframes, options)的第三个参数基本一致,但是多了一个可选属性,就是id,用来标记动画,也方便 在Element.getAnimations结果中精确的查找。


参数名 含义
delay 延迟动画开始的毫秒数。默认为0。
direction 动画运动方向
duration 动画每次迭代完成所需的毫秒数。默认为0
easing 动画曲线函数,可以自定义
endDelay 动画结束后要延迟的毫秒数。这主要用于基于另一个动画的结束时间对动画进行排序。默认为0。
fill 动画结束后属性值的状态
iterationStart 描述动画应该在迭代的什么时候开始。0.5表示在第一次迭代中途开始,使用这个值集,一个有两次迭代的动画将在第三次迭代中途结束。默认为0.0
iterations 动画应该重复的次数。默认值为1,也可以取一个值 Infinity,使其在元素存在期间重复。
composite 动画和其他单独的动画之间组合。 这是个高级特性,默认是replace,就是替换提起的动画。
iterationComposite 动画的属性值变化如何在每次动画迭代时累积或相互覆盖


后续四个特性相对高级,掌握好了可以玩出花来,本章主要讲基本知识,后续会出高级版本。


更多细节可以参见 KeyframeEffect


Element.getAnimations



我们通过Element.animate或者创建Animation给Element添加很多动画,通过这个方法可以获得所有Animation的实例。


在需要批量修改参数,或者批量停止动画的时候,那可是大杀器。


比如批量暂停动画:


box1ItemEl.getAnimations()
    .forEach(el=> el.pause()) // 暂停全部动画
复制代码


优势



  1. 相对css动画更加灵活
  2. 相对requestAnimation/setTimeout/setInterval 动画,性能更好,代码更简洁
  3. 天然支持Promise,爽爽爽!!!


你有什么理由拒绝她呢?


对比 CSS Animation



动画参数属性键对照表


Web Animation API CSS
delay animation-delay
duration animation-duration
iterations animation-iteration-count
direction animation-direction
easing animation-timing-function
fill animation-fill-mode


参数设置值上的区别


  1. duration 参数只支持毫秒
  2. 迭代次数无限使用的是 JS的Infinity,不是字符串 "infinite"
  3. 默认动画的贝塞尔是linear,而不是css的ease


兼容性


整体还不错,Safari偏差。

如果不行, 加个垫片 web-animations-js

我们在实际的桌面项目上已经使用,非常灵活, nice!

7.JPG


总结



web Animations API 和 css动画,不是谁替换谁。结合使用,效果更佳。

复杂的逻辑动画,因为web Animations API和JS天然的亲和力,是更优的选择。


写在最后



你的一赞一评就是我前行的最大动力。

技术交流群请到 这里来。 或者添加我的微信 dirge-cloud,一起学习。

相关文章
|
12天前
|
存储 消息中间件 前端开发
Web2py框架下的神秘力量:如何轻松集成第三方API,让你的应用不再孤单!
【8月更文挑战第31天】在开发现代Web应用时,常需集成第三方服务如支付网关、数据存储等。本文将指导你使用Web2py框架无缝接入第三方API。通过实例演示从注册获取API密钥、创建控制器、发送HTTP请求到处理响应的全过程。利用`requests`库与Web2py的内置功能,轻松实现API交互。文章详细介绍了如何编写RESTful控制器,处理API请求及响应,确保数据安全传输。通过本教程,你将学会如何高效整合第三方服务,拓展应用功能。欢迎留言交流心得与建议。
26 1
|
21天前
|
前端开发
HTML+CSS动画实现动感3D卡片墙:现代Web设计的视觉盛宴
HTML+CSS动画实现动感3D卡片墙:现代Web设计的视觉盛宴
|
21天前
|
监控 前端开发 Serverless
现代化 Web 应用构建问题之观测站点的PV、UV和API异常等指标如何解决
现代化 Web 应用构建问题之观测站点的PV、UV和API异常等指标如何解决
26 2
|
28天前
|
XML 开发框架 .NET
ASP.NET Web Api 如何使用 Swagger 管理 API
ASP.NET Web Api 如何使用 Swagger 管理 API
|
1月前
|
缓存 JavaScript API
【颠覆想象!】Vue 3全新Reactivity API:解锁响应式编程的终极奥秘,让你的Web应用瞬间变身超能战士!
【8月更文挑战第12天】Vue 3带来了革新性的响应式系统,基于Proxy技术,提升了性能并提供了强大的API。本文通过示例介绍核心API `reactive` 和 `ref` 的使用,展示如何创建、更新响应式对象与引用,探讨深度响应式、响应式数组的管理,以及如何运用计算属性和侦听器优化应用。此外,还介绍了如何构建自定义响应式逻辑,让开发者能更高效地开发高性能Web应用。
31 1
|
1月前
|
Java API 数据库
【神操作!】Spring Boot打造RESTful API:从零到英雄,只需这几步,让你的Web应用瞬间飞起来!
【8月更文挑战第12天】构建RESTful API是现代Web开发的关键技术之一。Spring Boot因其实现简便且功能强大而深受开发者喜爱。本文以在线图书管理系统为例,展示了如何利用Spring Boot快速构建RESTful API。从项目初始化、实体定义到业务逻辑处理和服务接口实现,一步步引导读者完成API的搭建。通过集成JPA进行数据库操作,以及使用控制器类暴露HTTP端点,最终实现了书籍信息的增删查改功能。此过程不仅高效直观,而且易于维护和扩展。
34 1
|
11天前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
41 0
|
12天前
|
API 网络安全 数据库
Web2py框架如何颠覆传统的RESTful API开发?掌握这些技巧,让你的开发效率飞跃!
【8月更文挑战第31天】Web2py是一款全栈Python Web框架,适用于快速开发复杂交互的Web应用。本文将介绍如何使用Web2py创建RESTful API,包括设置新控制器、定义RESTful路由、处理数据库交互、确保API安全性、编写文档与使用Swagger、测试API以及部署时的注意事项。Web2py的高度抽象和易用性使其成为实现RESTful API的理想选择,帮助开发者专注于业务逻辑而非技术细节。
19 0
|
18天前
|
移动开发 数据挖掘 API
HTML5 中 Web Workers API 的用法
【8月更文挑战第24天】
33 0
|
19天前
|
API
【Azure API 管理】在 Azure API 管理中使用 OAuth 2.0 授权和 Azure AD 保护 Web API 后端,在请求中携带Token访问后报401的错误
【Azure API 管理】在 Azure API 管理中使用 OAuth 2.0 授权和 Azure AD 保护 Web API 后端,在请求中携带Token访问后报401的错误