首页 > 其他分享 >前端实现简单轮播图,js实现一个无缝轮播图

前端实现简单轮播图,js实现一个无缝轮播图

时间:2023-05-10 12:45:30浏览次数:36  
标签:activeIndex style const 轮播 timer js length children 无缝

吐槽 公司首页有一个动态显示数据的板块,同事直接用定时器手动修改div里面的数据,后来要求要有一个动态轮播滚动效果。哎,没办法,加入这个项目后就是在优化改写别人的代码,以前没测试到的bug,现在测出来让我修复,以前没实现的功能让我去实现。一堆简单堆砌的代码,重复用到的地方就是再复制一份,改起来都头大,只能自己一个一个重写再封装成组件。

  这个轮播图组件只是简单练手,实际最好使用成熟的swiper库。

js文件

/* eslint-disable react/no-array-index-key */
/**
* @file 简易轮播图组件,建议直接使用swiper库(https://github.com/nolimits4web/swiper, https://swiperjs.com/react)
* @author Anin
* @lastEditors 
*/
import React, { FC, memo, useEffect, useState } from 'react'
import './index.less';
interface AnSwiperProps {
    items?: any[];
    speed?: number;
    autoplay?: boolean;
    paginationRender?: any;
    slidesPerView?: number; //  同时显示的slides数量

}
export interface AnSwiperType extends FC<AnSwiperProps> {
    AnSwiperSlide: FC<any>
}
let timer: NodeJS.Timer | null = null;
let length = 0;
let activeIndex = 0;
const AnSwiper: AnSwiperType = ({ autoplay = true, speed = 3000, slidesPerView = 1, paginationRender, children }) => {
    const [index, setIndex] = useState(activeIndex);
    // 无缝切换
    const next = () => {
        const wrapperDom: HTMLDivElement = document.querySelector('.AnSwiper-wrapper');
        activeIndex = activeIndex + 1
        wrapperDom.style.transition = 'transform 0.5s ease'
        wrapperDom.style.transform = `translateX(-${activeIndex * (100 / slidesPerView)}%)`
        if (activeIndex >= length) {
            setTimeout(() => {
                wrapperDom.style.transition = 'none'
                wrapperDom.style.transform = 'translateX(0%)'
                activeIndex = 0
                setIndex(0)
            }, 500);

            return;
        }
        setIndex(activeIndex)
    }
    const prev = () => {
        const wrapperDom: HTMLDivElement = document.querySelector('.AnSwiper-wrapper');
        activeIndex = activeIndex - 1
        wrapperDom.style.transition = 'transform 0.5s ease'
        wrapperDom.style.transform = `translateX(-${activeIndex * (100 / slidesPerView)}%)`
        if (activeIndex <= 0) {
            setTimeout(() => {
                wrapperDom.style.transition = 'none'
                wrapperDom.style.transform = `translateX(-${length * (100 / slidesPerView)}%)`
                activeIndex = length
                setIndex(length)
            }, 500);
            return;
        }
        setIndex(activeIndex)
    };
    const start = () => {
        if (timer) {
            clearInterval(timer);
            timer = null;
        }
        timer = setInterval(next, speed);
    }
    // 鼠标划入
    const handleMouseOver = () => {
        if (timer) {
            clearInterval(timer);
            timer = null;
        }
    };
    // 鼠标划出
    const handleMouseLeave = () => {
        if (!timer && length > 1) {
            start()
        }
    };
    useEffect(() => {
        document.body.style.setProperty('--slidesPerView', `${100 / slidesPerView}%`);
        if (children) {
            if (Array.isArray(children)) {
                length = children.length;
                if (autoplay && children?.length > 0) {
                    start()
                }
            } else if (typeof children === 'object') {
                length = 1
            }
        }
        return () => {
            if (timer) {
                clearInterval(timer);
                timer = null;
            }
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [autoplay, children])
    console.log(index)
    return (<div className='AnSwiper' onm ouseOver={handleMouseOver} onm ouseLeave={handleMouseLeave}>
        <div className='AnSwiper-wrapper' >
            {children?.[children?.length - 1]}
            {children}
            {children?.[0]}
        </div>
        {paginationRender && <ul className='pagination-wrap'>
            {
                ([... new Array(length)].map((_, i) => (
                    <div key={i} onClick={()=> {
                        activeIndex = i+ 1;
                        setIndex(i + 1)
                        document.querySelector('.AnSwiper-wrapper').style.transform = `translateX(-${(i+1) * (100 / slidesPerView)}%)`
                        }}>
                        {/* {paginationRender((i +1) === index) || (i === length -1) } */}
                        {paginationRender(i === index -1 || (index === 0 && i === length -1))}
                    </div>
                )

                ))
            }
        </ul>
        }
    </div>)
}
function ANSwiperSlide({ children }) {
    return <div className='AnSwiper-slide'>{children}</div>
}
// AnSwiper.AnSwiperSlide = AnSwiperSlide
export const AnSwiperSlide = memo(ANSwiperSlide);
export default memo(AnSwiper);

 less 文件

.AnSwiper {
    width: 100%;
    height: fit-content;
    position: relative;
    overflow: hidden;

    .AnSwiper-wrapper {
        display: flex;
        // transition: transform 0.5s ease;
        transform: translateX(-100%);

        .AnSwiper-slide {
            // width: 30%;
            flex: 0 0 var(--slidesPerView);
        }
    }

    .pagination-wrap {
        position: absolute;
        padding-left: 35px;
        bottom: 0;
        width: 100%;
    }
}

 使用

import AnSwiper, { AnSwiperSlide } from '@/components/AnSwiper';

const App = () => {
  const list = [
  {
    name: '1',
    icon: 'icon'
  },
  {
    name: '2',
    icon: 'icon'
  },
  {
    name: '3',
    icon: 'icon'
  },
  {
    name: '4',
    icon: 'icon'
  },

] reutrn (<div> <AnSwiper paginationRender={(isActive)=> { return <li className={`pagination ${isActive ? 'tabs-active': 'tabs-item'}`}></li> }} > {list.map((item)=> ( <AnSwiperSlide key={item?.name}> <div className='banner-box'> <img className="banner-img-cock" src={item.icon} /> </div> </AnSwiperSlide>))} </AnSwiper> ) </div>) }

 css

 .tabs-item {
        width: 12px;
        height: 4px;
        border-radius: 4px;
        float: left;
        margin-right: 4px;
        background: #d4e5ff;
        cursor: pointer;
    }

    .tabs-active {
        width: 12px;
        height: 4px;
        border-radius: 4px;
        float: left;
        margin-right: 4px;
        background: #2468f2;
        cursor: pointer;
    }

 style.setProperty 方法用来动态改变样式。有时候不能通过动态添加修改类名的方式改变样式的时候,使用style.setProperty方法就能很好的解决这个问题

标签:activeIndex,style,const,轮播,timer,js,length,children,无缝
From: https://www.cnblogs.com/anin/p/17387646.html

相关文章

  • 微信小程序 app.json 里 "style": "v2" 的作用
    新版微信小程序的app.json文件中多了一个:style":"v2"{"pages":["pages/index/index","pages/logs/logs"],"window":{"backgroundTextStyle":"light","navigationBarBac......
  • requests标头在json序列化时报错TypeError: Object of type CaseInsensitiveDict is n
    requests的作者似乎为了解决header里大小写兼容的问题,而创建了大小写不敏感的数据结构CaseInsensitiveDict,具体分析可以参见:详解Requests中的数据结构CaseInsensitiveDict。requests返回的response_header即是一个CaseInsensitiveDict类型,而且我们知道response_header里通常并非......
  • jsp内置对象
    九大内置对象:request、response、session、application、page、pageContext、out、config、exception。四大作用域:page、request、session、application作用域的有效期限:page作用域的变量只在当前页面中有效,只要页面跳转了,page域中的变量重新计算。request里的变量可以跨越forw......
  • 实现一个js平滑滚动到顶部的小功能
    //平滑滚动到顶部// scrollDom出现滚动条,要滚动的元素//speed平滑滚动的速度number类型const scrollToTopSmooth =(scrollDom, speed) => {  let scrollTop = scrollDom.scrollTop  function move(){    scrollTop -= speed    scrollDom.s......
  • C#-JSON详解
      最近在做微信开发时用到了一些json的问题,就是把微信返回回来的一些json数据做一些处理,但是之前json掌握的不好,浪费了好多时间在查找一些json有关的转换问题,我所知道的方法只有把json序列化和反序列化一下,但是太麻烦了我觉得,所以就在找一些更简单又方便使用的方法。也许这个会......
  • nodejs
    node.js学习笔记1fs模块概念fs全称为filesystem,称之为文件系统,是Node.js中的内置模块,可以对计算机中的磁盘进行操作。文件写入文件写入就是将数据保存到文件中,我们可以使用如下几个方法来实现该效果方法说明writeFile异步写入writeFileSync同步写入......
  • 利用NewtonSoft.Json的JsonScheme校验数据格式
    推送的报文信息,需要校验格式是否正确,必传的是否传了,字符串长度是否超长。之前是把报文反序列化为类后,一个字段一个字段进行校验。JsonSchema可以一次性校验校验对象的格式,如下:{"type":"object","properties":{"soId":{"type":"string",......
  • js基础---事件
    事件的概念与使用方法js标签引入的时机......
  • 用print-js实现打印功能时element table组件打印不全的问题
    插件下载:npminstall--saveprint-js解决方案,修改print.js里面的 getHtml//打印类属性、方法定义/*eslint-disable*/constPrint=function(dom,options){  if(!(thisinstanceofPrint))returnnewPrint(dom,options);  this.options=this.exten......
  • Python获取jsonp数据
    使用python爬取数据时,有时候会遇到jsonp的数据格式,由于不是json的,所以不能直接使用json.loads()方法来解析,需要先将其转换为json格式,再进行解析。在前面讲了jsonp的原理,这里就略过一部分。jsonp的格式jsonp的内容一般是这样的:callback({"name":"zhangsan","age":18......