50天50个小项目 (React19 + Tailwindcss V4) ✨| BackgroundSlider(背景滑块)

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

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

构建一个全屏、背景模糊变暗、中间高亮显示的图片轮播组件。用户可以通过左右按钮切换图片,并带有缩放动画效果。

🌀 组件目标

  • 展示一组全屏背景图
  • 每张图中央有"高亮"展示区域
  • 支持左右按钮切换图片
  • 添加缩放动画提升视觉体验
  • 使用 TailwindCSS 快速构建现代 UI 界面

🔧 BackgroundSlider.tsx组件实现

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

interface ImageItem {
    id: number
    className: string
}

const BackgroundSlider: React.FC = () => {
    const [currentIndex, setCurrentIndex] = useState(0)
    const [isAnimating, setIsAnimating] = useState(false)

    const imageList: ImageItem[] = [
        {
            id: 1,
            className:
                'bg-[url(https://images.unsplash.com/photo-1495467033336-2effd8753d51?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2100&q=80)]',
        },
        {
            id: 2,
            className:
                'bg-[url(https://images.unsplash.com/photo-1522735338363-cc7313be0ae0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2689&q=80)]',
        },
        {
            id: 3,
            className:
                'bg-[url(https://images.unsplash.com/photo-1559087867-ce4c91325525?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2100&q=80)]',
        },
    ]

    const nextImage = () => {
        setIsAnimating(true)
        setCurrentIndex((prev) => (prev + 1) % imageList.length)
    }

    const prevImage = () => {
        setIsAnimating(true)
        setCurrentIndex((prev) => (prev - 1 + imageList.length) % imageList.length)
    }

    // 监听 transitionend 事件(通过副作用模拟)
    useEffect(() => {
        const handleTransitionEnd = () => {
            setIsAnimating(false)
        }

        // 注意:由于 Tailwind 的 transform 是内联 style 控制,我们无法直接监听 DOM 元素的 transitionend,
        // 所以这里用一个简单延迟代替(或可绑定 ref 到具体元素并 addEventListener)
        const timer = setTimeout(handleTransitionEnd, 500) // 与 duration-500 一致

        return () => clearTimeout(timer)
    }, [currentIndex])

    return (
        <div className="relative h-screen overflow-hidden text-white">
            {/* 背景图片变暗效果 */}
            <div
                className={`absolute inset-0 origin-center bg-cover bg-center brightness-50 transition-transform duration-500 ease-in-out ${
                    imageList[currentIndex].className
                }`}
                style={{
                    transform: isAnimating ? 'scale(1.2)' : 'scale(1)',
                }}
            />

            {/* 中间亮框 */}
            <div className="absolute inset-0 flex items-center justify-center">
                <div
                    className={`relative h-3/4 w-3/4 bg-cover bg-center brightness-100 ${
                        imageList[currentIndex].className
                    }`}
                />
            </div>

            {/* 切换按钮 */}
            <button
                onClick={prevImage}
                className="absolute top-1/2 left-4 -translate-y-1/2 rounded-full bg-white/30 p-4 text-white transition-all hover:bg-white/50"
                aria-label="Previous image">
                &lt;
            </button>
            <button
                onClick={nextImage}
                className="absolute top-1/2 right-4 -translate-y-1/2 rounded-full bg-white/30 p-4 text-white transition-all hover:bg-white/50"
                aria-label="Next image">
                &gt;
            </button>
            <div className="fixed right-20 bottom-5 text-2xl text-red-500">CSDN@Hao_Harrision</div>
        </div>
    )
}

export default BackgroundSlider

🔧 转换说明

功能/概念 Vue 3 (Composition API) 示例代码 React (TS + Hooks) 示例代码
状态管理 使用 ref 来定义响应式变量,如 currentIndexisAnimating 使用 useState 来定义组件的状态,例如 const [currentIndex, setCurrentIndex] = useState(0)
模板渲染 <template> 标签内的 HTML 结构 JSX 语法,直接在 return 中使用 HTML 类似的结构
类名动态绑定 使用 :class 动态绑定类名 在 JSX 中通过字符串模板或条件运算符来实现
内联样式动态绑定 使用 :style 动态应用样式 JSX 中通过对象形式的 style 属性来动态应用样式
事件处理 使用 @click 简写进行事件监听 使用 onClick 等属性直接绑定事件处理器
生命周期钩子/副作用 使用 onMounted, watch, 或者组合式 API 进行逻辑处理 使用 useEffect 钩子处理副作用和模拟生命周期行为
循环/列表渲染 使用 v-for 指令遍历数组 使用 .map() 方法遍历数组并返回 JSX 元素
计算属性 可以通过 computed 创建依赖其他响应式数据的计算结果 直接在需要的地方使用 JavaScript 表达式,或者使用 useMemo
方法定义 定义在 setup 函数内部的方法 在函数组件内部直接定义方法,或者使用 useCallback 来优化性能
过渡/动画 使用 Vue 的 <transition> 组件与 @transitionend 监听器 使用 setTimeout 模拟,或通过 ref 获取 DOM 节点添加事件监听器

🎨 TailwindCSS 样式重点讲解

类名 作用
h-screen, overflow-hidden 全屏高度并隐藏溢出内容
absolute inset-0 铺满整个父容器
bg-cover, bg-center 图片自适应铺满并居中
brightness-50, brightness-100 调整明暗对比度
origin-center 设置缩放中心点
transition-transform duration-500 ease-in-out 添加平滑的缩放动画
flex items-center justify-center 居中布局
hover:bg-white/50 鼠标悬停改变透明度
rounded-full 圆形按钮样式
[🎯 TailwindCSS 样式说明]

这些 Tailwind 工具类帮助我们快速构建了一个极具视觉冲击力的全屏轮播组件。

🦌 路由组件 + 常量定义

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

TypeScript 复制代码
{
    path: '/',
    element: <App />,
    children: [
       ...
       {
                path: '/BackgroundSlider',
                lazy: () =>
                    import('@/projects/BackgroundSlider.tsx').then((mod) => ({
                        Component: mod.default,
                    })),
            },
    ],
 },

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

TypeScript 复制代码
import demo18Img from '@/assets/pic-demo/demo-18.png'
省略部分....
export const projectList: ProjectItem[] = [
    省略部分....
     {
        id: 18,
        title: 'BackgroundSlider',
        image: demo18Img,
        link: 'BackgroundSlider',
    },

🚀 小结

这个卡片涵盖了React的响应式系统、动画控制、按钮交互以及 TailwindCSS 的强大样式能力。它非常适合用于网站主页、作品集展示、产品介绍等需要突出视觉表现的场景。

  • 你可以进一步扩展的功能包括:

  • 自动播放功能(定时切换)

  • 添加底部导航圆点指示器

  • 支持键盘左右键切换

  • 支持移动端滑动手势切换

  • 支持主题切换(暗色/亮色)

📅 明日预告: 我们将完成ThemeClock组件,非常简约的始终组件可以切换主题以及显示时间。🚀

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

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

相关推荐
weixin_307779134 小时前
Jenkins Font Awesome API插件:现代化插件界面的图标引擎
开发语言·前端·自动化·jenkins
June bug4 小时前
【Vue】从0开始使用Vue构建界面
前端·vue.js·前端框架
IT_陈寒5 小时前
SpringBoot3.0性能优化:这5个冷门配置让我节省了40%内存占用
前端·人工智能·后端
霍理迪5 小时前
常用块标签和三种列表
前端·html
kesteler5 小时前
v-model的使用
前端·javascript·vue.js
Zhi.C.Yue5 小时前
React 的桶算法详解
前端·算法·react.js
果壳~5 小时前
【前端】【canvas】【pixi.js】水波纹滤镜实现教程 - 支持随机波动与鼠标交互
前端·javascript
han_5 小时前
手把手教你写一个VSCode插件,从开发到发布全流程
前端·javascript·visual studio code
爱吃大芒果5 小时前
Flutter 状态管理全家桶:Provider、Bloc、GetX 实战对比
开发语言·前端·javascript·flutter·华为·ecmascript