50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | DoubleClickHeart(双击爱心)

发布于:2025-07-16 ⋅ 阅读:(18) ⋅ 点赞:(0)

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

仓库地址:https://github.com/SunACong/50-vue-projects

项目预览地址:https://50-vue-projects.vercel.app/

在这里插入图片描述


使用 Vue 3 的 Composition API(<script setup>)结合 TailwindCSS 和 Font Awesome 创建一个双击点赞动画组件。用户可以双击图片区域触发一个“❤️ 爱心飞出”动画,并统计点赞次数。

这个交互体验非常适用于社交媒体、照片墙、内容点赞等场景。


🎯 组件目标

  • 用户双击图片区域时显示爱心动画
  • 显示当前点赞总次数
  • 动画结束后自动移除爱心元素
  • 使用 Vue 3 Composition API 管理状态
  • 使用 TailwindCSS 构建 UI 样式与布局
  • 支持动态定位和点击时间判断

⚙️ 技术实现点

技术点 描述
Vue 3 <script setup> 使用响应式变量管理点赞数、爱心列表
ref 响应式变量 控制 likeshearts 和 DOM 容器引用
双击检测逻辑 判断两次点击时间间隔是否小于 800ms
动态创建元素 在点击位置生成爱心图标并添加动画
TailwindCSS 样式 设置图片容器、文字样式、动画基础属性
自定义字体加载 使用 JS 动态加载 Oswald 字体与 Font Awesome 图标库
CSS 关键帧动画 实现放大淡出的爱心动画效果

🧱 组件实现

模板结构 <template>

<template>
    <div class="flex min-h-screen flex-col items-center justify-center overflow-hidden font-[Oswald] text-white">
        <h3 class="mb-0 text-center">
            Double click on the image to
            <i class="fas fa-heart text-red-600"></i>
            it
        </h3>
        <small class="mb-5 block text-center">
            You liked it
            <span>{{ likes }}</span>
            times
        </small>

        <!-- 图片容器 -->
        <div
            class="relative h-[440px] w-[300px] cursor-pointer overflow-hidden bg-cover bg-center shadow-lg"
            :style="{ backgroundImage: `url(${imageUrl})` }"
            @click="handleClick"
            ref="container">
            <i
                v-for="heart in hearts"
                :key="heart.id"
                class="fas fa-heart heart-anim absolute text-red-600"
                :style="{ top: heart.y + 'px', left: heart.x + 'px' }"></i>
        </div>
    </div>
</template>

脚本逻辑 <script setup>

<script setup>
import { onMounted, ref } from 'vue'

const likes = ref(0)
const hearts = ref([])
const container = ref(null)
let clickTime = 0

const handleClick = (e) => {
    const now = new Date().getTime()
    if (clickTime === 0) {
        clickTime = now
    } else {
        if (now - clickTime < 800) {
            createHeart(e)
            clickTime = 0
        } else {
            clickTime = now
        }
    }
}

const createHeart = (e) => {
    const rect = container.value.getBoundingClientRect()
    const xInside = e.clientX - rect.left
    const yInside = e.clientY - rect.top

    const id = Date.now()
    hearts.value.push({ id, x: xInside, y: yInside })
    likes.value++

    setTimeout(() => {
        hearts.value = hearts.value.filter((h) => h.id !== id)
    }, 1000)
}

const imageUrl =
    'https://images.unsplash.com/photo-1504215680853-026ed2a45def?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=334&q=80'

onMounted(() => {
    const fontLink = document.createElement('link')
    fontLink.href = 'https://fonts.googleapis.com/css?family=Oswald'
    fontLink.rel = 'stylesheet'
    document.head.appendChild(fontLink)

    const faLink = document.createElement('link')
    faLink.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css'
    faLink.rel = 'stylesheet'
    faLink.crossOrigin = 'anonymous'
    document.head.appendChild(faLink)
})
</script>

样式部分 <style scoped>

<style scoped>
.heart-anim {
    position: absolute;
    animation: grow 0.6s linear;
    transform: translate(-50%, -50%) scale(0);
}

@keyframes grow {
    to {
        transform: translate(-50%, -50%) scale(10);
        opacity: 0;
    }
}
</style>

🔍 重点效果实现

✅ 双击事件判断

通过记录点击时间戳来判断是否为双击行为:

const now = new Date().getTime()
if (now - clickTime < 800) {
    createHeart(e)
    clickTime = 0
} else {
    clickTime = now
}

这是模拟原生 dblclick 事件的一种方式,同时保留了对单击行为的控制。

💡 动态生成爱心图标

每次双击会根据点击坐标生成一个爱心图标:

hearts.value.push({ id, x: xInside, y: yInside })

并在一秒后自动从数组中移除,以实现动画结束后的清理。

🎨 动画设计

使用 CSS 关键帧实现放大并透明消失的效果:

@keyframes grow {
    to {
        transform: translate(-50%, -50%) scale(10);
        opacity: 0;
    }
}

配合 Tailwind 的 absolute 定位,实现了视觉上“从点击点飞出”的效果。


🎨 TailwindCSS 样式重点讲解

类名 作用
min-h-screen, flex-col, items-center, justify-center 居中布局
font-[Oswald], text-white 字体与文字颜色
relative, absolute 心形图标的绝对定位
h-[440px] w-[300px] 固定图片容器大小
bg-cover bg-center 设置背景图片居中覆盖
cursor-pointer 鼠标悬停为手型
overflow-hidden 防止爱心动画溢出容器
shadow-lg 添加阴影提升层次感
text-red-600 爱心颜色设置为红色

这些类帮助我们快速构建了一个美观、互动性强的点赞组件。


📁 常量定义 + 组件路由

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

{
        id: 29,
        title: 'Double Click Heart',
        image: 'https://50projects50days.com/img/projects-img/29-double-click-heart.png',
        link: 'DoubleClickHeart',
    },

router/index.js 中添加路由选项:

{
        path: '/DoubleClickHeart',
        name: 'DoubleClickHeart',
        component: () => import('@/projects/DoubleClickHeart.vue'),
    },

🏁 总结

基于 Vue 3 和 TailwindCSS 的双击点赞动画组件不仅实现了基本的交互功能,它非常适合用于社交平台、图片浏览、内容互动等需要增强用户体验的场景。

你可以进一步扩展此组件的功能包括:

  • ✅ 添加音效反馈(如“滴”一声)
  • ✅ 支持移动端触摸双击识别
  • ✅ 支持本地存储点赞数(使用 localStorage)
  • ✅ 添加粒子爆炸或其他动画效果
  • ✅ 将组件封装为 <DoubleHeartImage /> 可复用组件

👉 下一篇,我们将完成AutoTextEffect组件,一个类似打字机的组件,可以调节速度。🚀

感谢阅读,欢迎点赞、收藏和分享 😊


网站公告

今日签到

点亮在社区的每一天
去签到