Next.js+TypeScript项目构建失败:framer-motion translateY类型错误
Next.js + TypeScript 构建失败:motion.img 的 translateY 类型错误
问题描述
项目在 npm run dev 模式下运行正常,但执行 next build 时编译失败,报错指向 Hero.tsx 中 motion.img 组件 animate 属性内的 translateY 配置。
package.json 依赖配置
"scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "autoprefixer": "^10.4.21", "clsx": "^2.1.1", "motion": "^12.18.1", "next": "15.3.3", "postcss": "^8.5.4", "react": "^19.0.0", "react-dom": "^19.0.0", "tailwind-merge": "^3.3.0" }, "devDependencies": { "@eslint/eslintrc": "^3", "@svgr/webpack": "^8.1.0", "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "babel-plugin-inline-react-svg": "^2.0.2", "eslint": "^9", "eslint-config-next": "15.3.3", "tailwindcss": "^4.1.8", "typescript": "^5" }
Hero 组件代码
"use client"; import ArrowIcon from "@/assets/arrow-right.svg"; import poundImage from "@/assets/pound.png"; import houseImage from "@/assets/house.png"; import businessImage from "@/assets/business.png"; import { motion, useScroll, useTransform } from "framer-motion"; import { useRef } from "react"; export const Hero = () => { const heroRef = useRef(null); const { scrollYProgress } = useScroll({ target: heroRef, offset: ["start end", "end start"], }); const translateY = useTransform(scrollYProgress, [0, 1], [150, -150]); return <section ref={heroRef} className="pt-8 pb-20 md:pt-5 pl-20 pr-20 md:pb-10 bg-[radial-gradient(ellipse_200%_100%_at_bottom_left,#8a0194,#ffffff_100%)] overflow-x-clip"> <div className="container"> <div className="md:flex items-center"> <div className="md:w-[478px]"> <div className="text-sm inline-flex border border-[#222]/10 px-3 py-1 rounded-lg tracking-tight">Rethink Finance</div> <h1 className="text-5xl md:text-7xl font-bold tracking-tighter bg-gradient-to-b from-black to-[#8a0194] text-transparent bg-clip-text mt-6">Empowering Your Business with Smart Financial Solutions</h1> <p className="text-xl text-[#8a0194] tracking-tight mt-6">Whether you are seizing new opportunities, investing in inventory, or streamlining your cash flow, our tailored financial solutions are designed to power your progress and take your business further.</p> <div className="flex gap-1 items-center mt-[30px]"> <a href="https://us.bigin.online/org884823567/forms/check-your-funding-eligibility-for-free"><button className="bg-fuchsia-800 text-white focus:outline-none hover:bg-indigo-600 px-4 py-2 rounded-lg font-medium inline-flex items-center justify-center tracking-tight">Get Started</button></a> <button className="text-black px-4 py-2 font-light inline-flex items-center justify-center tracking-tight gap-1"> <span>Learn more</span> <ArrowIcon className="h-5 w-5" /> </button> </div> </div> <div className="mt-20 md:mt-0 md:h-[648px] md:flex-1 relative"> <motion.img src={poundImage.src} alt="Pound Image" className="md:absolute md:h-full md:w-auto md:max-w-none md:-left-6 lg:left-0" animate={{ translateY: [-30, 30], }} transition={{ repeat: Infinity, repeatType: "mirror", duration: 2, ease: "easeInOut", }} /> <motion.img src={houseImage.src} width={220} height={220} alt="House image" className="hidden md:block -top-8 -left-32 md:absolute" style={{ translateY: translateY }} /> <motion.img src={businessImage.src} width={220} height={220} alt="Business image" className="hidden lg:block absolute top-[524px] left-[448px] rotate-[30deg]" style={{ translateY: translateY, }} /> </div> </div> </div> </section> };
错误信息
./src/sections/Hero.tsx:39:29 Type error: Object literal may only specify known properties, and 'translateY' does not exist in type 'string[] | TargetAndTransition | LegacyAnimationControls'. 37 | src={poundImage.src} alt="Pound Image" className="md:absolute md:h-full md:w-auto md:max-w-none md:-left-6 lg:left-0" 38 | animate={{ > 39 | translateY: [-30, 30], | ^ 40 | }} 41 | transition={{ 42 | repeat: Infinity, Next.js build worker exited with code: 1 and signal: null
问题原因
你使用的是 Framer Motion v12+(包名已从 framer-motion 改为 motion),该版本对动画 API 做了变更:animate 属性中不再支持直接使用 translateY/translateX 这类单个变换属性,必须将所有变换属性统一放在 transform 对象内。
开发模式下 TypeScript 的类型校验相对宽松,未触发报错;但构建阶段启用严格类型检查,不符合新 API 结构的代码直接导致编译失败。
解决方法
修正 animate 属性的写法
将 translateY 移到 transform 对象中,有两种写法可选:
写法1:使用 CSS 字符串数组
<motion.img src={poundImage.src} alt="Pound Image" className="md:absolute md:h-full md:w-auto md:max-w-none md:-left-6 lg:left-0" animate={{ transform: ["translateY(-30px)", "translateY(30px)"], }} transition={{ repeat: Infinity, repeatType: "mirror", duration: 2, ease: "easeInOut", }} />
写法2:使用变换对象数组
<motion.img src={poundImage.src} alt="Pound Image" className="md:absolute md:h-full md:w-auto md:max-w-none md:-left-6 lg:left-0" animate={{ transform: [ { translateY: -30 }, { translateY: 30 } ], }} transition={{ repeat: Infinity, repeatType: "mirror", duration: 2, ease: "easeInOut", }} />
注意事项
另外两个 motion.img 组件中 style={{ translateY: translateY }} 的写法是正常的,因为 React 的 style 属性支持直接使用 CSS 变换属性,只有 motion 组件的 animate 属性需要遵循新 API 规范。
内容的提问来源于stack exchange,提问作者C N K
相关产品推荐
相关产品推荐

