原生JS轮播-各种效果的极简实现

Posted 海客无心x

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原生JS轮播-各种效果的极简实现相关的知识,希望对你有一定的参考价值。

寒假持续摸鱼中~此为老早以前博客的重写,当时还是分开写的,这里汇总重写,正好复习一遍~

春招我来了!
所有有意思的,一股脑先扔进收藏,然后再也不看哈哈,真是糟糕。
今日事,今日毕,说起来容易。
当时竟然不是用markdown写的!
当时使用var还需要解决必报的问题!而如今使用ES6的let,自带领域的感觉就是不一样!

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    * {
      margin: 0;
      padding: 0;
    }
    ul, li {
      list-style: none;
    }
    body {
      background-color: #000;
    }
    .wrap {
      position: relative;
      border: 8px solid #fff;
      margin: 100px auto;
      width: 400px;
      height: 250px;
      overflow: hidden;
    }
    .pic-group {
      position: absolute;
      top: -250px;
    }
    .pic-group li img {
      display: block;
      width: 100%;
      height: 100%;
    }
  </style>
</head>
<body>
  <div class="wrap">
    <ul class="pic-group">
      <li><img src="./pic1.jpg" alt=""></li>
      <li><img src="./pic2.jpg" alt=""></li>
      <li><img src="./pic3.jpg" alt=""></li>
      <li><img src="./pic4.jpg" alt=""></li>
      <li><img src="./pic5.jpg" alt=""></li>
    </ul>
    <ol class="num-group">
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
    </ol>
  </div>
</body>
</html>

一.轮播是什么?

轮播其实就是一个定时变换的广告(卡片?图片?)。
在HTML结构上他们其实是ul里面的li。数据层面来说的话,他们就是list的一条数据。

那么,这其中的变换其实也可以有很多种~你可能会知道现在的 vue-swiper这么绚丽的轮播效果

  • 缓冲效果 --- 透明度变化(意味着一开始所有的item刚开始都是叠在一起的)
  • 滑动效果 --- position top位置的变化(意味着所有的item单/竖/横向排列)

二.变化和上述的代码分析 --- 改变 top 则切换图片。

如上面的代码,只搭了个结构,我们看到wrap层被设为了 1.position:relative2.overflow:hidden,本质上是为了子层的pic-group服务的,我们设子层pic-group3.position:absolute,这样的话 3 就可以根据 1和2 来达到 => 改变top位置(top位置为图片高度的 n 倍哦!)

为了极简!!!!!我这里只设置了 .pic-group li img 的宽高。一般情况下其实每个外层元素都会写一个具体的高宽的。

  • 为什么我给.pic-group li img 设置 display:block ?

    实际上呢,img 它是行内元素。行内元素有默认的 4px 边距。去除的办法有 font-size:0等诸多方法,这里我追求代码极简。所以一句话,变成块级元素吧少年。

  • 为什么我只给.pic-group li img 设置了 宽高?

    依旧为了极简~实际上应该根据要求都设置一下宽高的。这里的结果就是
    a.内层 img 宽高继承了最外的 400 250
    =>
    b.继而作为 li 的子层撑开了 li
    =>
    c.li 再继续撑开 .pic-group
    =>
    d.因为.pic-group的高度被老大的overflow:hidden限制了,最后就变成了一张图片。
    原来的样子应该是好几层图片~

技术分享图片

三.变化的契机 --- 谁来改变 top?

我们给我们的轮播案例加上数字,通过点击数字来按下改变世界的开关!
首先这是我们给数字添加的样式

.num-group {
      position: absolute;
      bottom: 0;
      right: 0;
      height: 20px;
    }
    .num-group li {
      float: left;
      width: 20px;
      height: 20px;
      line-height: 20px;
      font-size: 10px;
      margin-right: 10px;
      background-color: #089e8a;
      color: #eee;
      text-align: center;
      border-radius: 10px;
      cursor: pointer;
      opacity: 0.8;
    }
    .num-group li:hover {
      box-shadow: 0 0 18px #000;
    }
    .num-group li.current {
      opacity: 1;
      color: #089a8a;
      background-color: #000;
    }

这里就不多解释了,上面是是样式的部分。
下面是JS的部分

// 首先,获取我们要改变的元素
const oImage = document.getElementsByClassName("pic-group")[0];
// 其次,获取改变世界的钥匙
const oNumber = document.getElementsByClassName("num-group")[0];
const numList = oNumber.getElementsByTagName("li");
// 接下来,便是世界改变的逻辑
for (let i = 0; i < numList.length; i++) {
  // 关键:我们要把我们的 索引index 传进 onclick/onmouseover 里面
  numList[i].onclick = () => {
    // numList[i].className = "current";
    clearNumState();
    numList[i].className = "current";
    const topValue = - i * 250;
    oImage.style.top = topValue + "px";
  }
}
// 每次新点击 num,先置空所有list的current的类,此后再添加当前索引
const clearNumState = () => {
  for (const item of numList) {
    item.className = "";
  }
}
通过上面的代码我们已经可以实现点击数字按钮进行对图片的切换了.

改变世界的最终还是 JS,而不是CSS,我们用JS给数字们添加上事件。
技术分享图片
技术分享图片

4.用户体验为王! -- 缓冲的轮播

点击不能立马切换图片系列

时代在进步,刀耕火种的JS --- 谈谈重写之前用var,重写之后用let的变化

不用纠结闭包的问题了!!!!
哦草!
我他妈竟然忘了!

秀一秀古老的onclick

  for (var i = 0; i < oList.length; i++) {
    oList[i].onclick = function () {
      console.log(i);
    }
  }

这样写的后果是,无论怎么写,最后的i的结果都会是oList.length
闭包(匿名函数)要使用外部作用于中变量的结果,这也是由于匿名函数本身无法传递参数,
故无法维护自己的作用域。
当函数调用外部变量就构成一个闭包,里面的变量会受到别的地方的影响。不可抗力!所以解决的方式是:构建一个只有匿名函数本身才可以访问的闭包,保存只供本身使用的变量。

  • 古老的解决方案一.使用过去的 function 式函数,将 当前的 i 赋值给 index

      for (var i = 0; i < oList.length; i++) {
    oList[i].index = i;
    oList[i].onclick = function () {
      console.log(this.index);
    }
      }
  • 古老的解决方案二.使用匿名函数的方式隔离外部的i => 匿名函数:这就是我的领域,魔法-画地为牢!!!

      for (var i = 0; i < oList.length; i++) {
    (function (i) {
      oList[i].onclick = () => {
        console.log(i);
      }
    })(i);
      }
  • 然而我是现代人,能坐车我干嘛要走路???So !

      for (let i = 0; i < oList.length; i++) {
    oList[i].onclick = () => {
      console.log(i);
    }
      }

    正所谓四两拨千斤!什么?你说没差别? var -> let
    归根结底还是作用域的问题,let 是自带领域的。

最终代码如下

github地址

以上是关于原生JS轮播-各种效果的极简实现的主要内容,如果未能解决你的问题,请参考以下文章

js原生 JavaScript轮播图渐变淡入淡出效果实现(附代码)

原生js实现一个简单轮播效果

原生JS实现过渡效果的轮播图

使用原生js实现轮播图效果

原生js面向对象实现简单轮播

原生js实现轮播图