这篇文章发布于 2024年08月10日,星期六,21:45,归类于 CSS相关, Web综合。 阅读 6049 次, 今日 1 次 3 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11308
本文可全文转载,独立域名个人网站无需授权,但需要保留原作者、出处以及文中链接,任何网站均可摘要聚合,商用请联系授权。
一、先从最简单的案例开始
本文介绍View Transitions API,可以实现类似Keynote里面神奇移动这样的动画效果,也即是浏览器自动识别场景1和场景2的不同,并让这个不同产生动画效果,特别适合复杂的页面级别的场景切换动画。
先从最简单的案例开始。
一、append图片淡出动画
传统方法实现页面插入一个图片并有动画效果,需要用到CSS3 animation定义,例如:
img { animate: fadeIn .2s both; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
container.append(img);
而实现View Transitions API实现则是另外的风格,只需要JS代码,这样:
document.startViewTransition(() => { container.append(img); });
此时图片插入就有淡出效果了,如下视频所示(不动点击播放):
就是这么简单。
眼见为实,您可以狠狠地点击这里:startViewTransition实现图片插入淡入效果demo
二、若要改变动画时间和类型
虽然旧元素淡出,新元素淡入是最常用的动画效果,但是总会遇到需要自定义动画时长和类型的场景。
例如,我们希望图片淡入的时间是1s,或者希望图片append到页面中是放大效果,该如何处理呢?
此时,需要动画CSS属性了,几个专门为View Transitions API设计的CSS伪元素。
例如动画时长1s可以这么设置:
::view-transition-group(root) { animation-duration: 1s; }
或者:
::view-transition-image-pair(root) { animation-duration: 1s; }
或者:
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 1s; }
上面突然出现的4个CSS伪元素估计很多人都看不懂,嗯……我想想,怎么讲才更好理解。
这么说吧,View动画的实现,本质上是新旧快照的diff然后动画。
所以,为了方便设置这些新旧快照的动画特性,就设计了若干全新的CSS伪元素,总共有5个,一起构成了一个伪元素树,其层级关系如下所示:
::view-transition ├─ ::view-transition-group(root) │ └─ ::view-transition-image-pair(root) │ ├─ ::view-transition-old(root) │ └─ ::view-transition-new(root) │ /* 等等... */
其中,root
可以看成是根元素,这个名称是可以自定义的,后面会有说明
然后,动画执行最细枝末节的伪元素就是::view-transition-old
和::view-transition-new
,因此这两个伪元素最为常用,至于其父级的几个伪元素,专门用在设置公共CSS属性的场景下,例如上面设置的动画时长。
动画类型设置
想要改变动画的类型,例如,从淡入效果变成放大效果,很多人会想到使用如下所示的代码:
::view-transition-new(root) { animation: scaleUp 1s; } @keyframes scaleUp { from { transform: scale(0.1); } to { transform: scale(1); } }
然而,图片插入到页面后,出现的不是图片放大,而是整个视窗内容一起放大了,如下所示:
那该如何处理呢?这就需要用到view-transition-name
这个CSS属性了。
三、view-transition-name与局部动画
我们可以使用view-transition-name
属性给任意的元素设置一个名称,此时,就可以将此名称作为参数,以约束::view-transition-old
和::view-transition-new
的作用范围。
例如:
img { view-transition-name: wooo; } ::view-transition-new(wooo) { animation: scaleUp 1s; } @keyframes scaleUp { from { transform: scale(0.1); } to { transform: scale(1); } }
此时IMG插入到页面的时候,就可以看到放大效果了。截图示意:
您可以狠狠地点击这里:::view-transition-new实现图片放大动画demo
需要注意的是,view-transition-name
指定的名称一次只能适用于一个元素,否则会报错,例如下面的错误提示。
因此,如果动画元素多个且重复,稳妥的方式是使用JS去赋予view-transition-name名称,例如:
img.style.viewTransitionName = 'wooo'; document.startViewTransition(() => { this.after(img); setTimeout(() => { img.style.viewTransitionName = ''; }, 1000); });
这样,每一个append的图片都可以有放大显示的效果。
四、看似复杂的动画变得简单了
单个图片的动画并不能体现视区动画的强大,下面通过几个例子演示View Transitions API擅长且推荐做的事情。
案例1:倒序后列表的移动
在过去,在改变列表的顺序的时候,我一直希望可以有动画效果,这样用户才能够直观地看到变化的过程。
可实操下来,太复杂了,除非所有元素都是绝对定位,然后动态修改每一个元素的left,top值。
现在有了View Transitions API,事情就简单多了,因此视图动画他无需设置元素的具体的定位值,它是根据新旧快照前后的位置变化实现的动画效果。
所以事情就变成了:
- 给所有列表元素设置一个唯一的
view-transition-name
; - 执行startViewTransition()然后改变位置;
结束了,就这么两步,非常简单。
无论是DOM位置变化实现的倒序,还是CSS属性在视觉上实现的倒序都可以有动画效果。
如下GIF录屏所示:
眼见为实,您可以狠狠地点击这里:View Transition实现列表倒序动画demo
其中实现的关键要点就是给每个列表设置独立的视图动画名称,此时,浏览器会给每一个元素创建独立的动画组,执行的动画就不是页面级的,而是元素之间的。
案例2:DOM元素remove淡出
在过去,删除某个列表元素,执行DOM.remove()
方法的时候,元素删除效果很生硬,“bang”地一下就没了,一不留神,都没注意刚才删除的是哪个列表。
jQuery里面有个fadeOut()
方法很好用,淡出后元素隐藏。
但是现在都是数据驱动了,数据一变,哗,列表一变,硬邦邦的,fadeOut()
效果想用都用不上。
现在有了View Transitions API,一切都简单了,数据变化(或DOM手动移除),startViewTransition一下,就可以看到元素移出加淡出的效果了,老卵了。
实现也非常简单:
第一步:列表元素设置唯一的view-transition-name
;
第二步:执行类似下面的JS代码。
document.startViewTransition(() => { dom.remove(); });
就有如下所示的删除动效了,简单高效效果还好。
眼见为实,您可以狠狠地点击这里:View Transition实现DOM移除淡出动画demo
五、@view-transition与页面间动画
View Transitions API除了可以用在单页中,也可以用在多页面跳转场景中,实现步骤如下。
页面插入这么一段CSS语句:
@view-transition { navigation: auto; }
然后设置页面之间切换的动画类型,例如:
/* 创建自定义动画 */ @keyframes move-out { from { transform: translateX(0%); } to { transform: translateX(-100%); } } @keyframes move-in { from { transform: translateX(100%); } to { transform: translateX(0%); } } /* 给新旧快照应用动画效果 */ ::view-transition-old(root) { animation: 0.4s ease-in both move-out; } ::view-transition-new(root) { animation: 0.4s ease-in both move-in; }
此时页面间切换,就会像单页页面一样,有滑来滑去的效果了。
就是这么神奇,眼见为实:传统跳转页面变得单页一样滑来滑去demo
六、其他一些说明
View Transitions API还包括pagereveal和pageswap两个事件方法。
前者文档首次呈现时触发,无论是从网络加载新文档还是激活文档(从反向/正向缓存(bfcache)或预渲染器),后者在文档因导航而即将卸载时触发。
可以用来实现一些自定义行为。
好,暂时就说这么多吧,之后有其他新的东西再补充。
感谢阅读,欢迎。
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11308
(本篇完)
- 这啥?CSS calc-size和interpolate-size,真学不动了 (0.692)
- 不能落后,好好缕缕CSS滚动动画 (0.673)
- 分享一个即插即用的私藏缓动动画JS小算法 (0.605)
- URL锚点HTML定位技术机制、应用与问题 (0.395)
- 近期折腾:使用JS以及HTML5实现鑫情动画 (0.327)
- 小tip: CSS3 animation渐进实现点点点等待提示效果 (0.308)
- CSS3实现鸡蛋饼饼图loading等待转转转 (0.308)
- 小tips: 纯CSS实现打字动画效果 (0.308)
- JavaScript实现图片幻灯片滚动播放动画效果 (0.241)
- CSS3+js实现多彩炫酷旋转圆环时钟效果 (0.241)
- 超级强大的SVG SMIL animation动画详解 (RANDOM - 0.131)
可惜移动端不太支持
这玩意目前就chrome在正式版有这个功能,而且之前还在iframe里显示出现过bug(指iframe的view transition不能和外部的view transition同时进行)
safari 目前只有18-TP有这个,效果来看还有点bug
虽然但是,类似功能早在25年前就被 IE 实现了(逃)……
毕竟,用 HTML 实现应用(而不是“页面”)的想法由来已久(但是 IE 在各方面惨败)…… 但直到近年来才变为现实。