截止到这里,其实简易的自动轮播就完成了,但是其实很多同学也会有疑问,是不是还缺少分页器(Pagination) 。
5、分页器(Pagination)分页器的原理其实很简单,我们可以分成两个步骤来看 。1、渲染与图片相同个数的节点;2、根据activeIndex动态改变分页样式 。
import React, { FC } from "react";import styled from "styled-components";const SwiperSlideBar = styled.div` margin-top: 16px; width: 100%; height: 4px; display: flex; align-items: center; justify-content: center;`;const SwiperSlideBarItem: any = styled.div` cursor: pointer; width: ${(props: any) => (props.isActive ? "26px" : "16px")}; height: 4px; background: #e6e6e6; margin-right: 6px;`;const SlideBarInner: any = styled.div` width: 100%; height: 100%; background: #0075ff; animation: ${innerFrame} ${(props: any) => `${props.speed}s`} ease;`;{urls?.length > 1 ? ( <SwiperSlideBar> {urls?.map((f: string, index: number) => ( <SwiperSlideBarItem onClick={() => slideToOne(index)} isActive={index === activeIndex} > {index === activeIndex ? <SlideBarInner speed={speed} /> : null} </SwiperSlideBarItem> ))} </SwiperSlideBar>) : null}细心的同学可能看到我在这里为什么还有一个SlideBarInner元素,其实是在这里实现了一个当前所在分页停留时间进度条展示的功能,感兴趣的同学可以自己看一下,我这里就不在赘述了 。
6、整体实现代码最后,我们可以看到完整的Swiper代码如下:
import React, { FC, useEffect, useRef, useState } from "react";import styled, { keyframes } from "styled-components";const innerFrame = keyframes` from { width: 0%; } to { width: 100%; }`;const Swiper = styled.div` overflow: hidden; position: relative;`;const SwiperNextTip = styled.div` position: absolute; top: 50%; transform: translateY(-50%); right: 24px; width: 32px; height: 32px; border-radius: 50%; background: #ffffff70; display: flex; justify-content: center; align-items: center; cursor: pointer; opacity: 0.7; user-select: none; :hover { opacity: 1; background: #ffffff80; }`;const SwiperPrevTip = (styled as any)(SwiperNextTip)` left: 24px;`;const SwiperContainer = styled.div` position: relative; display: flex; align-item: center; justify-content: flex-start; transition: all 0.3s ease; -webkit-transition: all 0.3s ease; -moz-transition: all 0.3s ease; -o-transition: all 0.3s ease;`;const SwiperSlide = styled.div` display: flex; align-item: center; justify-content: center; flex-shrink: 0;`;const SwiperSlideBar = styled.div` margin-top: 16px; width: 100%; height: 4px; display: flex; align-items: center; justify-content: center;`;const SwiperSlideBarItem: any = styled.div` cursor: pointer; width: ${(props: any) => (props.isActive ? "26px" : "16px")}; height: 4px; background: #e6e6e6; margin-right: 6px;`;const SlideBarInner: any = styled.div` width: 100%; height: 100%; background: #0075ff; animation: ${innerFrame} ${(props: any) => `${props.speed}s`} ease;`;const Swiper: FC< { direction?: 'horizontal' | 'vertical'; speed?: number; width: string; height: string; urls: string[]; }> = ({ direction = "horizontal", speed = 3, width = "", height = "", urls = []}) => { const [activeIndex, setActiveIndex] = useState<number>(0); const [isDone, setDone] = useState<boolean>(false); const [swiperStyle, setSwiperStyle] = useState<{ width: string; height: string; }>({ width: (width as string)?.replace("%", "vw"), height: (height as string)?.replace("%", "vh"), } as any); const timer = useRef<any>(null); const swiperContainerRef = useRef<HTMLDivElement>(null); const styles = { width: isNaN(+swiperStyle.width) ? swiperStyle!.width : `${swiperStyle!.width}px`, height: isNaN(+swiperStyle.height) ? swiperStyle.height : `${swiperStyle.height}px`, }; const startPlaySwiper = () => { if (speed <= 0) return; timer.current = setInterval(() => { setActiveIndex((preValue) => preValue + 1); }, speed * 1000); }; const slideToOne = (index: number) => { if (index === activeIndex) return; setActiveIndex(index); clearInterval(timer?.current); startPlaySwiper(); }; useEffect(() => { if (swiperContainerRef?.current) { startPlaySwiper(); } return () => { clearInterval(timer?.current); timer.current = null; }; }, [swiperContainerRef?.current]); useEffect(() => { const swiper = document.querySelector("#swiper-container") as any; if (direction === "vertical") { swiper.style.bottom = (height as string)?.includes("%") ? `${activeIndex * +(height as string)?.replace("%", "")}vh` : `${activeIndex * +height}px`; } else { swiper.style.right = (width as string)?.includes("%") ? `${activeIndex * +(width as string)?.replace("%", "")}vw` : `${activeIndex * +width}px`; } if (activeIndex >= urls.length - 1) { clearInterval(timer?.current); timer.current = null; setDone(true); } }, [activeIndex, urls]); return (<> <Swiper style={{ width, height }}> <SwiperContainer id="swiper-container" ref={swiperContainerRef} style={{ height, // 根据轮播方向参数,调整flex布局方向 flexDirection: direction === "horizontal" ? "row" : "column", }} > {urls.map((f: string, index: number) => ( <SwiperSlide style={{ ...styles }}> <img src=https://www.huyubaike.com/biancheng/{f} style={{ ...styles }} />
经验总结扩展阅读
- React +SpreadJS+Echarts 项目实战:在线报价采购系统
- 四十七 SpringCloud微服务实战——搭建企业级开发框架:【移动开发】整合uni-app搭建移动端快速开发框架-添加Axios并实现登录功能
- 怎么去除电脑上一个mcafee(怎么去除电脑上的小图标)
- 喜欢一个人在空间表白的说说100句 很甜很撩的表白情话
- 表示对某人心寒的句子看清一个人适合发朋友圈
- 一个鸡蛋两块五是什么意思网络用语
- 2023年农历6月搬家好吗
- 一个火龙果的热量是多少
- 每天一个番石榴的危害
- 两个6寸蛋糕和一个8寸哪个大