轮播图实现的思路,当我们的图片自动向左轮播的时候,当轮播到最后一张图片时,我们要让他从第一张图片开始轮播,并且需要跟最后一张图片衔接上,才是一个完整的轮播图
首先我们在根组件中封装两个组件
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}><</span>
<span id="right" onClick={this.right}>></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;
}