news 2026/4/16 10:20:40

50天50个小项目 (React19 + Tailwindcss V4) ✨ | ButtonRippleEffect(按钮涟漪效果)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
50天50个小项目 (React19 + Tailwindcss V4) ✨ | ButtonRippleEffect(按钮涟漪效果)

📅 我们继续 50 个小项目挑战!—— ButtonRippleEffect 组件

仓库地址:https://gitee.com/hhm-hhm/50days50projects.git

构建一个带有点击波纹动画效果的按钮组件。这个按钮在点击时会从点击位置生成一个扩散的“涟漪”动画,增强用户交互体验。

🌀 组件目标

  • 创建一个具有点击波纹动画的按钮
  • 波纹动画从点击位置开始扩散
  • 支持多个连续点击的波纹动画
  • 使用 TailwindCSS快速构建现代 UI 界面

🔧 ButtonRippleEffect.tsx组件实现

import React, { useState, useRef } from 'react' const ButtonRippleEffect: React.FC = () => { const [ripples, setRipples] = useState<{ x: number; y: number; size: number }[]>([]) const buttonRef = useRef<HTMLButtonElement>(null) const addRipple = (event: React.MouseEvent) => { const button = buttonRef.current if (!button) return const rect = button.getBoundingClientRect() const x = event.clientX - rect.left const y = event.clientY - rect.top const size = Math.max(button.offsetWidth, button.offsetHeight) setRipples((prevState) => [...prevState, { x, y, size }]) // 600ms 后移除波纹效果,与动画持续时间匹配 setTimeout(() => { setRipples((prevState) => prevState.slice(1)) }, 600) } return ( <div className="flex h-screen items-center justify-center bg-gray-900"> <button ref={buttonRef} className="relative h-20 w-48 cursor-pointer overflow-hidden rounded-lg bg-blue-500 font-bold text-white transition-colors hover:bg-blue-600 active:bg-blue-700" onMouseDown={addRipple}> Click Me {ripples.map((ripple, index) => ( <span key={index} style={{ left: ripple.x + 'px', top: ripple.y + 'px', width: ripple.size + 'px', height: ripple.size + 'px', }} className="animate-ripple pointer-events-none absolute rounded-full bg-white/50 opacity-0"></span> ))} </button> <div className="fixed right-20 bottom-5 text-2xl text-red-500">CSDN@Hao_Harrision</div> </div> ) } export default ButtonRippleEffect

🦄样式动画

assets/style.css

... @keyframes ripple { 0% { transform: translate(-50%, -50%) scale(0); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(1.5); /* 根据需要调整scale大小 */ opacity: 0; } } .animate-ripple { animation: ripple 0.6s ease-out; /* 确保这个值与setTimeout中的延迟相匹配 */ }

🔧 转换说明

功能 / 概念Vue 3 (Composition API)React (TS + Hooks)
响应式状态const count = ref(0)const [count, setCount] = useState(0)
事件处理@click="handler"onClick={handler}
模板循环渲染<div v-for="(item, i) in list" :key="i">{list.map((item, i) => <div key={i}>...)}
动态内联样式:style="{ left: x + 'px' }"style={{ left:${x}px}}
动态 class:class="[isActive ? 'active' : '']"className={${isActive ? 'active' : ''}}或使用clsx/classnames
生命周期(挂载)onMounted(() => { ... })useEffect(() => { ... }, [])
副作用清理onUnmounted(() => { ... })useEffect(() => () => { ... }, [])
引用 DOM 元素const el = ref(null)+ref="el"const elRef = useRef<HTMLButtonElement>(null)+ref={elRef}
监听原生事件@mousedown="handler"onMouseDown={handler}
动画类名手动绑定.animate-ripple同样使用className="animate-ripple",配合 CSS
CSS scoped 样式<style scoped>单独.css文件 + 手动引入,或使用 CSS Modules /styled-components

⚠️ 常见陷阱与注意事项

问题解决方案
NodeJS.Timeout报错浏览器中setInterval返回number,应使用useRef<number | null>
setState in useEffect警告首次初始化时调用setState是合理的,可加// eslint-disable-next-line react-hooks/set-state-in-effect忽略
动态定位偏移使用rotate + translateY + rotate(-angle)时,transformOrigin: 'center'是关键;避免直接用translate(x,y)除非加上中心偏移
Tailwind 不生效确保tailwind.config.js正确配置content包含你的组件路径
TypeScript 类型安全明确标注状态类型,如useState<{x: number, y: number}[]>([])

✅ 最佳实践建议

  1. 状态合并:多个相关状态(如日期+时间)可合并为一个格式化字符串,减少重渲染。
  2. 定时器管理:始终用useRef存储setIntervalID,并在useEffect清理函数中清除。
  3. 事件坐标计算:使用getBoundingClientRect()获取按钮位置,再计算点击点相对坐标。
  4. 动画同步setTimeout清除 ripple 的时间必须 ≥ CSS 动画持续时间。
  5. 避免内联回调:若性能敏感,可用useCallback包裹事件处理器(本例中非必需)。

🎨 TailwindCSS 样式重点讲解

🎯 TailwindCSS 样式说明
类名作用
h-screen,items-center,justify-center设置全屏高度并垂直居中布局
bg-gray-900设置深色背景
relative为按钮设置相对定位,方便内部绝对定位的波纹元素
h-20,w-48设置按钮高度和宽度
rounded-lg圆角按钮
bg-blue-500,hover:bg-blue-600,active:bg-blue-700按钮颜色及悬停、激活状态下的变色效果
font-bold,text-white文字加粗和白色字体
transition-colors添加颜色变化的过渡动画
absolute,rounded-full,bg-white/50波纹元素的基本样式
pointer-events-none避免波纹干扰按钮点击事件
opacity-0初始隐藏波纹,由动画控制显示

这些 Tailwind 工具类快速构建了一个视觉丰富、交互性强的按钮组件

🦌 路由组件 + 常量定义

router/index.tsxchildren数组中添加子路由

{ path: '/', element: <App />, children: [ ... { path: '/ButtonRipple', lazy: () => import('@/projects/ButtonRippleEffect.tsx').then((mod) => ({ Component: mod.default, })), }, ], },

constants/index.tsx 添加组件预览常量

import demo20Img from '@/assets/pic-demo/demo-20.png' 省略部分.... export const projectList: ProjectItem[] = [ 省略部分.... { id: 20, title: 'Button Ripple Effect', image: demo20Img, link: 'ButtonRipple', },

🚀 小结

扩展的功能推荐:

  • 支持不同颜色主题的波纹按钮
  • 支持禁用状态下的点击无反应
  • 支持自定义波纹颜色或透明度
  • 多个按钮共享波纹动画逻辑(封装为可复用组件)

📅 明日预告: 我们将完成DragNDrop组件,一个非常有意思的拖拽组件,可以对元素进行重新排列。🚀


原文链接:https://blog.csdn.net/qq_44808710/article/details/149080035

每天造一个轮子,码力暴涨不是梦!🚀

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/10 11:34:23

7天精通Daytona Web远程桌面:从零搭建企业级云端开发环境

7天精通Daytona Web远程桌面&#xff1a;从零搭建企业级云端开发环境 【免费下载链接】daytona 开源开发环境管理器。 项目地址: https://gitcode.com/GitHub_Trending/dayt/daytona 还在为团队开发环境碎片化而头疼&#xff1f;是否曾经因为一台电脑无法满足所有开发需…

作者头像 李华
网站建设 2026/4/16 10:19:13

电商微服务:Docker+Jenkins实战部署指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个电商微服务演示项目&#xff0c;包含&#xff1a;1. 商品服务、订单服务、用户服务三个微服务&#xff1b;2. 每个服务有独立的Docker容器配置&#xff1b;3. 完整的Jenkin…

作者头像 李华
网站建设 2026/4/16 9:01:33

GUI智能交互新范式:重新定义人机协作边界

GUI智能交互新范式&#xff1a;重新定义人机协作边界 【免费下载链接】UI-TARS-7B-DPO 项目地址: https://ai.gitcode.com/hf_mirrors/ByteDance-Seed/UI-TARS-7B-DPO 当企业每天需要处理数百个重复性界面操作时&#xff0c;当跨系统数据流转成为效率瓶颈时&#xff0c…

作者头像 李华
网站建设 2026/4/15 6:13:44

深入了解服务器!构建稳定可靠的网络核心如此重要

服务器基础概念与核心作用 服务器作为网络架构的核心组件&#xff0c;承担着数据存储、计算处理和资源分配的关键任务。从硬件角度看&#xff0c;服务器本质上是高性能计算机&#xff0c;但具备更强的稳定性、可靠性和扩展性。与普通PC相比&#xff0c;服务器采用ECC内存、RAI…

作者头像 李华
网站建设 2026/4/16 10:20:14

服务器怎么搭建?一文读懂从硬件选型到安全运维的完整指南

服务器搭建的硬件选型搭建服务器的第一步是选择合适的硬件配置。硬件选型需根据服务器用途&#xff08;如Web服务器、数据库服务器、文件服务器等&#xff09;和预期负载进行权衡。CPU选择 高性能服务器推荐多核处理器&#xff0c;如Intel Xeon或AMD EPYC系列。计算密集型任务&…

作者头像 李华
网站建设 2026/4/15 12:46:32

【AI任务调试必看】:Open-AutoGLM执行日志深度解读与故障预判

第一章&#xff1a;Open-AutoGLM 任务执行日志查看与分析在 Open-AutoGLM 系统中&#xff0c;任务执行日志是诊断模型推理流程、排查错误和优化性能的核心依据。日志不仅记录了任务的调度时间、输入参数和执行状态&#xff0c;还包含详细的中间推理步骤与资源消耗信息。日志存储…

作者头像 李华