美文网首页
Slider - 轮播图

Slider - 轮播图

作者: WillLi | 来源:发表于2017-11-09 16:22 被阅读0次

    简介:

    用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;
          }
        }
      }
    }
    

    相关文章

      网友评论

          本文标题:Slider - 轮播图

          本文链接:https://www.haomeiwen.com/subject/hofmmxtx.html