简介:
用react开发的轮播图组件,支持淡入淡出、水平滚动、垂直滚动的无缝轮播效果。可自定义轮播内容。
API
参数 | 作用 | 必传 | 数值 | 默认值 | 备注 |
---|---|---|---|---|---|
type | 轮播模式 | 否 | opacity淡入淡出,moveHorizontal横向移动,moveVertical纵向移动 | moveHorizontal | opacity类型暂不支持自定义轮播内容 |
data | 需要渲染的数据 | 单标签需要传,双标签不需要传 | [ ] | ||
stepWidth | 每屏切换的宽度(px) | 否 | 1200 | ||
showItemNum | 每屏显示的个体数量 | 否 | 1 | ||
intervalTime | 每屏切换的时间间隔(ms) | 否 | 3000 | ||
autoRun | 自动播放 | 否 | left向左,right向右,up向上,down向下,不写或者false禁止自动播放 | 禁止 | left、right对应moveHorizontal,up、down对应moveVertical |
hoverStop | 鼠标悬浮时,是否停止播放 | 否 | true悬浮停止,不写或者false悬浮不停止 | 悬浮时不停止 | |
point | 底部是否显示轮播进度 | 否 | true显示,false隐藏 | true |
示例1.默认轮播
import Slider from '../../../../../plugin/component/Slider/Slider'
...
<div className='slider-box'>
<Slider
type='opacity'
data={sliderData}
stepWidth={960}
showItemNum={1}
intervalTime={4000}
autoRun='right'
hoverStop={true}
point />
</div>
企业微信截图_15102163287693.png
示例2.自定义轮播
import Slider from '../../../../../plugin/component/Slider/Slider'
...
<div className='slider-box'>
<Slider stepWidth={960} >
{
sliderData2.map((item, index) => {
return (
<li>
<a href={item.href} target='_blank'>
<img src={item.img} alt={item.alt} />
</a>
</li>
)
})
}
</Slider>
</div>
企业微信截图_15102163581813.png
目录结构:
企业微信截图_15102145191107.png文件说明:
1.Slider.js 入口文件
import SliderMove from './src/SliderMove'
import SliderOpacity from './src/SliderOpacity'
class Slider extends React.Component {
render () {
let {type} = this.props
return type === 'opacity'
? <SliderOpacity {...this.props} />
: <SliderMove {...this.props} />
}
}
export default Slider
2.SliderMove.js 横向 / 纵向滚动
import './slider.less'
class SliderMove extends React.Component {
constructor (props) {
super(props)
this.sliderInterval = null
this.state = {
sliderIndex: 1,
thisMoveOver: true// 本次轮播是否结束,未结束前,不可进行下次操作
}
}
moveEnd () {
let {showItemNum} = this.props
let len = this.props.children || this.props.data
let thisIndex = this.state.sliderIndex
if (thisIndex > Math.ceil(len.length / showItemNum)) {
this.sliderList.style.transition = 'none'
this.sliderList.style.webkitTransition = 'none'
this.setState({
sliderIndex: 1
})
}
if (thisIndex <= 0) {
this.sliderList.style.transition = 'none'
this.sliderList.style.webkitTransition = 'none'
this.setState({
sliderIndex: Math.ceil(len.length / showItemNum)
})
}
console.log(1)
this.setState({thisMoveOver: true})
}
// 向左
turnLeftHandle () {
console.log(this.state.thisMoveOver)
if (this.state.thisMoveOver) {
this.sliderList.style.transition = 'all 0.5s linear'
this.setState((preState, props) => ({
sliderIndex: preState.sliderIndex + 1,
thisMoveOver: false
}))
}
}
// 向右
turnRightHandle () {
if (this.state.thisMoveOver) {
this.sliderList.style.transition = 'all 0.5s linear'
this.setState((preState, props) => ({
sliderIndex: preState.sliderIndex - 1,
thisMoveOver: false
}))
}
}
// 清除定时器
clearSliderInterval () {
clearInterval(this.sliderInterval)
}
// 重新开始定时器
startSliderInterval () {
let {autoRun, intervalTime} = this.props
if (autoRun !== undefined && autoRun !== false) {
this.clearSliderInterval()
this.sliderInterval = setInterval(() => {
switch (autoRun) {
case 'right':
case 'down':
this.turnRightHandle()
break
case 'left':
case 'up':
this.turnLeftHandle()
break
default:
return false
}
}, intervalTime)
}
}
// 判断用户是否正在浏览当前页面
onVisibilityChanged (e) {
let hidden = e.target.hidden
if (hidden) {
clearInterval(this.sliderInterval)
} else {
this.startSliderInterval()
}
}
componentDidMount () {
this.sliderList.addEventListener('transitionend', this.moveEnd.bind(this, 0), false)
document.addEventListener('visibilitychange', this.onVisibilityChanged.bind(this), false)
this.startSliderInterval()
}
render () {
let {children, data, stepWidth, hoverStop, point, showItemNum, type} = this.props
let {sliderIndex} = this.state
let sliderData = children || data || []
let showNum = showItemNum || 1
let startData = sliderData.slice(0, showNum)
let endData = sliderData.slice(sliderData.length - showNum, sliderData.length)
let mapData = [...endData, ...sliderData, ...startData]
return (
<div className='slider-will'
onMouseOver={() => { hoverStop && this.clearSliderInterval() }}
onMouseOut={() => { this.startSliderInterval() }}>
<div className='slider-cont'>
<div className='turn-btn turn-left' onClick={() => { this.turnRightHandle() }} />
<ul className={type === 'moveVertical' ? 'slider-ul-move-vertical' : 'slider-ul-move-horizontal'}
ref={(sliderList) => (this.sliderList = sliderList)}
style={{[type === 'moveVertical' ? 'top' : 'left']: `${-sliderIndex * (stepWidth || 1200)}px`}}
>
{
children ? mapData : mapData.map((item, index) => {
return (
<li key={`slider-${index}`}>
<a href={item.href} target='_blank'>
<img src={item.img} alt={item.alt} />
</a>
</li>
)
})
}
</ul>
<div className='turn-btn turn-right' onClick={() => { this.turnLeftHandle() }} />
</div>
{point === false ? ''
: <ul className='slider-point-box'>
{
sliderData.map((item, index) => {
if (index % showItemNum === 0) {
return (
<li key={`slider-point-${index}`}
className={this.state.sliderIndex === (index / showItemNum + 1) ? 'select-point' : ''}
onClick={() => { this.setState({sliderIndex: index + 1}) }}
>
<a href='javascript:void(0);' />
</li>
)
}
})
}
</ul>
}
</div>
)
}
}
export default SliderMove
3.SliderOpacity.js 淡入淡出
import './slider.less'
class SliderOpacity extends React.Component {
constructor (props) {
super(props)
this.sliderInterval = null
this.state = {
sliderIndex: 0,
thisMoveOver: true// 本次轮播是否结束,未结束前,不可进行下次操作
}
}
moveEnd () {
this.setState({thisMoveOver: true})
}
// 向左
turnLeftHandle () {
let len = this.props.children || this.props.data
this.setState((preState, props) => ({
sliderIndex: preState.sliderIndex - 1 < 0 ? len.length - 1 : preState.sliderIndex - 1,
thisMoveOver: false
}))
}
// 向右
turnRightHandle () {
let len = this.props.children || this.props.data
this.setState((preState, props) => ({
sliderIndex: preState.sliderIndex + 1 > len.length - 1 ? 0 : preState.sliderIndex + 1,
thisMoveOver: false
}))
}
// 清除定时器
clearSliderInterval () {
clearInterval(this.sliderInterval)
}
// 重新开始定时器
startSliderInterval () {
let {autoRun, intervalTime} = this.props
if (autoRun !== undefined && autoRun !== false) {
this.clearSliderInterval()
this.sliderInterval = setInterval(() => {
switch (autoRun) {
case 'left':
this.turnLeftHandle()
break
case 'right':
this.turnRightHandle()
break
default:
return false
}
}, intervalTime)
}
}
// 判断用户是否正在浏览当前页面
onVisibilityChanged (e) {
let hidden = e.target.hidden
if (hidden) {
clearInterval(this.sliderInterval)
} else {
this.startSliderInterval()
}
}
componentDidMount () {
document.addEventListener('visibilitychange', this.onVisibilityChanged.bind(this), false)
this.startSliderInterval()
}
render () {
let {children, data, stepWidth, hoverStop, point, showItemNum} = this.props
let {sliderIndex} = this.state
let mapData = children || data || []
return (
<div className='slider-will'
onMouseOver={() => { hoverStop && this.clearSliderInterval() }}
onMouseOut={() => { this.startSliderInterval() }}>
<div className='slider-cont'>
<div className='turn-btn turn-left' onClick={() => { this.turnLeftHandle() }} />
<ul className='slider-ul-opacity'>
{
children ? mapData : mapData.map((item, index) => {
return (
<li key={`slider-${index}`} className={sliderIndex === index ? 'selected-slider-item' : ''}>
<a href={item.href} target='_blank'>
<img src={item.img} alt={item.alt} />
</a>
</li>
)
})
}
</ul>
<div className='turn-btn turn-right' onClick={() => { this.turnRightHandle() }} />
</div>
{point === false ? ''
: <ul className='slider-point-box'>
{
mapData.map((item, index) => {
return (
<li key={`slider-point-${index}`}
className={this.state.sliderIndex === index ? 'select-point' : ''}
onClick={() => { this.setState({sliderIndex: index}) }}
>
<a href='javascript:void(0);' />
</li>
)
})
}
</ul>
}
</div>
)
}
}
export default SliderOpacity
4.slider.less 样式文件
@import "../../../../plugin/less/class.less";
@imgSrc:'@{webpath_cn}activity/17-double11/';
.slider-will{
width:100%;
height:100%;
position: relative;
.slider-cont{
width:100%;
height:100%;
position: relative;
z-index: 0;
overflow: hidden;
&:hover{
.turn-btn{
display: block;
z-index: 3;
}
}
}
.turn-btn{
position: absolute;
top:50%;
.translate(0,-50%);
width:47px;
height: 67px;
cursor: pointer;
z-index: -1;
display: none;
}
.turn-left{
left:0;
background:rgba(0,0,0,.5) url("@{imgSrc}turn_left.png") no-repeat center;
}
.turn-right{
right:0;
background:rgba(0,0,0,.5) url("@{imgSrc}turn_right.png") no-repeat center;
}
.slider-ul-move-horizontal{
width: max-content;
height:100%;
position: absolute;
left:0;
top:0;
.transition();
&>li{
display: table-cell;
}
}
.slider-ul-move-vertical{
width:100%;
height:max-content;
position: absolute;
left:0;
top:0;
.transition();
&>li{
display: block;
}
}
.slider-ul-opacity{
width:100%;
height:100%;
position: relative;
z-index: 1;
&>li{
position: absolute;
left:0;
top:0;
opacity: 0;
z-index: -1;
.transition();
}
.selected-slider-item{
opacity: 1;
z-index: 2;
}
}
.slider-point-box{
border-radius: 10px;
position: absolute;
bottom: 15px;
height: 13px;
text-align: center;
font-size: 0;
left: 50%;
.translate(-50%);
background-color: rgba(255,255,255,.3);
&>li{
display: inline-block;
margin: 3px;
a{
display: block;
padding-top: 8px;
width: 8px;
height: 0;
border-radius: 50%;
background: #fff;
}
}
.select-point{
a{
background: #ff5000;
}
}
}
}
网友评论