WEB程序员笔记

一个前端开发工程师的个人博客

使用React Router对路线过渡进行动画处理

在进行副项目时,我想为用户在路线之间导航时创建漂亮的“ flow” -y动画。路线必须实现不同的“输入”和“离开”动画,具体取决于用户导航到哪个页面和从哪个页面导航,即,从“ 登录”页面导航到“ 首页”时,其动画(“ 登录”页面的离开动画)与“ 登录”动画不同页面到“ 应用程序”页面。

《使用React Router对路线过渡进行动画处理》

最后,我得到了一个很整洁的Provider-and-hook二人组,可以与流行的React Router很好地配合使用,所以我想我可以把它打包好并共享。

看到它住在这里

反应路线转换

因此,反应路线转换是该周末工作的结果。

它的工作方式非常简单。

它导出您需要包装您的应用程序的提供程序(将其放置在react-router的内部Router)。

在幕后,该Provider只是用Context Provider包装其子级(您的应用程序)。它设置了Context Provider,并为其传递了push(history.pushpush它们的useHistory钩子提供的react-router的方法)函数,location(window.location或react-router的usLocation()返回值)和(空)侦听器数组。

由react-route-transition(useTransition()useTransitionHistory())提供的两个钩子将稍后从该上下文读取和写入。

用它包装应用程序后,您可以声明动画的行为。为此,您称为useTransition()钩子。

描述动画

useTransition()接受一个对象,该对象的键名为,handlers其值是Handlers数组。

处理程序是描述以下内容的对象:

  1. 动画
  2. 什么时候开火说动画

处理程序对象由以下键组成:

  • path -一个字符串(或字符串数​​组),用于指定动画函数在输入/离开这些路径时应触发的路径。
  • onEnter-一个异步功能,一旦用户导航到,该功能就会触发path。这是动画代码所在的位置,应该在完成动画后解析。
  • onLeave-和一样onEnter,离开时只会开火path

这是使用示例useTransition()

useTransition({
  handlers: [
    {
      path: '/',
      onEnter: async () => {
        await gsap  // highlight-line
          .timeline()  // highlight-line
          .fromTo( // highlight-line
            '[data-home-main] > *, [data-home-footer]',  // highlight-line
            { opacity: 0, y: 20 },  // highlight-line
            { duration: 0.6, stagger: 0.125, y: 0, opacity: 1 }  // highlight-line
          )  // highlight-line
      },
      onLeave: async () => {
        await gsap.timeline().to('[data-home-main] > *, [data-home-footer]', {
          duration: 0.6,
          stagger: 0.125,
          opacity: 0,
          y: -20,
        })
      },
    },
  ],
})

进入 /启动的OnEnter动画,当离开,开始onLeave

当调用useTransition()卸载的组件时,它注册的处理程序也会被删除,因此不再可见的页面将不会在后台启动动画。

现在,如果您不熟悉gsap,那么它是00年代的老式动画库,仍然非常不错。anime.js是一个不错的轻量级选择。它们都公开了简单的API,使DOM动画变得轻而易举,并且(IMO)比声明性的API更易读(请参见下面的免责声明)。

第一个动画块(突出显示的行)的作用是将数据属性名为的元素home-main 数据属性名为的元素的所有子项变暗(过渡不透明度为0)home-footer。每个动画元素将在600毫秒内进行动画处理,并应用125毫秒的惊人效果。

此类动画的渲染元素可能类似于:

return (
  <div>
    <main data-home-main>{/* this content will be animated */}</main>
    <footer data-home-footer>{/* some stuff here as well */}</footer>
  </div>
)

等待gsap.timeline().to()是指等待动画完成(然后它的返回值即可,动画完成后便会解析)。

现在我们准备看动画播放了。

启动动画

当用户导航到(或从中)需要动画的页面时(在上面的示例中,当用户从和进行动画时),react-route-transition将启动动画/

使用react-route-transition导航页面的方式与react-router相同,方法是调用history.push("/some-path"),不同的是history这里的对象是useTransitionHistory()由react-route-transition提供的钩子返回的内容。

react-route-transition为您处理导航。它导出名为的钩子useTransitionHistory(),接受您要导航到的路径。那个钩子精心编排动画。它遍历已注册的处理程序列表,找到哪个描述onLeave了当前位置的动画,同时启动所有这些动画,等待它们完成,然后调用history.push(反应路由器),这将导致安装新组件并注册其处理程序(可能会或可能不会描述onEnter此新视图的动画)。最后,它onEnter为新位置触发所有动画。

2动画1视图

假设您希望onLeave当用户从“ 登录”页面导航到主页时开始播放一个动画,而当用户从同一“ 登录”页面导航到“ 应用程序”页面时播放一个动画。

您可以通过传递fromto选项而不是传递path选项来实现,例如:

useTransition({
  handlers: [
    {
      from: '/signin',
      to: '/app',
      onLeave: async () => {
        // Animation 1
      },
    },
    {
      from: '/signin',
      to: '/',
      onLeave: async () => {
        // Animation 2
      },
    },
  ],
})

留给何时开始动画1 应用程序页面,动画2留给当主页页面。

最后,pathfromto也接受的路径的阵列。当您想要导航到(或从)多个页面时触发相同的动画时,这很有用。

为什么需要命令式动画?

就个人而言,我不喜欢以声明性的方式编写复杂的动画。它们非常适合交互,但是我发现与以命令方式编写的动画相比,学习曲线陡峭,代码可读性受到影响,玩转(只是测试内容)不如反馈循环会更长。那可能是因为我是作为Flash(ActionScript)开发人员开始的,因为补间动画非常流行,因此不要以为事实。如果您喜欢采用声明式方法,请在下面的评论中让我知道,我很想听听他们的优点!

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注