新鲜的知识又来啦,昨天从信息流刷到 Google 的一个视频,其中提到了 View Transition API,一看效果就是前两年 Android 上面流行的无缝衔接动画,稍微尝试了下效果。
首先,目前这还是一项实验型的技术,只有 Chrome 111+ 才支持,之后 API 也可能会变,并且目前只支持 SPA 应用的跨页动画,据说目标是实现普通网站的跨页动画。
如果真能实现实现普通网站的跨页动画,那么我的博客就可以从首页的列表在跳到详情时,博客的 banner 和 title 都可以产生一个连贯的衔接效果。
主要的核心点是操作时通过调用 startViewTransition
来使浏览器产生一个快照,在回调函数里面执行更新 DOM 操作,最后对比之前保存的快照和更改后的快照来产生动画效果,通过使用相同的 view-transition-name
属性关联动画前后的元素。
浏览器默认实现了一些如淡入淡出,大小或位置变化的动画,如果想要实现一些较复杂的动画,也可以通过使用 animation 来自定义过度动画。
直接上代码:
import './index.css'
import { useRef, useState } from 'react'
import { flushSync } from 'react-dom'
export default function Index () {
const [active, setActive] = useState(true)
const bigImgRef = useRef()
const imgUrl = '/images/child-find.svg'
const handleToggle = () => {
document.startViewTransition(() => {
flushSync(() => {
setActive(!active)
})
})
}
return (
<div>
<div>
<button onClick={handleToggle}>Toggle</button>
</div>
{active && <img
src={imgUrl}
style={{
width: 50,
viewTransitionName: 'name'
}} /> }
{!active && <img
src={imgUrl}
style={{
width: 50,
marginLeft: 200,
viewTransitionName: 'name'
}} />}
</div>
)
}
一个典型的 React 页面,点击按钮切换显示图片,切换时产生了动画过渡效果,视频如下:
然后再实现一个自定义过渡动画的效果:
@keyframes old {
from {
transform: scale(1);
}
to {
transform: scale(1.5);
}
}
@keyframes new {
0% {
transform: rotateZ(45deg);
}
50% {
transform: rotateZ(-45deg);
}
100% {
transform: rotateZ(0deg);
}
}
::view-transition-old(name) {
animation: 1s ease old;
}
::view-transition-new(name) {
animation: 1s 1s ease new;
}
如果你是用的 react 里面的 lazy load, 那么可能无法触发动画效果,因为该回调需要同步方法,异步可能需要加 sleep 来确保内容已经被载入
就目前效果来讲还是有些缺陷的,比如上面视频中,同时存在了两个图层,我首先使用了一个缩放的动画,然后使用了一个抖动的动画,每个动画都产生了一个图层。
目前最佳使用场景是放大,或者移动,因为这样不会产生多图层(或许是我使用的方式不对,目前网上的资料大部分都是 fade 或者 scale 的效果,没有复杂变形的案例)。
如果你是用的 react 里面的 lazy load, 那么可能无法触发动画效果,因为该回调需要同步方法,异步可能需要加 sleep 来确保内容已经被载入
参考链接: