50天50个小项目 (React19 + Tailwindcss V4) ✨| ThreeDBackgroundBoxes(3D背景盒子组件)

📅 今天我们继续 50 个小项目挑战!------ThreeDBackgroundBoxes组件

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

​​​​

创建一个充满魔法感的交互式动画组件 ------ "魔法盒子"。当你点击"Magic"按钮时,整个盒子阵列会放大并旋转,带来一种神奇的视觉体验!

准备好施展魔法了吗?让我们开始吧!✨

🌀 组件目标

  • 动态生成 4×4 的盒子网格
  • 实现点击按钮触发整体缩放与旋转动画
  • 利用背景定位实现 Gif 动画的分块显示
  • 添加 3D 边框效果增强立体感
  • 采用 Tailwind CSS 快速构建美观的响应式布局

🔧 ThreeDBackgroundBoxes.tsx组件实现

TypeScript 复制代码
import React, { useState, useEffect } from 'react'

// 定义 Box 类型
interface Box {
    x: number
    y: number
}

const ThreeDBackgroundBoxes: React.FC = () => {
    const [isBig, setIsBig] = useState<boolean>(false)
    const [boxes, setBoxes] = useState<Box[]>([])

    // 创建 4x4 盒子数据
    const createBoxes = () => {
        const boxArray: Box[] = []
        for (let i = 0; i < 4; i++) {
            for (let j = 0; j < 4; j++) {
                boxArray.push({
                    x: -j * 125,
                    y: -i * 125,
                })
            }
        }
        setBoxes(boxArray)
    }

    // 组件挂载时初始化盒子
    useEffect(() => {
        createBoxes()
    }, [])

    return (
        <div className="flex h-screen flex-col items-center justify-center overflow-hidden bg-gray-800">
            {/* 魔法按钮 */}
            <button
                onClick={() => setIsBig(!isBig)}
                className="font-poppins fixed top-5 z-50 transform cursor-pointer rounded bg-yellow-400 px-5 py-3 text-white shadow-md transition-all duration-200 hover:shadow-lg active:translate-y-1 active:shadow-none">
                Magic 🎩
            </button>

            {/* 盒子容器 */}
            <div
                className={`relative flex flex-wrap justify-around transition-all duration-400 ${
                    isBig ? 'h-[600px] w-[600px]' : 'h-[500px] w-[500px]'
                }`}>
                {/* 动态生成盒子 */}
                {boxes.map((box, index) => (
                    <div
                        key={index}
                        className={`relative h-[125px] w-[125px] transition-all duration-400 ${
                            isBig ? 'rotate-360' : 'rotate-0'
                        }`}
                        style={{
                            backgroundImage:
                                'url(https://media.giphy.com/media/EZqwsBSPlvSda/giphy.gif)',
                            backgroundRepeat: 'no-repeat',
                            backgroundSize: '500px 500px',
                            backgroundPosition: `${box.x}px ${box.y}px`,
                        }}>
                        {/* 3D 效果伪元素 ------ 使用额外 div 模拟 */}
                        <div className="absolute top-2 right-[-15px] h-full w-4 skew-y-12 transform bg-yellow-200" />
                        <div className="absolute bottom-[-15px] left-2 h-4 w-full skew-x-12 transform bg-yellow-400" />
                    </div>
                ))}
            </div>
            <div className="fixed right-20 bottom-5 z-100 text-2xl text-red-500">
                CSDN@Hao_Harrision
            </div>
        </div>
    )
}

export default ThreeDBackgroundBoxes

🔄 关键差异总结

功能 Vue 3 React + TS
响应式状态 ref() useState()
生命周期 onMounted useEffect(..., [])
列表渲染 v-for .map()
条件类名 :class="[...]" 模板字符串 + 三元
动态样式 :style style={``{}}
类型安全 --- interface Box + 泛型

✅ 使用前检查

  1. 确保 Tailwind 支持任意值 (如 h-[600px], rotate-[360deg])------默认支持;
  2. 确认 GIF 可访问,否则替换为本地资源;
  3. 若使用 font-poppins,需在项目中引入 Poppins 字体(Google Fonts 或本地)。

🔁 转换说明

1. 状态管理:refuseState

Vue React
const isBig = ref(false) const boxes = ref([]) const [isBig, setIsBig] = useState(false) const [boxes, setBoxes] = useState<Box[]>([])

✅ 使用 TypeScript 泛型 Box[] 提供类型安全。


2. 生命周期:onMounteduseEffect

Vue React
onMounted(() => { createBoxes() }) useEffect(() => { createBoxes(); }, [])

✅ 空依赖数组 [] 确保只在组件挂载时执行一次,等价于 onMounted


3. 列表渲染:v-for.map()

  • Vue: <div v-for="(box, index) in boxes" :key="index">
  • React: {boxes.map((box, index) => <div key={index}>...)}

✅ 由于 boxes 是静态生成(4x4 固定),使用 index 作为 key 是安全的。


4. 动态类名与样式

动态尺寸和旋转:
TypeScript 复制代码
className={`... ${isBig ? 'h-[600px] w-[600px]' : 'h-[500px] w-[500px]'}`}
TypeScript 复制代码
className={`${isBig ? 'rotate-[360deg]' : 'rotate-0'}`}

⚠️ 注意:Tailwind 默认不支持 rotate-360,需使用 任意值语法 rotate-[360deg]

动态背景位置(inline style):
TypeScript 复制代码
style={{
  backgroundPosition: `${box.x}px ${box.y}px`,
}}

✅ 与 Vue 的 :style 行为完全一致。


5. 事件处理:@clickonClick

TypeScript 复制代码
onClick={() => setIsBig(!isBig)}

✅ 简洁且符合 React 习惯。


6. 3D 伪元素模拟

Vue 和 React 都无法直接使用 ::before / ::after 通过 Tailwind 控制(因 Tailwind 不作用于伪类,除非启用插件)。

因此,两者都采用 额外 <div> 元素 模拟 3D 边效果:

  • 右侧黄条:right-[-15px], skew-y-12
  • 底部黄条:bottom-[-15px], skew-x-12

✅ 视觉效果完全一致。


7. GIF 背景问题提醒 ⚠️

你使用的 GIF 地址:

bash 复制代码
https://media.giphy.com/media/EZqwsBSPlvSda/giphy.gif

但在你之前上传的文件中显示:

Access to media.giphy.com was denied --- HTTP ERROR 403

这意味着 该图片可能无法加载(Giphy 限制了外站引用)。

🔧 建议

  • 下载 GIF 并放入 public/ 目录,改用本地路径:

    TypeScript 复制代码
    backgroundImage: 'url(/giphy.gif)'
  • 或替换为可公开访问的图片 URL。


💡 优化建议(可选)

  • boxes 逻辑提取为自定义 Hook(如 useBoxesGrid);
  • 使用 useMemo 缓存 boxes(但此处由 useEffect 初始化,非必需);
  • 添加 key={box.x}-${box.y} 提升 key 唯一性(虽非必要,但更规范)。

🎨 TailwindCSS 样式重点讲解

类名 作用
h-screen 设置高度为视口高度
flex-col 垂直方向 Flex 布局
items-center / justify-center 居中对齐
overflow-hidden 隐藏溢出内容
bg-gray-100 设置背景色
fixed top-5 按钮固定在顶部
z-50 提升按钮层级
transform 启用变换
rounded 圆角按钮
bg-yellow-400 / text-white 按钮颜色
shadow-md / hover:shadow-lg 阴影效果
active:translate-y-1 按下时向下移动
active:shadow-none 按下时隐藏阴影
relative / flex-wrap 容器布局
transition-all duration-400 0.4s 平滑过渡
h-[125px] w-[125px] 固定盒子尺寸
rotate-360 / rotate-0 控制旋转状态
absolute top-2 right-[-15px] 创建右侧斜面
skew-y-12 Y轴倾斜12度
bg-yellow-200 / bg-yellow-400 3D边框颜色
[🎯 TailwindCSS 样式说明]

🦌 路由组件 + 常量定义

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

TypeScript 复制代码
{
    path: '/',
    element: <App />,
    children: [
       ...
       {
                path: '/ThreeDBackgroundBoxes',
                lazy: () =>
                    import('@/projects/ThreeDBackgroundBoxes').then((mod) => ({
                        Component: mod.default,
                    })),
            },
    ],
 },
复制代码
constants/index.tsx 添加组件预览常量
TypeScript 复制代码
import demo40Img from '@/assets/pic-demo/demo-40-1.png'
省略部分....
export const projectList: ProjectItem[] = [
    省略部分....
      {
        id: 40,
        title: 'ThreeDBackgroundBoxes',
        image: demo40Img,
        link: 'ThreeDBackgroundBoxes',
    },
]

🚀 小结

通过这篇文章,我们使用 React19 和 TailwindCSS 创建一个充满魔法感的交互式动画组件 ------ "魔法盒子"。当你点击"Magic"按钮时,整个盒子阵列会放大并旋转.

想让你的魔法盒子更炫酷?试试这些扩展:

  • 添加音效:点击时播放魔法音效
  • 随机旋转角度:每个盒子旋转角度不同
  • 颜色主题切换:支持多种配色方案
  • 手势控制:支持触摸滑动触发动画
  • 粒子特效:点击时释放小星星或火花动画

📅 明日预告: 我们将完成VerifyAccountUi组件,实现了一个非常使用的验证码UI组件。🚀

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

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

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

相关推荐
加个鸡腿儿8 小时前
经验分享2:SSR 项目中响应式组件的闪动陷阱与修复实践
前端·css·架构
心.c9 小时前
如何基于 RAG 技术,搭建一个专属的智能 Agent 平台
开发语言·前端·vue.js
智航GIS9 小时前
10.7 pyspider 库入门
开发语言·前端·python
华仔啊9 小时前
写 CSS 用 px?这 3 个单位能让页面自动适配屏幕
前端·css
静听松涛13310 小时前
提示词注入攻击的防御机制
前端·javascript·easyui
晚风予星10 小时前
简记 | 一个基于 AntD 的高效 useDrawer Hooks
前端·react.js·设计
栗子叶10 小时前
网页接收服务端消息的几种方式
前端·websocket·http·通信
菩提小狗10 小时前
Sqli-Labs Less-3 靶场完整解题流程解析-豆包生成
前端·css·less
澄江静如练_10 小时前
优惠券提示文案表单项(原生div写的)
前端·javascript·vue.js