You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js+Framer Motion:监听Link跳转提前移除动画类的方法

解决方案:在Next.js路由跳转前移除动画类

你的问题出在useEffect监听asPath是路由完成变化后才触发状态更新,所以动画会短暂执行。要解决这个问题,需要在路由跳转开始前就移除动画类,具体可以通过自定义拦截跳转的Link组件、监听浏览器前进后退事件来实现:

实现代码

import { useRouter } from 'next/router'
import { useState, useEffect } from 'react'
import Image from 'next/image'

// 自定义拦截跳转的Link组件,替代原生next/link
const CustomLink = ({ href, children, setAnimated }) => {
  const router = useRouter()

  const handleClick = (e) => {
    e.preventDefault()
    // 跳转前立即移除动画类
    setAnimated(false)
    // 可选:如果你的CSS动画有过渡时长,这里加对应延迟再跳转,确保动画完全结束
    setTimeout(() => {
      router.push(href)
    }, 300) // 300ms对应你的动画时长,可自行调整
  }

  return (
    <a href={href} onClick={handleClick}>
      {children}
    </a>
  )
}

export default function Projects() {
  const [animated, setAnimated] = useState(true)
  const router = useRouter()

  useEffect(() => {
    // 处理浏览器前进/后退操作:路由变化前移除动画类
    const handleBeforePopState = () => {
      setAnimated(false)
      return true // 允许路由正常变化
    }

    router.beforePopState(handleBeforePopState)

    // 回到/projects页面时,恢复动画状态
    const handleRouteComplete = (url) => {
      if (url === '/projects') {
        // 延迟恢复,避免页面加载时的动画异常
        setTimeout(() => setAnimated(true), 100)
      }
    }

    router.events.on('routeChangeComplete', handleRouteComplete)

    // 组件卸载时清除监听
    return () => {
      router.beforePopState(() => true)
      router.events.off('routeChangeComplete', handleRouteComplete)
    }
  }, [router])

  // 注意:修复你原来的className拼接错误,用空格分隔类名而非+号
  return (
    <div className={styles.activeLayer}>
      <Image 
        layout="fill" 
        height='100%'
        src={allProjects[currentDisplay].backgroundImg} 
        alt="" 
      />
      <div className={`${styles.descriptionBox} ${animated ? styles.animatedOne : ''}`}>
        <h2>SomeTitle</h2>
        <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Modi excepturi esse ex odit saepe ipsam facere beatae similique doloremque quo quidem tempore quas molestias, commodi corporis natus possimus atque voluptatem?</p>

        <div className={`${styles.iconComponent} ${animated ? styles.animatedFive : ''}`}>
          <Tool imgArray={allProjects[currentDisplay].tools} />
        </div>
      </div>

      {/* 使用自定义跳转组件 */}
      <CustomLink href="/other-page" setAnimated={setAnimated}>
        跳转到其他页面
      </CustomLink>
    </div>
  )
}

关键说明

  1. 自定义CustomLink:拦截点击事件,先更新animated状态移除动画类,再执行路由跳转,从根源避免动画短暂执行的问题。
  2. beforePopState监听:处理浏览器前进/后退操作,同样在路由变化前移除动画类。
  3. routeChangeComplete恢复状态:回到/projects页面时,延迟恢复动画状态,确保页面加载完成后动画能正常触发。
  4. 修复className拼接:原代码中用+拼接类名是错误的,模板字符串内直接用空格分隔即可正确组合类名。

内容的提问来源于stack exchange,提问作者Mazakina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 07:18:20