一、简介
View Transitions 目前是一门实验性的技术,在部分浏览器中已经实现,它的 API提供了一种机制,可以轻松地在不同 DOM 状态之间创建动画转换,同时还可以一步更新 DOM 内容。以下是 View Transitions 解决的核心问题:
- 处理新旧内容的加载和定位。
- 对旧状态和新状态进行动画处理以创建过渡。
- 防止用户与旧内容的意外交互导致问题。
- 转换完成后删除旧内容。
二、兼容性
目前在 chrome 内核的浏览器支持的比较好。
三、js-api
js 相关的实例属性和实例方法
- const vt = document.startViewTransition(callback)
- vt.finished
- vt.Experimental
- vt.ready
- vt.skipTransition()
callback 中可以做 dom 相关的操作
四、css-api
css
figcaption {
view-transition-name: figure-caption;
}
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.5s;
}
五、基础示例
在 原生 Js 中使用时判断 document.startViewTransition
是否存在,不存在直接执行相关的 dom 操作,并且返回,存在的话在其 startViewTransition 回调函数中 进行 dom 擦作
ts
const domOP = () => {
if (!document.startViewTransition) {
// domOp 降级用法
return;
}
document.startViewTransition(() => {
// dom op
});
};
六、与 css 动画配合
css
view-transition-name: box;
@keyframes box-out {
from {
transform: rotateX(0);
opacity: 1;
}
to {
transform: rotateX(180deg);
opacity: 0;
}
}
@keyframes box-in {
from {
transform: rotateX(180deg);
opacity: 0;
}
to {
transform: rotateX(0);
opacity: 1;
}
}
::view-transition-old(box) {
animation-name: box-out;
}
::view-transition-new(box) {
animation-name: box-in;
}
七、 伪元素树
ruby
::view-transition
└─ ::view-transition-group(root)
└─ ::view-transition-image-pair(root)
├─ ::view-transition-old(root)
└─ ::view-transition-new(root)
view 有自己的特殊元素树结构。
八、在 React 中使用
React 中直接使用 document.startViewTransition 函数,创建 ViewTransition 过渡:
tsx
export default function Index() {
const [show, setShow] = useState(false);
return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
<h1>Welcome to Remix</h1>
<button onClick={() => {
// setShow(!show)
document.startViewTransition(() => {
setShow(!show)
})
}}>toggle show</button>
{
show ? <div>this is show</div> : <div>this is not show</div>
}
</div>
);
}
在 startViewTransition 回调函数中,通过状态控制 dom 的渲染,达到 ViewTransition 的
九、在 react-router 中使用
- 属性:unstable_viewTransition
- 钩子函数:unstable_useViewTransitionState
ts
import { unstable_useViewTransitionState, Link } from 'react-router-dom'
export function NavImage({ src, alt }: { src: string; alt: string }) {
const vt = unstable_useViewTransitionState('/img');
return (
<Link to='/img' unstable_viewTransition>
<img
src={src}
alt={alt}
style={{
viewTransitionName: vt ? "image-expand" : "",
}}
/>
</Link>
);
}
十、在 remix 中使用
- navigate 导航
- submit 提交数据
- Link 组件
ts
import { Link } from "@remix-run/react";
<Link to={to} unstable_viewTransition> Click me </Link>
- NavLink 组件
ts
import { NavLink } from "@remix-run/react";
<NavLink to={to} unstable_viewTransition>
<p>Image Number {idx}</p>
<img src={src} alt={`Img ${idx}`} />
</NavLink>
- Form 组件
ts
import { Form } from "@remix-run/react";
<Form unstable_viewTransition>
<input type="text" />
</Form>
十一、其他 Astro
- Astro 中也直接支持了
View Transitions API
, Astro 提供了一个<ViewTransitions />
路由组件,可以添加到单个页面的<head>
中,以控制页面在导航到另一个页面时的过渡效果。
十二、小结
本文主要讲解了实验性的 View Transitions API 简单使用教程,从原生 JS 中的用法到 React,然后到 React Router 以及 Remix 对其的支持。不仅仅在 React 技术栈,在 Astro 中也实现此功能,View Transitions 实用程度比较好,尤其是在路由过渡的时候,本探究入门,复杂的交互效果需要更加深入的探索。