专栏名称: 奇舞精选
《奇舞精选》是由奇舞团维护的前端技术公众号。除周五外,每天向大家推荐一篇前端相关技术文章,每周五向大家推送汇总周刊内容。
目录
相关文章推荐
数据宝  ·  罕见涨停,机构抢筹1.4亿元 ·  昨天  
有限次重复博弈  ·  点评一下? 有限次重复博弈的微博视频 ... ·  2 天前  
第一财经  ·  超3600只个股上涨! ·  3 天前  
首席商业评论  ·  雷军为何会公开惦念大S? ·  3 天前  
51好读  ›  专栏  ›  奇舞精选

web过渡动画

奇舞精选  · 公众号  ·  · 2024-05-16 18:00

正文

本文作者系360奇舞团前端开发工程师

Web 动画不仅能够提升用户界面的美观度,还能增强用户的交互体验。

在手机app中,经常会见到这种丝滑的交互动画,用来引导用户的视线,使用户更加关注产品的重要信息。这种交互动画在安卓端被称为共享元素动画。通过观察可以发现这种动画的特点,就是在动画前后有一个或者多个相同的元素。
那么在浏览器里前端如何实现这样的动画呢?
通常都会在触发动画的时候新建一个dom结构,计算动画元素的初始状态和最终状态,通过js的animate执行动画。也就是FLIP的思想来实现。这种实现的存在的问题是需要关注有哪些元素参与了动画,动画前后有哪些属性发生了变化,手动计算并应用到元素上。其次还需要保证元素是始终存在页面中,并且还不能实现跨页面的动画过渡。

View Transition

view transition是w3c工作组提出的一个草案,view transition允许你在可视 DOM 改变的两种状态之间添加动画过渡。这些改变的范围可以从向 DOM 添加新元素这样的小更改,到从一个页面导航到另一个页面这样的的大更改。view transition提供了一种简单的方式来实现dom的更改和动画。
目前的浏览器兼容性如下图:

使用view transition可以非常简单的实现共享元素动画,那么接下来看一下view transition的相关内容吧!

View Transition的核心概念

view transition提供了一个js方法:

document.startViewTransition(updateCallback);

通过这个方法可以开启view transition。其中startViewTransition方法接收一个回调函数作为参数,在回调函数updateCallback 里,我们执行变更 DOM 状态的逻辑,比如切换页面路由、更新页面内容等。
下图是没有使用view transiton和使用了view transtion的对比:

在调用了startViewTransition后会得到一个只读的promise对象,这个对象有三个属性,代表了过渡动画中的三个状态节点:
1.  updateCallbackDone: 回调函数执行完毕。
2.  ready:准备完毕即将准备播放动效。
3.  finished:动效执行结束。
这三个属性也都是promise对象,可以使开发者更精准的控制动画的过程。

const withTransitionButton = document.querySelector('.with-transition button');

    withTransitionButton.addEventListener("click"async (e) => {
      
      const vt = document.startViewTransition(() => { 
        const newImage = document.createElement("img");
        newImage.src = "//p5.img.360kuai.com/t01ab608eed52439d4a.jpg";   
        e.target.parentElement.appendChild(newImage);   

        console.log('Update Callback')
      });  
      console.log('View Transition Instance', vt);

      // vt.skipTransition();

      // updateCallback函数执行状态 会在 updateCallback函数执行完时兑现
      await vt.updateCallbackDone;
      console.time('Callback Done');

      // 跳过快照动画,但不会跳过updateCallback函数执行
      vt.skipTransition();

      // 动画是否准备好 会在伪元素树被创建且过渡动画即将开始时兑现
      await vt.ready
      // console.log('Transition Ready');

      // vt.skipTransition();

      // 转场动画是否执行完 会在转场过渡动画完成时兑现
      await vt.finished
      console.log('Transition Finished');
      
    });

返回的promise对象还有一个skipTransition方法,可以跳过动画效果而不影响updatecallback函数的执行。

View Transition背后的运行机制

view transition的API设计非常简单,那么浏览器是如何实现这种过渡动画的呢?
当调用document.startViewTransition方法的时候,浏览器会捕获当前的页面状态作为旧视图,暂停浏览器的渲染,执行updatecallback函数,更新dom,这个时候虽然dom更新了,但是并没有渲染,所以用户看的内容并没有变化。浏览器会再次捕获到当前dom的状态作为新视图。updatecallback执行完后,updateCallbackDone的状态变更。

浏览器会利用刚刚生成的新旧视图,创建一系列伪元素,插入到 html 节点中。旧、新视图,对应着上文提到的两个伪元素:::view-transition-old、::view-transition-new。

之后再恢复渲染,这时用户会看到伪元素渲染的样式,此时的ready状态完成。
浏览器会对这些伪元素执行动画。伪元素的层级是最高的,所以在执行动画的过程中,页面不能进行任何的交互。
动画结束后,添加到页面的伪元素会被浏览器移除。finished状态完成。
(在 W3C 标准文档中,有一个步进式 Demo,可以帮我们更直观地了解生命周期的每个阶段)。

View Transition的视图命明和自定义动画

在核心概念里的demo可以看到view transition的动画是交叉淡化动画,这个是view transition的默认动画。在运行机制里我们了解到view transition是通过伪元素来实现动画的,所以也就支持通过css来自定义动画。
以下面的元素点击后变小删除的demo来看一下view transition如何自定义动画。

html>


  
  
  Document
  


  

  


为了保证动画只作用到删除元素,需要给元素定一个view-transition-name的css属性来命名视图转换。之后就可以用::view-transition-old(box)选择到这个元素的旧状态,并对其设置动画。
当一个页面中有多个命名视图的话,就会产生多组的伪元素结构:

其中视图转换不要求在同一个元素上,可以是不同的元素,但要保证在一个页面中是唯一的。

View Transition的多页面

到目前为止,过渡效果只能在同一文档中实现,但是view transition它允许你在跨不同文档导航时添加过渡。换句话说,你还可以向多页面应用程序添加过渡效果。
要启用这些页面之间的视图转换,你需要做的就是将以下  标记添加到文档的 HTML  中:

"view-transition" content="same-origin">

可以通过这个demo(https://view-transition-demo-crossfade.netlify.app/)来查看效果(在使用chrome的时候需要浏览器版本>111 并且手动启用了view transition的api)

开源框架对View Transition的支持

  1. Astro v2.9 (https://astro.build/blog/astro-290/)
  2. SvelteKit 从1.24 版本,集成了View Transition API (https://svelte.dev/blog/    view-transitions)
  3. Nuxt.js v3.4 将view transition作为实验性功能引入 (https://nuxt.com/blog/v3-4#view-transitions-api-support)
  4. React-router v6.17.0 (https://github.com/remix-run/react-router/blob/main/ CHANGELOG.md#view-transitions-)

总结

创建平滑的页面过渡一直是 Web 开发的目标。View Transitions API 是实现这一目标的一大进步。它允许开发人员在网站上添加有吸引力的动画。



- E N D -


3 6 0 W 3 C E C M A T C 3 9 L e a d e r







请到「今天看啥」查看全文