react组件轮播图

轮播图实现的思路,当我们的图片自动向左轮播的时候,当轮播到最后一张图片时,我们要让他从第一张图片开始轮播,并且需要跟最后一张图片衔接上,才是一个完整的轮播图

首先我们在根组件中封装两个组件

import Swiper from '../lunbo/Swper';
import SwiperItem from '../lunbo/SwperITtem';

function App() {
  return (
    <div className="App">

        <Swiper autoplay={true} loop={true}>
            <SwiperItem>
              <img src="https://img.alicdn.com/imgextra/i2/26958996/O1CN010NKdKC2GKDl4rmWjn_!!0-saturn_solar.jpg_468x468q75.jpg_.webp"/>
            </SwiperItem>
            <SwiperItem>
              <img src="https://img.alicdn.com/imgextra/i2/119181013/O1CN01UBWPhA1JLzxX8yEOC_!!0-saturn_solar.jpg_468x468q75.jpg_.webp"/>
            </SwiperItem>
            <SwiperItem>
              <img src="https://img.alicdn.com/imgextra/i3/98494397/O1CN0138Jp1m1iLsBqwct3T_!!0-saturn_solar.jpg_468x468q75.jpg_.webp"/>
            </SwiperItem>
        </Swiper>
    </div>
  );
}
export default App;

Swiper是我们包裹图片的盒子组件,SwiperItem是图片组件

Swiper传递的两个参数,当autoplay为true时,图片自动进行轮播,loop为true的话,那么就复制第一张图片的dom节点

SwiperItem组件

import React from 'react'

export default function Item(props) {
    
  return (
    <li>
        {props.children}
    </li>
  )
}

Swiper组件

import React, { Component } from 'react'
import './index.scss'

export default class Index extends Component {
    constructor() {
        super()
        this.state = {
            index:0,
            acIndex:0
        }
        
    }
    refDom = React.createRef()
    refAd = React.createRef()
    refImgs = React.createRef()
    // 生命周期
    componentDidMount() {
        if(this.props.loop) {
            // 如果传过来的loop为true,那么就复制第一张图片的dom节点,cloneNode为true是不仅获取dom节点,还要获取dom节点下的所有标签
            let cloneLi = this.refImgs.current.firstElementChild.cloneNode(true)
            this.refImgs.current.appendChild(cloneLi)
        }
        // 如果接收到autoplay为true,那么就自动轮播
        if(this.props.autoplay) {
            setInterval(()=>{
               this.right()
            },1000)
        }
    }
    animationFn=(ele,target)=> {
        // 设置周期性定时器
        clearInterval(ele.timer)
        ele.timer = setInterval(() =>{
            // 正方向还是负方向
            // 每次进行加10,box.offsetLeft距离左侧距离,动态读取
            let speed = target>ele.offsetLeft?10:-10
            let value = target - ele.offsetLeft  // 差值
            // 如果差值小于步骤距离,那么清理定时器
            if(Math.abs(value) < Math.abs(speed)) {
                // 清楚定时器
                clearInterval(ele.timer)
                // 将移动误差还原成目标的距离
                ele.style.left = target
                // 如果走到最后一张之后
                // console.log(this.state.index,this.props.children.length)
                if(this.state.index >= this.props.children.length && this.props.loop){
                    this.state.index = 0
                    this.setState({
                        index:this.state.index
                    })
                    this.refImgs.current.style.left = 0 // 一瞬间变成0
                }
                return false
            }
            // 设置,每次进行加或者减
            ele.style.left = speed + ele.offsetLeft + "px"
        }, 10);

    }
    // 右按钮
    right=()=> {
        this.state.index ++
        this.setState({
            index:this.state.index
        })
        if(this.props.loop) {
            this.animationFn(this.refImgs.current,-this.state.index*490)     
        } else {
            console.log(this.state.index,this.props.children.length)
            if(this.state.index>=this.props.children.length-1) {        
                this.state.index = this.props.children.length-1
                this.setState({
                    index:this.state.index
                },()=>{
                    this.animationFn(this.refImgs.current,-this.state.index*490)
                })  
            }          
        }      
    }
    // 左按钮
    left =()=> {          
            this.state.index --
            if(this.state.index < 0) {
                if(this.props.loop) {
                    // alert("已经到第一张了")
                    this.state.index = this.props.children.length-1
                    this.refImgs.current.style.left = -(this.state.index+1)*490 +"px" // 一瞬间变成最后的位置
                } else {
                    this.state.index = 0
                }       
            }
            console.log(this.state.index)
            this.setState({
                index:this.state.index
            },()=>{
                this.animationFn(this.refImgs.current,-this.state.index*490)
            })   
    }
    render() {
        console.log(this.props)
        // 创建空数组,主要来做的是nav,index
        let arr = []
        for(let i =1;i<this.props.children.length+1;i++) {
            arr.push(i)
        }
        return (
        <div className='swipercom'>
            <div id="box" ref={this.refDom} className="all">
            <div className="ad" ref={this.refAd}>
                <ul id="imgs" ref={this.refImgs}>
                   {
                    this.props.children
                   }
                </ul>
                <ol>
                    {
                        arr.map((item,index)=>{
                            return (
                                <li key={index} className={this.state.index === index?'active':''}>{item}</li>
                            )
                        })
                    }
                </ol>
            </div>
            <div id="arr">
                <span id="left" onClick={this.left}>&lt;</span>
                <span id="right" onClick={this.right}>&gt;</span>
            </div>
        </div>
        </div>
        )
    }
}

scss样式

body,
ul,
ol,
li,
img {
    margin: 0;
    padding: 0;
    list-style: none;
}

#box {
    width: 490px;
    height: 170px;
    padding: 5px;
    position: relative;
    border: 1px solid #ccc;
    margin: 0 auto 0;
}

.ad {
    width: 490px;
    height: 170px;
    position: relative;
    overflow: hidden;
}

#box img {
    width: 490px;
}

.ad ol {
    position: absolute;
    right: 10px;
    bottom: 10px;
}

.ad ol li {
    width: 20px;
    height: 20px;
    line-height: 20px;
    border: 1px solid #ccc;
    text-align: center;
    background: #fff;
    float: left;
    margin-right: 10px;
    cursor: pointer;
    _display: inline;
}

.ad ol li.current {
    background: yellow;
}

.ad ul li {
    float: left;
}

.ad ul {
    position: absolute;
    top: 0;
    width: 2940px;
}

.ad ul li.current {
    display: block;
}

#arr {
    display: block;
}

#arr span {
    width: 40px;
    height: 40px;
    position: absolute;
    left: 5px;
    top: 50%;
    margin-top: -20px;
    background: #000;
    cursor: pointer;
    line-height: 40px;
    text-align: center;
    font-weight: bold;
    font-family: '黑体';
    font-size: 30px;
    color: #fff;
    opacity: 0.3;
    border: 1px solid #fff;
}

#arr #right {
    right: 5px;
    left: auto;
}

.active {
    color: red;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值