原生js实现轮播图

 原生js实现轮播图,说难不难,说简单不简单。基础套路还是来复习一下吧。先看图。

 先看html结构!很简单!

    <div class="slider">
      <div class="slide-item slide-item-1">1</div>
      <div class="slide-item slide-item-2">2</div>
      <div class="slide-item slide-item-3">3</div>
      <div class="slide-item slide-item-4">4</div>
    </div>

 来分析一下轮播图的css逻辑。

轮播图容器,重点  position:relative;overflow: hidden;其他样式可以自定义

.slider {
  width: 100%;
  height: 300px;
  position: relative;
  overflow: hidden;
  margin: 0 auto;
}

轮播图子项,重点 left:-100%达到隐藏效果。

.slide-item {   
  display: inline-block;
  width: 100%;
  height: 100%;
  position: absolute;
  left: -100%;    /*  隐藏  */
}
.slide-item:first-child {    /*  首项不隐藏  */
  left: 0;
}

写划入划出动画(下一张动画效果),包括反向划入划出动画(上一张动画效果)

@keyframes slideIn {
  from { left: 100%; }
  to { left: 0; }
}
@keyframes slideOut {
  from { left: 0; }
  to { left: -100%; }
}
@keyframes slideInReverse {
  from { left: -100%; }
  to { left: 0; }
}
@keyframes slideOutReverse {
  from { left: 0; }
  to { left: 100%; }
}

 

 

一切工具准备齐全。来上大刀,js!

轮播图的逻辑很简单。首先整理轮播的元素items。假设现在有五个轮播元素。可以将items划分为两个数组。

1.  activeIndex = [0,1]   //  activeIndex[0] 表示当前元素的下标  ,activeIndex[1] 表示下一个将划入的元素下标     

2.  waitIndex = [2,3,4]  // waitIndex表示等待轮播队列


  let slider = document.querySelector('.slider')
  let slideItems = slider.getElementsByClassName('slide-item');
  let activeIndex = [0, 1]
  let waitIndex = []
  
  if (slideItems.length > 2) {
    for (let i = 2; i < slideItems.length; i++) {
      waitIndex.push(i)
    }
  }

接下来追加轮播小点点和左右方向箭头dom元素

  function initDotAndArrow(num) {
    let str = '<div class="dot-panel">'
    for (let i = 0; i < num; i++) {
      if (i === 0) {
        str += '<div class="dot dot-active"></div>'
      } else {
        str += '<div class="dot"></div>'
      }
    }
    str += '</div>'
    str += `<div class="arrow-panel pre-panel">
                <div class="arrow left-arrow"></div>
              </div>
              <div class="arrow-panel next-panel">
                <div class="arrow right-arrow"></div>
              </div>`
    let old = slider.innerHTML
    slider.innerHTML = old + str
  }
  initDotAndArrow(slideItems.length)

 

先定义一些变量,方便轮播的后续操作

  let pre = slider.getElementsByClassName('left-arrow')[0]
  let next = slider.getElementsByClassName('right-arrow')[0]
  let dot = slider.getElementsByClassName('dot')
  let slideIn = 'slideIn 2s ease forwards'
  let slideOut = 'slideOut 2s ease forwards'
  let slideInReverse = 'slideInReverse 2s ease-in-out forwards'
  let slideOutReverse = 'slideOutReverse 2s ease-in-out forwards'
  let ticker;

 

这样有了activeIndex 和waitIndex 这两个数组,一切都清晰明了了,实现轮播这个动作就是去操作这两个数组。

轮播的动作可以切割为四个子动作即几个函数:下一张 / 上一张 / 开始 / 停止

1. 下一张:进场目标是activeIndex[1],  退场目标是activeIndex[0]。为这两个目标增加动画。进退场完毕,需要改变activeIndex,waitIndex了。

  function toNext() {

    let current = activeIndex[0]
    let target = activeIndex[1]
    slideItems[current].style.animation = slideOut
    slideItems[target].style.animation = slideIn

    activeIndex[0] = target
    activeIndex[1] = waitIndex.length > 0 ? waitIndex[0] : current

    if (waitIndex.length > 0) {
      waitIndex.push(current)
      waitIndex.splice(0, 1)
    }

    dot[current].className = 'dot'
    dot[target].className = 'dot dot-active'
  }

2. 上一张:进场目标是waitIndex末尾(需要判断waitIndex是否为空数组),退场目标是activeIndex[0]。为这两个目标增加动画

  function toPre() {

    let current = activeIndex[0]
    let next = activeIndex[1]
    let target = waitIndex.length > 0 ? waitIndex[waitIndex.length - 1] : activeIndex[1]

    slideItems[current].style.animation = slideOutReverse
    slideItems[target].style.animation = slideInReverse

    activeIndex[0] = target
    activeIndex[1] = current

    if (waitIndex.length > 0) {
      for (let i = 0; i < waitIndex.length; i++) {
        let f = waitIndex[i] - 1
        waitIndex[i] = f < 0 ? slideItems.length - 1 : f
      }
    }

    dot[current].className = 'dot'
    dot[target].className = 'dot dot-active'
  }

3.开始轮播

  function play() {
    ticker = setInterval(function () {
      toNext()
    }, duration)
  }

4.停止轮播

function pause() {
    clearInterval(ticker)
}

轮播事件构建完成了。加上DOM操作吧

  pre.onclick = function () {
    toPre()
  }
  next.onclick = function () {
    toNext()
  }
  slider.onmouseenter = function () {
    clearInterval(ticker)
  }
  slider.onmouseleave = function () {
    play()
  }

 

 

 

 

最后整一个轮播函数如下

function cl_slider(obj) {
  const D = document
  let slider = D.querySelector(obj.element)
  let slideItems = slider.getElementsByClassName('slide-item');
  let activeIndex = [0, 1]
  let waitIndex = []
  let duration = obj.duration?obj.duration:4500
  
  if (slideItems.length > 2) {
    for (let i = 2; i < slideItems.length; i++) {
      waitIndex.push(i)
    }
  }

  function initDotAndArrow(num) {
    let str = '<div class="dot-panel">'
    for (let i = 0; i < num; i++) {
      if (i === 0) {
        str += '<div class="dot dot-active"></div>'
      } else {
        str += '<div class="dot"></div>'
      }
    }
    str += '</div>'
    str += `<div class="arrow-panel pre-panel">
                <div class="arrow left-arrow"></div>
              </div>
              <div class="arrow-panel next-panel">
                <div class="arrow right-arrow"></div>
              </div>`
    let old = slider.innerHTML
    slider.innerHTML = old + str
  }
  initDotAndArrow(slideItems.length)

  let pre = slider.getElementsByClassName('left-arrow')[0]
  let next = slider.getElementsByClassName('right-arrow')[0]
  let dot = slider.getElementsByClassName('dot')
  let slideIn = 'slideIn 2s ease forwards'
  let slideOut = 'slideOut 2s ease forwards'
  let slideInReverse = 'slideInReverse 2s ease-in-out forwards'
  let slideOutReverse = 'slideOutReverse 2s ease-in-out forwards'
  let ticker;

  function play() {
    ticker = setInterval(function () {
      toNext()
    }, duration)
  }

  function toNext() {

    let current = activeIndex[0]
    let target = activeIndex[1]
    slideItems[current].style.animation = slideOut
    slideItems[target].style.animation = slideIn

    activeIndex[0] = target
    activeIndex[1] = waitIndex.length > 0 ? waitIndex[0] : current

    if (waitIndex.length > 0) {
      waitIndex.push(current)
      waitIndex.splice(0, 1)
    }

    dot[current].className = 'dot'
    dot[target].className = 'dot dot-active'
  }

  function toPre() {

    let current = activeIndex[0]
    let next = activeIndex[1]
    let target = waitIndex.length > 0 ? waitIndex[waitIndex.length - 1] : activeIndex[1]

    slideItems[current].style.animation = slideOutReverse
    slideItems[target].style.animation = slideInReverse

    activeIndex[0] = target
    activeIndex[1] = current

    if (waitIndex.length > 0) {
      for (let i = 0; i < waitIndex.length; i++) {
        let f = waitIndex[i] - 1
        waitIndex[i] = f < 0 ? slideItems.length - 1 : f
      }
    }

    dot[current].className = 'dot'
    dot[target].className = 'dot dot-active'
    console.log(activeIndex, waitIndex);
  }


  play()
  pre.onclick = function () {
    toPre()
  }
  next.onclick = function () {
    toNext()
  }
  slider.onmouseenter = function () {
    clearInterval(ticker)
  }
  slider.onmouseleave = function () {
    play()
  }
}

 

调用方法也很简单。

let myslider = cl_slider({
  element: '.slider', // 轮播图容器
  duration: 2500, // 播放间隔(ms),默认4500ms
})

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值