50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | ButtonRippleEffect(按钮涟漪效果)
📅 我们继续 50 个小项目挑战!—— ButtonRippleEffect
组件
仓库地址:https://github.com/SunACong/50-vue-projects
项目预览地址:https://50-vue-projects.vercel.app/
使用 Vue 3 的 Composition API 和 <script setup>
语法结合 TailwindCSS 构建一个带有点击波纹动画效果的按钮组件。这个按钮在点击时会从点击位置生成一个扩散的“涟漪”动画,增强用户交互体验。
🎯 组件目标
- 创建一个具有点击波纹动画的按钮
- 波纹动画从点击位置开始扩散
- 支持多个连续点击的波纹动画
- 使用 TailwindCSS 快速构建现代 UI 界面
- 使用 Vue 3 Composition API 管理状态和事件
⚙️ 技术实现点
技术点 | 描述 |
---|---|
Vue 3 Composition API (<script setup> ) | 使用响应式变量管理组件状态 |
ref 响应式变量 | 存储波纹的位置与尺寸 |
@click 事件绑定 | 触发波纹动画生成 |
getBoundingClientRect() | 获取按钮在页面中的位置 |
TailwindCSS 动画类 | 构建美观的波纹扩散动画 |
setTimeout 定时清理 | 控制波纹动画结束后的清除逻辑 |
🧱 组件实现
模板结构 <template>
<template><div class="flex h-screen items-center justify-center bg-gray-900"><buttonclass="relative h-20 w-48 overflow-hidden rounded-lg bg-blue-500 font-bold text-white transition-colors hover:bg-blue-600 active:bg-blue-700"@click="addRipple">Click Me<spanv-for="(ripple, index) in ripples":key="index":style="{left: ripple.x + 'px',top: ripple.y + 'px',width: ripple.size + 'px',height: ripple.size + 'px',}"class="animate-ripple pointer-events-none absolute rounded-full bg-white/50 opacity-0"></span></button></div>
</template>
脚本逻辑 <script setup>
<script setup>
import { ref } from 'vue'const ripples = ref([])const addRipple = (event) => {const button = event.currentTargetconst rect = button.getBoundingClientRect()const x = event.clientX - rect.leftconst y = event.clientY - rect.topconst size = Math.max(button.offsetWidth, button.offsetHeight)ripples.value.push({ x, y, size })// 300ms 后移除最早添加的波纹,与动画持续时间匹配setTimeout(() => {ripples.value.shift()}, 300)
}
</script>
自定义样式 <style scoped>
<style scoped>
@keyframes ripple {0% {transform: translate(-50%, -50%) scale(0);opacity: 1;}100% {transform: translate(-50%, -50%) scale(4);opacity: 0;}
}.animate-ripple {animation: ripple 0.3s ease-out;
}
</style>
🔍 重点效果实现
✅ 波纹动画触发逻辑
通过 @click
事件获取点击坐标,并计算相对于按钮左上角的位置:
const x = event.clientX - rect.left
const y = event.clientY - rect.top
再根据按钮宽高确定波纹的最大扩散范围:
const size = Math.max(button.offsetWidth, button.offsetHeight)
然后将该波纹对象加入数组中,由模板循环渲染出对应的 <span>
元素。
💡 波纹动画样式
我们使用 CSS 自定义了一个名为 ripple
的动画,从中心缩放并逐渐消失:
@keyframes ripple {0% {transform: translate(-50%, -50%) scale(0);opacity: 1;}100% {transform: translate(-50%, -50%) scale(4);opacity: 0;}
}
并通过 .animate-ripple
类应用到每个波纹元素上。
🗑️ 波纹清理机制
每次添加新波纹后,设置一个定时器(0.3 秒)来移除最早的那个波纹,避免内存堆积:
setTimeout(() => {ripples.value.shift()
}, 300)
🎨 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 工具类帮助我们快速构建了一个视觉丰富、交互性强的按钮组件。
📁 常量定义 + 组件路由
constants/index.js
添加组件预览常量:
{id: 20,title: 'Button Ripple Effect',image: 'https://50projects50days.com/img/projects-img/20-button-ripple-effect.png',link: 'ButtonRippleEffect',},
router/index.js
中添加路由选项:
{path: '/ButtonRippleEffect',name: 'ButtonRippleEffect',component: () => import('@/projects/ButtonRippleEffect.vue'),},
🏁 总结
扩展的功能推荐:
- 支持不同颜色主题的波纹按钮
- 支持禁用状态下的点击无反应
- 支持自定义波纹颜色或透明度
- 多个按钮共享波纹动画逻辑(封装为可复用组件)
感谢阅读,欢迎点赞、收藏和分享 😊
👉 下一篇,我们将完成DragNDrop
组件,一个非常有意思的拖拽组件,可以对元素进行重新排列。🚀