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

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

相关推荐
用户69371750013843 小时前
Google 正在“收紧侧加载”:陌生 APK 安装或需等待 24 小时
android·前端
蓝帆傲亦4 小时前
Web 前端搜索文字高亮实现方法汇总
前端
用户69371750013844 小时前
Room 3.0:这次不是升级,是重来
android·前端·google
漫随流水5 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
踩着两条虫6 小时前
VTJ.PRO 核心架构全公开!从设计稿到代码,揭秘AI智能体如何“听懂人话”
前端·vue.js·ai编程
jzlhll1237 小时前
kotlin Flow first() last()总结
开发语言·前端·kotlin
蓝冰凌8 小时前
Vue 3 中 defineExpose 的行为【defineExpose暴露ref变量】详解:自动解包、响应性与实际使用
前端·javascript·vue.js
奔跑的呱呱牛8 小时前
generate-route-vue基于文件系统的 Vue Router 动态路由生成工具
前端·javascript·vue.js
柳杉8 小时前
从动漫水面到赛博飞船:这位开发者的Three.js作品太惊艳了
前端·javascript·数据可视化