如何在ReactJS中实现动画?含动画文本与鼠标交互画布需求
React动画实现指南:从文本动画到鼠标交互画布
一、React中实现动画的核心方式
- CSS原生动画:适合简单过渡、循环动画(如文本切换、hover效果),编写成本低,性能表现优秀。
- React过渡组件:比如
react-transition-group,专注处理组件挂载/卸载阶段的过渡动画。 - 自定义Hook/脚本:针对复杂交互类动画(如鼠标跟随、画布绘制),需通过事件监听、状态更新实现精细化控制。
二、实用工具包推荐
不用从零搭建动画逻辑,这些工具包能大幅提升开发效率:
- framer-motion:API简洁直观,支持声明式动画,内置手势、路径动画能力,新手友好。
- react-spring:基于物理引擎的动画库,适合实现弹性、惯性等自然流畅的动效。
- react-transition-group:React官方推荐的过渡组件库,聚焦组件生命周期的动画控制。
三、针对你的需求的具体实现
1. 动画文本(轮播切换效果)
你的代码中已有.animated-text容器,这里提供两种实现方案:
方案一:纯CSS动画
在Main.css中添加以下样式,无需修改JS代码:
.animated-text { height: 40px; /* 固定高度避免容器跳动 */ overflow: hidden; position: relative; } .animated-text h3 { position: absolute; top: 0; left: 0; width: 100%; opacity: 0; margin: 0; animation: textSlide 6s infinite; } .animated-text h3:nth-child(2) { animation-delay: 3s; } @keyframes textSlide { 0%, 15% { opacity: 0; transform: translateY(20px); } 20%, 50% { opacity: 1; transform: translateY(0); } 55%, 100% { opacity: 0; transform: translateY(-20px); } }
方案二:用framer-motion实现灵活可控的动画
先安装依赖:npm install framer-motion
再修改Main.js:
import React, { useState, useEffect } from 'react' import Heading from '../organisms/Heading' import Button from '../atoms/Button' import { motion, AnimatePresence } from 'framer-motion' import './Main.css' const Main = () => { const [activeIndex, setActiveIndex] = useState(0) const texts = ["Web Designer", "Jr Full-stack Web Developer"] // 自动切换文本 useEffect(() => { const timer = setInterval(() => { setActiveIndex(prev => (prev + 1) % texts.length) }, 3000) return () => clearInterval(timer) }, [texts.length]) return ( <div className='main_container'> <section className="main" id="main"> <div className="content"> <h2>Hello, I´m <br/> <span>Mateo Ghidini</span></h2> <div className="animated-text"> <AnimatePresence mode="wait"> <motion.h3 key={activeIndex} initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -20 }} transition={{ duration: 0.5 }} > {texts[activeIndex]} </motion.h3> </AnimatePresence> </div> <Button className="btn" content="See My Work"/> <div className="media-icons"> <a href="https://www.linkedin.com/in/mghidini/"><i className="fab fa-linkedin-in"></i></a> <a href="https://github.com/mateoghidini1998"><i className="fab fa-github"></i></a> </div> </div> </section> </div> ) } export default Main
2. 随鼠标移动变色的画布效果
通过自定义Hook监听鼠标位置,结合Canvas实现动态变色效果:
步骤1:创建自定义Hook useMousePosition.js
import { useState, useEffect } from 'react' export const useMousePosition = () => { const [position, setPosition] = useState({ x: 0, y: 0 }) useEffect(() => { const handleMouseMove = (e) => { setPosition({ x: e.clientX, y: e.clientY }) } window.addEventListener('mousemove', handleMouseMove) return () => window.removeEventListener('mousemove', handleMouseMove) }, []) return position }
步骤2:在Main.js中集成Hook与Canvas
import React, { useRef, useEffect } from 'react' import Heading from '../organisms/Heading' import Button from '../atoms/Button' import { useMousePosition } from '../hooks/useMousePosition' import './Main.css' const Main = () => { const { x, y } = useMousePosition() const canvasRef = useRef(null) // 随鼠标位置更新画布颜色 useEffect(() => { const canvas = canvasRef.current if (!canvas) return const ctx = canvas.getContext('2d') canvas.width = window.innerWidth canvas.height = window.innerHeight // 根据鼠标坐标计算RGB值 const r = Math.floor((x / window.innerWidth) * 255) const g = Math.floor((y / window.innerHeight) * 255) const b = 150 ctx.fillStyle = `rgb(${r}, ${g}, ${b})` ctx.fillRect(0, 0, canvas.width, canvas.height) // 添加半透明覆盖层,实现移动渐变效果 ctx.fillStyle = 'rgba(255,255,255,0.05)' ctx.fillRect(0, 0, canvas.width, canvas.height) }, [x, y]) return ( <div className='main_container'> {/* 画布作为背景层 */} <canvas ref={canvasRef} className="mouse-canvas" /> <section className="main" id="main"> <div className="content"> <h2>Hello, I´m <br/> <span>Mateo Ghidini</span></h2> <div className="animated-text"> <h3>Web Designer</h3> <h3>Jr Full-stack Web Developer</h3> </div> <Button className="btn" content="See My Work"/> <div className="media-icons"> <a href="https://www.linkedin.com/in/mghidini/"><i className="fab fa-linkedin-in"></i></a> <a href="https://github.com/mateoghidini1998"><i className="fab fa-github"></i></a> </div> </div> </section> </div> ) } export default Main
步骤3:在Main.css中设置画布样式
.mouse-canvas { position: fixed; top: 0; left: 0; z-index: -1; /* 置于内容下方 */ pointer-events: none; /* 不干扰其他元素交互 */ } .main_container { position: relative; min-height: 100vh; }
四、关于自定义Hook的使用建议
如果是复用性高的逻辑(如鼠标位置监听、滚动状态监听),自定义Hook能让代码更简洁、可维护;如果只是单一页面的简单动画,直接写在组件内或用CSS实现即可。
内容的提问来源于stack exchange,提问作者tukitooo1998
相关产品推荐
相关产品推荐

