vue3使用view transitions api 实现跨路由的过度动画效果

762 阅读2分钟

最近kimi用的挺多,kimi的网站也是做的比较简洁优雅,但每次从首页到新对话页面的时候,那个生硬的过度动画就让我产生了疑惑,明明用的是同一个组件吧, 这个:

image.png

这个:

image.png

就不能像app的图标那样做一下过度动画切换吗?

想起来比较简单,但真想实现这样的效果好像也不是很容易,原因可能如下:

  1. 这是两个路由的页面,搜索组件虽然是一样的,但在各自页面的里面生成了两个不同的实例
  2. 想要实现过度就要计算两个组件实例的各自位置,并在路由切换的时候生成一个新的过度组件让它动起来(FLIP动画原理)
  3. 组件的数据需要同步

这时我想到了antfu的**starport**项目,它好像就是做这个工作的。在项目主页,我注意到更新时间在10个月前,还看到了下面的提示:

Note: With the View Transitions API coming to the browsers, you may not this library anymore (even tho it's not a 1:1 replacement as View Transition does not preseve dom and state).

翻译过来就是,浏览器现在有View Transitions API可以一定程度的取代这个库的效果了。具体原理就不介绍了,大家可以点击上面这个链接去看下。

我尝试去使用View Transitions API来实现我想要的这个效果,别说还挺简单的。

在主页home.vue里面,我给chatInput这个输入框组件外部加了一个css属性

<div class="chat-box" >
    <ChatInput></ChatInput>
</div>
.chat-box {
  view-transition-name: chatBox;
}

再在chat这个页面的chatInput作同样的操作

<div class="chat-bottom" >
<ChatInput></ChatInput>
</div>
.chat-bottom {
  view-transition-name: chatBox;
}

注意,view-transition-name一定要设置成一样的。

然后就是施加魔法的代码了

function jumpTo(path) {
  if (document.startViewTransition) {
    document.startViewTransition(() => {
        push({
          path: path,
        });
      });
  } else {
    push({
      path: path,
    });
  }
}

意思就是在路由跳转的时候开启动画过度效果,顺便做下兼容性处理,毕竟新语法兼容性堪忧。

最后来看下效果:

CPT2407251715-1042x806.gif