前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JS实现超简易轮播图

JS实现超简易轮播图

作者头像
治电小白菜
修改2023-09-23 15:13:15
10.2K0
修改2023-09-23 15:13:15
举报
文章被收录于专栏:技术综合

0.示例

预览地址: https://codepen.io/klren0312/full/ymvEbr

2

1.画界面

1.画显示区域

首先就是画个固定的区域, 用来展示轮播图当前能看到的图, 其余超出的部分, 使用 overflow: hidden 隐藏.

代码语言:javascript
复制
.box {
  width: 300px;
  height: 200px;
  overflow: hidden;
}
代码语言:javascript
复制
<div class="box"></div>
2.画轮播图主体

假设五张图, 将他们横向排列(图片太麻烦, 我就css画了, 有些样式可以忽略)

image.png

代码语言:javascript
复制
.swiper {
  position: relative;
  width: 1500px;
  height: 200px;
}

.swiper .swiper-item {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 300px;
  height: 100%;
  float: left;
  box-sizing: border-box;
  background: #efefef;
  border: 1px solid #333;
}

// 两个div区分一下
.swiper .swiper-item:nth-child(2n) {
  background: #fff;
}
代码语言:javascript
复制
<div class="box">
  <div class="swiper">
    <div class="swiper-item">1</div>
    <div class="swiper-item">2</div>
    <div class="swiper-item">3</div>
    <div class="swiper-item">4</div>
    <div class="swiper-item">5</div>
  </div>
</div>

这样, 样式部分就搞定了

2.轮播JS代码

1.原理

由于轮播图已经横向排列, 所以只要控制.swiper向x轴偏移距离, 就可以实现图片切换, 这里使用transformtranslate属性来控制x轴偏移.可以通过transition来设置过渡动画

问题与难点: 当轮播图到达最后一个图片时, 需要平滑切换到第一张, 如果没有过渡动画倒无所谓, 否则将会出现从最后一张快速倒回第一张的动画, 降低体验.

解决方法: 初始化的时候, 复制第一位图片放在最后一位;复制原来最后一位图片, 放到第一位.当然如果你只往右切换, 则不用将第一位放在最后一位.示例如下(数字代表图片顺序): 初始排列:

代码语言:javascript
复制
|1|2|3|4|5|

初始化后排列:

代码语言:javascript
复制
|5|1|2|3|4|5|1|
2.代码片段

代码使用ES6语法, 这些无所谓, 具体逻辑知道就行

1.构造器

构造器接收一个变量, 切换轮播图的延时.

在构造器里新建了一些常量, 轮播图的DOM, 轮播图片的DOM数组, 轮播图的个数(注意是没有初始化前的图片个数), 以及赋值延时(默认是1000ms)

随后调用初始化函数

代码语言:javascript
复制
constructor (delay = 1000) {
  this.swiper = document.querySelector('.swiper') // 轮播图
  this.swiperItemList = document.querySelectorAll('.swiper-item') // 轮播项
  this.totalLength = this.swiperItemList.length // 轮播图个数
  this.delay = delay
  this.init()
}
2.初始化函数

复制第一位图片放在最后一位;复制原来最后一位图片, 放到第一位;即 12345 => 5123451. 随后, 将轮播图显示的位置定在第一张图片位置, 即1的位置 currentPosition变量用于标记当前滚动的图片

代码语言:javascript
复制
init () {
  // 将轮播图第一项克隆, 并放在最后
  const cloneFirst = document.querySelectorAll('.swiper-item')[0].cloneNode(true)
  this.swiper.appendChild(cloneFirst)
  // 因为 totalLength 是原始的轮播图个数, 所以可以正确定位到原来的轮播图最后一个
  const cloneLast = document.querySelectorAll('.swiper-item')[this.totalLength - 1].cloneNode(true)
  this.swiper.insertBefore(cloneLast, this.swiper.firstChild)
  // 设置轮播图总长, 加上新加的两个
  this.swiper.style.width = (this.totalLength + 2) * 300 + 'px'
  // 当前轮播图位置分布为  5 12345 1
  // 初始化轮播图为 1 位置
  this.currentPosition = 1
  this.swiper.style.transform = `translateX(${-this.currentPosition * 300}px`
}
3.滚动动画

滚动时, 给.swiper标记一个isAnimating的class,来标明正在滚动. 给.swiper设置x轴偏移位置, 以及添加过渡动画. 滚动的延时使用设定的delay, 延时结束后, 清除过渡动画(过渡动画的清除, 主要给后面最后一位跳到第一位时用)和isAnimating标记

代码语言:javascript
复制
goSlider () {
  // 添加过渡效果, delay 需要一致; 位置偏移一个单位
  this.swiper.style.transition = `transform ${this.delay / 1000}s ease`
  this.swiper.style.transform = `translateX(${-this.currentPosition * 300}px`
  // 添加正在切换的class, 给上面 animate 方法用来判断
  this.swiper.classList.add('isAnimating')
  // 切换结束, 清空状态, 清空过渡效果
  setTimeout(() => {
    this.swiper.style.transition = ''
    this.swiper.classList.remove('isAnimating')
  }, this.delay)
}
4.轮播操作

判断滚动的位置, 若在最后一位即第5位, 则将定位改为与之相同的第0位, 并进行偏移.然后将位数加1, 到第1位. 此时没有过渡动画, 就实现了最后一位5和第一位5的快速切换, 然后过渡到第1位;

currentPosition设置为1后, 进入到切换动画, 这样视觉上就是5过渡到1

代码语言:javascript
复制
animate () {
  // 如果正在切换, 则不动
  if (this.swiper.classList.contains('isAnimating')) return
  // 如果在第五项, 则将定位改为第 0 项, 并设置位置, 此时没有 transition 动画, 秒切
  if (this.currentPosition === this.totalLength) {
    this.currentPosition = 0
    this.swiper.style.transform = `translateX(${-this.currentPosition * 300}px`
  }
  // 将位置设为第一项
  this.currentPosition++
  // 轮播
  setTimeout(() => {
    this.goSlider()
  }, 20)
}
5.轮播开始

循环调用轮播操作函数

代码语言:javascript
复制
start () {
  setInterval(() => this.animate(),this.delay)
}

3.使用这个轮播class

代码语言:javascript
复制
window.onload = function () {
  const slider = new SliderBox(2000)
  slider.start()
}

4.整体代码

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    .box {
      width: 300px;
      height: 200px;
      overflow: hidden;
    }

    .swiper {
      position: relative;
      width: 1500px;
      height: 200px;
    }

    .swiper .swiper-item {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 300px;
      height: 100%;
      float: left;
      box-sizing: border-box;
      background: #efefef;
      border: 1px solid #333;
    }

    .swiper .swiper-item:nth-child(2n) {
      background: #fff;
    }
  </style>
</head>

<body>
  <div class="box">
    <div class="swiper">
      <div class="swiper-item">1</div>
      <div class="swiper-item">2</div>
      <div class="swiper-item">3</div>
      <div class="swiper-item">4</div>
      <div class="swiper-item">5</div>
    </div>
  </div>
  <script>
    class SliderBox {
      /**
       * 构造器
       * @param {number} delay 切换延时
       */
      constructor(delay = 1000) {
        this.swiper = document.querySelector('.swiper') // 轮播图
        this.swiperItemList = document.querySelectorAll('.swiper-item') // 轮播项
        this.totalLength = this.swiperItemList.length // 轮播图个数
        this.delay = delay
        this.init()
      }
      /**
       * 初始化配置
       */
      init() {
        // 将轮播图第一项克隆, 并放在最后
        const cloneFirst = document.querySelectorAll('.swiper-item')[0].cloneNode(true)
        this.swiper.appendChild(cloneFirst)
        // 因为 totalLength 是原始的轮播图个数, 所以可以正确定位到原来的轮播图最后一个
        const cloneLast = document.querySelectorAll('.swiper-item')[this.totalLength - 1].cloneNode(true)
        this.swiper.insertBefore(cloneLast, this.swiper.firstChild)
        // 设置轮播图总长, 加上新加的两个
        this.swiper.style.width = (this.totalLength + 2) * 300 + 'px'
        // 当前轮播图位置分布为  5 12345 1
        // 初始化轮播图为 1 位置
        this.currentPosition = 1
        this.swiper.style.transform = `translateX(${-this.currentPosition * 300}px`
      }
      /**
       * 切换动画
       */
      animate() {
        // 如果正在切换, 则不动
        if (this.swiper.classList.contains('isAnimating')) return
        // 如果在第五项, 则将定位改为第 0 项, 并设置位置, 此时没有 transition 动画, 秒切
        if (this.currentPosition === this.totalLength) {
          this.currentPosition = 0
          this.swiper.style.transform = `translateX(${-this.currentPosition * 300}px`
        }
        // 将位置设为第一项
        this.currentPosition++
        // 轮播
        setTimeout(() => {
          this.goSlider()
        }, 20)
      }
      /**
       * 轮播
       */
      goSlider() {
        // 添加过渡效果, delay 需要一致; 位置偏移一个单位
        this.swiper.style.transition = `transform ${this.delay / 1000}s ease`
        this.swiper.style.transform = `translateX(${-this.currentPosition * 300}px`
        // 添加正在切换的class, 给上面 animate 方法用来判断
        this.swiper.classList.add('isAnimating')
        // 切换结束, 清空状态, 清空过渡效果
        setTimeout(() => {
          this.swiper.style.transition = ''
          this.swiper.classList.remove('isAnimating')
        }, this.delay)
      }
      /**
       * 开始轮播
       */
      start() {
        setInterval(() => this.animate(), this.delay)
      }
    }
  </script>
  <script>
    window.onload = function () {
      const slider = new SliderBox(2000)
      slider.start()
    }
  </script>
</body>

</html>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0.示例
  • 1.画界面
    • 1.画显示区域
      • 2.画轮播图主体
      • 2.轮播JS代码
        • 1.原理
          • 2.代码片段
            • 1.构造器
          • 2.初始化函数
            • 3.滚动动画
              • 4.轮播操作
                • 5.轮播开始
                • 3.使用这个轮播class
                • 4.整体代码
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档