js 轮播图(使用class实现)

js 轮播图(使用class实现)

纯属无聊,还花了一晚上时间o(╥﹏╥)o

1. js部分的代码
/**
 * 判断对象是否为DOM元素
 * @param {Object} obj
 * @returns
 */
const isDOM = (obj) => (typeof HTMLElement === 'object')
  ? obj instanceof HTMLElement
  : obj && typeof obj === 'object' &&
    (obj.nodeType === 1 || obj.nodeType === 9) &&
    typeof obj.nodeName === 'string'

const createDom = (className = '', tag = 'div') => {
  const ele = document.createElement(tag)
  ele.className = className
  return ele
}

// 返回0-num之间的数
const getRandomInt = (num) => Math.floor(Math.random() * num)
// eslint-disable-next-line no-unused-vars
const getDom = (selector, all = false) => {
  return all ? document.querySelectorAll(selector) : document.querySelector(selector)
}
class LoopImages {
  constructor (container, srcArr, config) {
    // 默认配置
    this.config = {
      loop: true, // 是否循环播放
      autoPlay: true, // 是否自动播放
      random: false, // 随机播放
      arrowAlwaysShow: false,
      duration: 3000 // 自动播放间隔
    }
    // 覆盖默认配置
    Object.assign(this.config, config)
    // 初始化容器,如果container为DOM对象则直接赋值,否则根据选择器查找
    if (isDOM(container)) {
      this.container = container
    } else {
      this.container = document.querySelector(container)
    }
    // 如果容器不存在
    if (!isDOM(this.container)) {
      throw new Error('未找到容器')
    }
    // 循环播放图片的地址数组
    if (!!srcArr && !(srcArr instanceof Array)) {
      throw new Error('srcArr 为数组')
    }
    this.srcArr = srcArr || []
    this.length = this.srcArr.length
    // 当前播放到的位置
    this.current = 0
    // 初始化内部的容器
    this.init()
    // 自动播放
    this.config.autoPlay && this.autoPlay()
  }

  get _length () {
    return this.length
  }

  get _srcArr () {
    return this.srcArr
  }

  set _srcArr (value) {
    if (!(this.srcArr instanceof Array)) {
      throw new Error('srcArr 为数组')
    }
    this.srcArr = value
    this.length = this.srcArr.length
  }

  get _current () {
    return this.current
  }

  set _current (value) {
    let errMsg
    if (isNaN(Number(value))) {
      errMsg = 'current 必须为数字'
    }
    if (errMsg) {
      throw new Error(errMsg)
    }
    this.current = Math.min(this.length - 1, value)
    this.setCurrent()
    this.rePlay()
  }

  render () {
    if (this.container && this.container.hasChildNodes()) {
      return
    }
    // 渲染DOM
    this.initImageList()
    this.initCircleBtn()
    this.initArrowBtn()

    this.setCurrent()
    this.addEventListener()

    this.container && this.container.appendChild(this.loopImgBox)
  }

  // 设置当前circleBtn和图片
  setCurrent () {
    const that = this
    ;(this.cricleBtnList || []).forEach((btn, index) => {
      index === that.current ? btn.classList.add('current') : btn.classList.remove('current')
    })
    ;(this.loopImgList || []).forEach((img, index) => {
      index === that.current ? img.classList.add('current') : img.classList.remove('current')
    })
  }

  init () {
    if (this.loopImgBox) {
      return
    }
    const loopImgBox = document.createElement('div')
    loopImgBox.className = 'loop-img-box'
    this.loopImgBox = loopImgBox
  }

  // 初始化next,prev按钮
  initArrowBtn () {
    // 生成容器
    if (this.arrowBtnBox) {
      return
    }
    const arrowBtnBox = createDom('arrow-btn-box')
    this.arrowBtnBox = arrowBtnBox
    const prev = createDom('arrow-btn arrow-btn-prev')
    this.prevBtn = prev
    const next = createDom('arrow-btn arrow-btn-next')
    this.nextBtn = next
    if (this.config.arrowAlwaysShow) {
      prev.classList.add('arrow-always-show')
      next.classList.add('arrow-always-show')
    }
    arrowBtnBox.appendChild(prev)
    arrowBtnBox.appendChild(next)

    this.loopImgBox && this.loopImgBox.appendChild(arrowBtnBox)
  }

  initCircleBtn () {
    if (this.circleBtnBox) {
      return
    }
    const circleBtnBox = createDom('circle-btn-box')
    this.circleBtnBox = circleBtnBox
    // 循环生成小圆点, this.length 为当前图片链接数组的长度
    this.cricleBtnList = []
    for (let i = 0; i < this.length; i++) {
      const circleBtn = createDom('circle-btn circle-btn-' + i)
      this.cricleBtnList.push(circleBtn)
      circleBtnBox.appendChild(circleBtn)
    }

    this.loopImgBox && this.loopImgBox.appendChild(circleBtnBox)
  }

  // 图片数组
  initImageList () {
    if (this.loopImgList) {
      return
    }
    const loopImgListBox = createDom('loop-img-list')
    this.loopImgList = []
    this.loopImgListBox = loopImgListBox
    Array.from(this.srcArr).forEach(src => {
      // eslint-disable-next-line no-unused-vars
      // const linkA = createDom('loop-img-link', 'a')
      // linkA.setAttribute('href', '')
      const img = createDom('loop-img-item', 'img')
      img.setAttribute('src', src)
      this.loopImgList.push(img)
      loopImgListBox.appendChild(img)
    })

    this.loopImgBox && this.loopImgBox.appendChild(loopImgListBox)
  }

  // 更新视图
  update () {

  }

  addEventListener () {
    this.prevBtn && (this.prevBtn.onclick = (e) => {
      e.stopPropagation()
      this.prev()
    })
    this.nextBtn && (this.nextBtn.onclick = (e) => {
      e.stopPropagation()
      this.next()
    })
    ;(this.cricleBtnList || []).forEach((btn, index) => {
      btn.onclick = () => ((i) => {
        this._current = i
      })(index)
    })
  }

  autoPlay () {
    if (this.config.autoPlay) {
      // 自动播放
      this.autoPlayInterval = setInterval(() => {
        this.config.random ? this.random() : this.next()
      }, this.config.duration)
    }
  }

  stopAutoPlay () {
    clearInterval(this.autoPlayInterval)
  }

  rePlay () {
    this.stopAutoPlay()
    this.autoPlay()
  }

  next () {
    // xia一张
    const current = this.current + 1
    if (current === this.length) {
      if (this.config.loop) {
        this._current = (current) % this.length
      }
    } else {
      this._current = (current) % this.length
    }
  }

  prev () {
    // shang一张
    let current = this.current
    if (this.current === 0) {
      if (this.config.loop) {
        current = this.length
        this._current = (current - 1) % this.length
      }
    } else {
      this._current = (current - 1) % this.length
    }
  }

  random () {
    // 随机一张
    let rand = getRandomInt(this.length)
    while (rand === this.current) {
      rand = getRandomInt(this.length)
    }
    this._current = rand
  }
}
module && (module.exports = {
  LoopImages
})
2. css 部分的样式

文件里的 …/img/prev.png 这张小图标如果觉得不大行的话直接到阿狸图标上找一张代替就行

…/img/prev.png

../img/prev.png

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
.loop-img-box {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
}

.loop-img-list {
  width: 100%;
  height: 100%;
  position: relative;
}

.loop-img-item {
  display: none;
  width: 100%;
  height: 100%;
}

.loop-img-item.current {
  display: block;
}


.circle-btn-box {
  position: absolute;
  display: flex;
  justify-content: space-between;
  width: 46px;
  bottom: 10px;
  left: calc(50% - 46px / 2);
}

.circle-btn {
  cursor: pointer;
  width: 10px;
  height: 10px;
  border: 1px solid #afafaf;
  border-radius: 50%;
}

.circle-btn.current {
  background: #272841;
}

.arrow-btn-box {
  width: 100%;
  height: 40px;
  display: flex;
  justify-content: space-between;
  top: calc(50% - 20px);
  position: absolute;
}
.arrow-btn-box:hover .arrow-btn {
  background-image: url('../img/prev.png');
}

.arrow-always-show {
  background-image: url('../img/prev.png');
}

.arrow-btn-prev {
  cursor: pointer;
  width: 30px;
  height: 100%;
  /*background-image: url('../img/prev.png');*/
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}

.arrow-btn-next {
  cursor: pointer;
  width: 30px;
  height: 100%;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  transform: rotate(180deg);
}

.arrow-btn-next:hover, .arrow-btn-prev:hover {
  background-image: url('../img/prev.png');
}
3. 使用
<template>
  <div>
    <div class="loop-img-container" ref="loopImg"></div>
  </div>
</template>
<script>
const { LoopImages } = require('@/assets/js/utils')
export default {
  mounted () {
    const loopImg = new LoopImages(this.$refs.loopImg, [
      require('@/assets/logo.png'),
      require('@/assets/img/prev.png'),
      require('@/assets/logo.png'),
      require('@/assets/img/prev.png')
    ], {
      arrowAlwaysShow: true,
    })
    loopImg.render()
  }
}
</script>
<style scoped>
.loop-img-container {
  width: 90%;
  border: 1px solid #1f1f1f;
  height: 200px;
  margin: 20px auto;
}
</style>

4. 效果

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值