React如何自定義輪播圖Carousel組件
自定義輪播圖Carousel組件
需求:
要求0-1自定義輪播圖組件,默認(rèn)自動翻頁,無限翻頁,允許點擊翻頁,底部有動畫進度條,且可配置輪播時間,可以操作Children.
架構(gòu)
React: ^18.0. Hooks. Css. FunctionComponent
- React : ^18.0 //未使用其他第三方庫
- Hooks //進行狀態(tài)管理 模塊化設(shè)計
- Css //進行樣式分離,xxx.module.css. 局部作用域樣式。防止Css全局污染 函數(shù)式編程.
需求解析
可點擊 + 可定義輪博時間 + 可無限輪播項 + 動畫進度條 + 可配置輪播圖單項內(nèi)容 + 業(yè)務(wù)定制化
- 可點擊:允許用戶點擊底部進度條進行對應(yīng)索引翻頁
- 可定義輪播時間:當(dāng)前默認(rèn)為3秒,可以根據(jù)業(yè)務(wù)來調(diào)節(jié)時間 3000ms = 3s
- 可無限輪播項:useEffect 進行監(jiān)聽 并進行相應(yīng)的操作 實現(xiàn)無線輪播
- 動畫進度條:底色 #0000001a 黑色+10%的透明度 固定寬度,動畫顏色為 #FFFFFF 動態(tài)寬度
.css{ animation-name: progressBar; // 指定要綁定到選擇器的關(guān)鍵幀的名稱 name = progressBar animation-fill-mode: forwards; // 指定動畫在執(zhí)行時間之外應(yīng)用的值 forwards = 保留最后一個關(guān)鍵幀設(shè)置的樣式值 animation-iteration-count: infinite; // 指定動畫播放的次數(shù) infinite = 播放無限次 animation-duration: 3s // 一個周期所需的時間長度 3s = 3秒 }
可配置輪播圖單項內(nèi)容:React.Children.map 和 React.cloneElement
需求解決
一、import Carousel, { CarouselItem, CarouselInfo } from “./Carousel”;
import React, { useState, useEffect } from "react"; import style from "./carousel.module.css"; /** * @param {children} children ReactNode * @param {width} width 寬度 * @param {height} height 高度 * @param {styles} styles 樣式 * @returns 輪播圖 單項 */ export const CarouselItem = ({ children = React.createElement("div"), width = "100%", height = "100%", styles = {}, }) => { return ( <div className={style.carousel_item} style={{ width: width, height: height, ...styles }} > {children} </div> ); }; /** * @param {title} title 標(biāo)題 * @param {describe} describe 描述 * @param {image} image 圖片 * @returns 輪播圖 主體 */ export const CarouselInfo = ({ title = "", describe = "", image = "" }) => { return ( <div className="carousel_info_container"> <div className="carousel_info_info"> <h1>{title}</h1> <span>{describe}</span> </div> <div className="carousel_info_image_container"> <img src={image} alt="Jay" className="carousel_info_image" /> </div> </div> ); }; /** * @param {children} children ReactNode * @param {switchingTime} switchingTime 間隔時間 默認(rèn)3秒 以毫秒為單位 3000ms = 3s * @returns 輪播圖 容器 */ const Carousel = ({ children = React.createElement("div"), switchingTime = 3000, }) => { const time = ((switchingTime % 60000) / 1000).toFixed(0); // 將毫秒轉(zhuǎn)換為秒 const [activeIndex, setActiveIndex] = useState(0); // 對應(yīng)索引 /** * 更新索引 * @param {newIndex} newIndex 更新索引 */ const onUpdateIndex = (newIndex) => { if (newIndex < 0) { newIndex = React.Children.count(children) - 1; } else if (newIndex >= React.Children.count(children)) { newIndex = 0; } setActiveIndex(newIndex); replayAnimations(); }; /** * 重置動畫 */ const replayAnimations = () => { document.getAnimations().forEach((anim) => { anim.cancel(); anim.play(); }); }; /** * 底部加載條點擊事件 * @param {index} index 跳轉(zhuǎn)索引 */ const onClickCarouselIndex = (index) => { onUpdateIndex(index); replayAnimations(); }; useEffect(() => { const interval = setInterval(() => { onUpdateIndex(activeIndex + 1); }, switchingTime); return () => { if (interval) { clearInterval(interval); } }; }); return ( <div className={style.container}> <div className={style.inner} style={{ transform: `translateX(-${activeIndex * 100}%)` }} > {React.Children.map(children, (child) => { return React.cloneElement(child, { width: "100%", height: "100vh" }); })} </div> <div className={style.loading}> {React.Children.map(children, (child, index) => { return ( <div className={style.indicator_outer} onClick={() => onClickCarouselIndex(index)} > <div className={style.indicator_inside} style={{ animationDuration: index === activeIndex ? `${time}s` : "0s", backgroundColor: index === activeIndex ? "#FFFFFF" : null, }} /> </div> ); })} </div> </div> ); }; export default Carousel;
二、import style from “./carousel.module.css”;
.container { overflow: hidden; } .inner { white-space: nowrap; transition: transform 0.3s; } .carousel_item { display: inline-flex; align-items: center; justify-content: center; height: 200px; color: #fff; background-color: #312520; } .loading { position: absolute; bottom: 0; display: flex; flex-direction: row; align-items: center; justify-content: center; margin-bottom: 10px; width: 100%; } .indicator_outer { width: 90px; height: 7px; background-color: #0000001a; margin-left: 20px; border-radius: 5px; } .indicator_inside { height: 100%; border-radius: 5px; animation-fill-mode: forwards; animation-name: progressBar; animation-iteration-count: infinite; } @keyframes progressBar { 0% { width: 0%; } 100% { width: 100%; } }
三、 App.js
import "./App.css"; import React, { useState } from "react"; import JayOne from "./assets/1.jpeg"; import JayTwo from "./assets/2.jpeg"; import JayThree from "./assets/3.jpeg"; import JayFour from "./assets/4.jpeg"; import Carousel, { CarouselItem, CarouselInfo } from "./Carousel"; // 輪播圖數(shù)據(jù) const info = [ { id: 1, title: "Jay", describe: "2000—11—07", image: JayOne, backgroundColor: "#425066", }, { id: 2, title: "范特西", describe: "2001—09—20", image: JayTwo, backgroundColor: "#1bd1a5", }, { id: 3, title: "范特西PLUS", describe: "2001—12—28", image: JayThree, backgroundColor: "#a78e44", }, { id: 4, title: "八度空間", describe: "2002—07—18", image: JayFour, backgroundColor: "#493131", }, ]; const App = () => { return ( <Carousel> {info?.map((item) => { return ( <CarouselItem key={item.id} styles={{ backgroundColor: item.backgroundColor }} > <CarouselInfo title={item.title} describe={item.describe} image={item.image} /> </CarouselItem> ); })} </Carousel> ); }; export default App;
效果圖
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解React??App.js?文件的結(jié)構(gòu)和作用
在React應(yīng)用中,App.js文件通常是項目的根組件文件,它負(fù)責(zé)組織和渲染其他組件,是應(yīng)用的核心部分,本文將詳細(xì)介紹App.js文件的結(jié)構(gòu)、作用和最佳實踐,感興趣的朋友跟隨小編一起看看吧2024-08-08React-Native TextInput組件詳解及實例代碼
這篇文章主要介紹了React-Native TextInput組件詳解及實例代碼的相關(guān)資料,需要的朋友可以參考下2016-10-10react 權(quán)限樹形結(jié)構(gòu)實現(xiàn)代碼
這篇文章主要介紹了react 權(quán)限樹形結(jié)構(gòu)實現(xiàn)代碼,項目背景react + ant design,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-05-05基于visual studio code + react 開發(fā)環(huán)境搭建過程
今天通過本文給大家分享基于visual studio code + react 開發(fā)環(huán)境搭建過程,本文給大家介紹的非常詳細(xì),包括react安裝問題及安裝 Debugger for Chrome的方法,需要的朋友跟隨小編一起看看吧2021-07-07React中的權(quán)限組件設(shè)計問題小結(jié)
這篇文章主要介紹了React中的權(quán)限組件設(shè)計,整個過程也是遇到了很多問題,本文主要來做一下此次改造工作的總結(jié),對React權(quán)限組件相關(guān)知識感興趣的朋友一起看看吧2022-07-07