本文最后更新于 1 年前,文中所描述的信息可能已发生改变。
概述
View Transitions Api View Transitions API 提供了一种机制,可以在更新 DOM 内容的同时,轻松地创建不同 DOM 状态之间的动画过渡。同时还可以在单个步骤中更新 DOM 内容。 ps:不同dom之间的视图过渡
常见的过渡/动画创建方式
- transition/keyframes ( 补间动画,帧动画 )
- requestAnimationFrame ( js 动画,每帧回调 )
- Web Animation Api( 和css动画一样在合成层渲染,js更好的干预和控制 )
- View Transitions Api ( 两个视图或者dom之间的过渡 )
View Transitions Api
过渡的本质是两个屏幕的截图之间的过渡,这两个屏幕截图是两个伪元素,在startViewTransition(callback)
执行时,浏览器截取当前屏幕截图作为旧的视图::view-transition-old
伪元素, 然后执行callback
回调更新dom,更新完成后,截取新的dom视图::view-transition-new
,这两个截图位于屏幕顶层,开始渲染过渡。实际上这个时候截图之下已经完成更新,仅仅是两个伪元素在绘制。
生命周期:
document.startViewTransition(callback)
,开启一个视图过渡- 执行
callback
完成dom更新后,兑现ViewTransition.updateCallbackDone
Promise - 兑现
ViewTransition.ready
Promise,在这个阶段,即将开始动画,可以在这个阶段自定义动画,比如使用Web Animation Api
新建一个动画,附着给::view-transition-new
- 动画结束后,兑现
ViewTransition.finished
Promise
demo1 文字过渡(同一个元素)
- 使用 views-transition-api 针对同一个dom元素,实现元素的过渡,虽然是一个dom,单实际上是两个伪元素的过渡,所以可以针对伪元素做控制,实现动画过渡。
- 当开启视图过渡时,默认使用
view-transition-name:root
这组过渡,是透明度的淡入淡出。所以给一组自定义过渡名称。 - 给旧元素隐藏,新元素附着动画。
code
css:
css
/* 动画 */
@keyframes AAA {
from {
transform: translateY(-50%);
opacity: 0;
}
to {
transform: translateY(0%);
opacity: 1;
}
}
.text {
font-size: 140px;
/* 新的过渡租名称 */
view-transition-name: cc;
}
/* 隐藏旧视图 */
::view-transition-old(cc) {
display: none;
}
/* 新视图附着动画 */
::view-transition-new(cc) {
animation: AAA forwards;
}
::view-transition-old(cc),
::view-transition-new(cc) {
animation-duration: 0.6s;
}
javascript:
javascript
const text = document.querySelector(".text");
let toggle = false;
addEventListener("click", (event) => {
// 开启视图过渡
if (document.startViewTransition) {
const transition = document.startViewTransition(() => {
updateText();
toggle = !toggle;
});
} else {
updateText();
toggle = !toggle;
}
});
const updateText = () => {
text.textContent = Number(text.textContent) + 1;
};
demo2 dom切换 (不同元素)
做一个简易的tab切换,实现两个不同元素之间的过渡,这在其他的实现手段中可能是比较复杂的,但是使用 View Transitions Api
,这会变得异常简单。
code
css:
css
.block1 {
width: 100px;
height: 50px;
border-radius: 10px;
background-color: #ac59bd;
view-transition-name: bb;
display: flex;
padding: 10px;
}
.block2 {
padding: 10px;
width: 100%;
height: 280px;
border-radius: 10px;
background-color: rgb(79, 171, 247);
display: none;
view-transition-name: bb;
}
::view-transition-old(bb),
::view-transition-new(bb) {
height: 100%;
width: 100%;
}
js:
javascript
const block1 = document.querySelector(".block1");
const block2 = document.querySelector(".block2");
let toggle = false;
addEventListener("click", (event) => {
const transition = document.startViewTransition(() => {
updateBlock();
toggle = !toggle;
});
});
const updateBlock = () => {
if (toggle) {
block2.style.display = "none";
block1.style.display = "block";
} else {
block2.style.display = "block";
block1.style.display = "none";
}
};
总结
- 实际上想要页面有一个简单过渡,只需要一行js代码即可:
document.startViewTransition(callback)
,使用默认的淡入淡出 - 更适合两个dom或者页面切换的时候使用
- 本站框架 Valaxy 的主题切换也是基于 View Transitions Api,实现上可参考:主题切换