web技术

三种方式实现轮播图功能

2023-07-08 03:49 作者:Admin

手动实现轮播图

使用纯HTML、CSS、JavaScript实现轮播图功能。

position

使用position的绝对定位与相对定位实现轮播图,首先将图片全部拼接成为一行,使用overflow: hidden;将其他图片隐藏,将这一行图片加入定时任务不断进行左移,从而只显示中间的图片,对于边缘特殊处理,将第一张轮播图追加到一行图片之后,当切换到最后一张轮播图时,下一张即播放第一张图,当此图轮播完成后,将所有图片归位,提供两个DEMO,第一个是单纯的轮播不存在任何控制按钮,第二个则比较完善。

实例

<!-- 
    简单DEMO,未实现任何控制,单纯图片轮播 
-->
<!DOCTYPE html>
<html>
  <head>
    <title>轮播图</title>
    <meta charset="utf-8" />
    <meta name="referrer" content="no-referrer" />
  </head>
  <style type="text/css">
    body {
      margin: 0;
      padding: 0px;
    }
    #carousel {
      margin: auto; /* 居中 */
      width: 600px; /* 设置宽度 */
      position: relative; /* 相对定位 */
      overflow: hidden; /* 超出隐藏 */
    }
    #carousel img {
      width: 600px; /* 设定大小 按比例缩放 */
    }
    #carousel > ul {
      display: flex; /* 图片处理为一行 */
      position: absolute; /* 设置绝对定位,实现相对于#carousel的绝对定位 */
    }
    #carousel > ul,
    #carousel > ul > li {
      padding: 0;
      margin: 0;
      list-style: none;
    }
  </style>
  <body>
    <!-- 轮播图容器 -->
    <div id="carousel">
      <ul>
        <!-- 图片容器 -->
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/9/7A/B1/F29B84DEF72DD329997E8172ABA_664BA3EF_32466.jpg"
          />
        </li>
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/B/F3/E4/693AB931C9FFB84646970D53BFE_C506394A_4282CA.jpg"
          />
        </li>
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/F/7A/AA/E1459849AA8AB0C89854A41BD41_BF3BD857_BC0D8.jpg"
          />
        </li>
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/1/95/CB/EDC1450B8FD1B8A25FAAC726AA4_A36D4253_16C91.jpg"
          />
        </li>
      </ul>
    </div>
  </body>
  <script type="text/javascript">
    var imgArr = []; // 图片数组
    var curIndex = 0; // 当前显示图片
    var timer = null; // 定时器

    function slide(slideContainer) {
      var width = imgArr[curIndex].width; // 获取图片宽度,也就是每次切换图片要滑动的距离
      var distanceMoved = 0; // 已经移动的距离
      var step = 10; //切换的步长
      var curConLeft = slideContainer.offsetLeft; // 获取ul的left
      var slideInterval = setInterval(function () {
        // 此定时器是为了实现切换动画
        if (Math.abs(width - distanceMoved) > step) {
          // 边界判定,判断已移动距离以及应移动距离的差与步长关系
          curConLeft -= step; // 大于步长则不断移动
          slideContainer.style.left = '${curConLeft}px'; // 移动
          distanceMoved += step; // 已移动距离加步长
        } else {
          clearInterval(slideInterval); // 若最后移动距离不足步长,则清除动画定时器
          slideContainer.style.left = '${curConLeft - width + distanceMoved}px'; // 直接完成此次动画
          distanceMoved = 0; // 重设移动距离为0
          if (++curIndex === imgArr.length) {
            // index加1,判断是否为最后一张来作边缘处理
            curIndex = 0; // 最后一张则重置index
            slideContainer.style.left = 0; // 重置ul
          }
        }
      }, 10);
    }

    (function start() {
      var config = {
        height: "300px", // 配置高度
        interval: 5000 // 配置轮播时间间隔
      };
      document.getElementById("carousel").style.height = config.height; // 将轮播容器高度设定
      document.querySelectorAll("#carousel img").forEach((v) => imgArr.push(v)); // 获取所有图片组成数组
      var slideContainer = document.querySelector("#carousel > ul"); // 获取ul也就是一行图片的容器
      var li = document.createElement("li"); // 创建<li>
      var img = document.createElement("img"); // 创建新的<img>
      img.src = imgArr[0].src; // 设置图片src
      li.appendChild(img); // 追加<img>到<li>
      slideContainer.appendChild(li); // 将第一张图片追加到轮播图的最后,作边缘处理
      timer = setInterval(() => {
        slide(slideContainer);
      }, config.interval); // 设置定时器定时切换
    })();
  </script>
</html>
<!-- 
    加入控制按钮,上一张与下一张,直接切换按钮
    将第一张图片的边缘化进行处理
    对浏览器页面显隐与鼠标移入移出事件的支持
-->
<!DOCTYPE html>
<html>
  <head>
    <title>轮播图</title>
    <meta charset="utf-8" />
    <meta name="referrer" content="no-referrer" />
  </head>
  <link
    rel="stylesheet"
    type="text/css"
    href="https://at.alicdn.com/t/font_1582902_u0zm91pv15i.css"
  />
  <style type="text/css">
    body {
      margin: 0;
      padding: 0px;
    }
    #carousel {
      margin: auto; /* 居中 */
      width: 600px; /* 设置宽度 */
      position: relative; /* 相对定位 */
      overflow: hidden; /* 超出隐藏 */
    }
    #carousel img {
      width: 600px; /* 设定大小 按比例缩放 */
    }
    #carousel > ul {
      display: flex; /* 图片处理为一行 */
      position: absolute; /* 设置绝对定位,实现相对于#carousel的绝对定位 */
    }
    #carousel > ul,
    #carousel > ul > li {
      padding: 0;
      margin: 0;
      list-style: none;
    }

    /* 控制按钮的样式 */
    #leftArrow,
    #rightArrow {
      position: absolute;
      left: 5px;
      top: 43%;
      width: 25px;
      height: 30px;
      background-color: #eee;
      display: flex;
      justify-content: center;
      align-items: center;
      opacity: 0.7;
      font-size: 20px;
      cursor: pointer;
    }
    #rightArrow {
      left: auto;
      right: 5px;
    }
    #sliderBtn {
      position: absolute;
      width: 100%;
      bottom: 0;
      display: flex;
      justify-content: flex-end;
    }
    .unitBtn {
      width: 10px;
      height: 10px;
      background-color: #eee;
      border-radius: 10px;
      margin: 10px;
      cursor: pointer;
    }
    .active {
      background-color: #4c98f7;
    }
  </style>
  <body>
    <!-- 轮播图容器 -->
    <div id="carousel">
      <ul>
        <!-- 图片容器 -->
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/9/7A/B1/F29B84DEF72DD329997E8172ABA_664BA3EF_32466.jpg"
          />
        </li>
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/B/F3/E4/693AB931C9FFB84646970D53BFE_C506394A_4282CA.jpg"
          />
        </li>
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/F/7A/AA/E1459849AA8AB0C89854A41BD41_BF3BD857_BC0D8.jpg"
          />
        </li>
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/1/95/CB/EDC1450B8FD1B8A25FAAC726AA4_A36D4253_16C91.jpg"
          />
        </li>
      </ul>
      <!-- 按钮组 -->
      <div id="leftArrow" class="iconfont icon-arrow-lift"></div>
      <!-- 左箭头切换按钮 -->
      <div id="rightArrow" class="iconfont icon-arrow-right"></div>
      <!-- 右箭头切换按钮 -->
      <div id="sliderBtn"></div>
      <!-- 切换按钮组 -->
    </div>
  </body>
  <script type="text/javascript">
    var imgArr = []; // 图片数组
    var curIndex = 0; // 当前显示图片
    var timer = null; // 定时器
    var clickAllow = true; // 锁,是否允许用户点击
    var btnList = []; // 右下角切换按钮组

    function slide(slideContainer, targetIndex = curIndex + 1) {
      var width = 0; // 计算切换图片要滑动的距离
      if (targetIndex > curIndex) {
        for (let i = curIndex; i < targetIndex; ++i) width += imgArr[i].width; // 正向切换则计算本图片到后续图片宽度
      } else {
        if (targetIndex === -1)
          width = imgArr[imgArr.length - 1].width; // 特殊处理第一张图片
        else
          for (let i = targetIndex; i < curIndex; ++i) width += imgArr[i].width; // 逆向切换处理宽度
      }
      clickAllow = false; // 不允许用户点击
      var step = width / 60; // 动态设置步长
      step = targetIndex > curIndex ? step : -step; // 正向逆向切换
      var curConLeft = slideContainer.offsetLeft; // 获取ul的left
      var distanceMoved = 0; // 已经移动的距离
      var slideInterval = setInterval(function () {
        // 此定时器是为了实现切换动画
        if (Math.abs(width - distanceMoved) > Math.abs(step)) {
          // 边界判定,判断已移动距离以及应移动距离的差与步长关系
          curConLeft -= step; // 大于步长则不断移动
          slideContainer.style.left = '${curConLeft - step}px'; // 移动
          distanceMoved += Math.abs(step); // 已移动距离加步长
        } else {
          clearInterval(slideInterval); // 若最后移动距离不足步长,则清除动画定时器
          var directMove =
            step > 0
              ? curConLeft - width + distanceMoved
              : curConLeft + width - distanceMoved; // 正向移动与逆向移动的计算方式不同
          slideContainer.style.left = '${directMove}px'; // 直接完成此次动画
          distanceMoved = 0; // 重设移动距离为0
          curIndex = targetIndex; // 设置当前index
          if (curIndex === imgArr.length) {
            // index加1,判断是否为最后一张来作边缘处理
            curIndex = 0; // 最后一张则重置index
            slideContainer.style.left = '-${imgArr[0].width}px'; // 重置ul
          } else if (curIndex === -1) {
            curIndex = imgArr.length - 1; // 第一张重置index
            slideContainer.style.left = '-${
              slideContainer.offsetWidth -
              imgArr[imgArr.length - 1].width -
              imgArr[0].width
            }px'; // 重置ul
          }
          switchBtnActive(); // 右下角按钮的切换
          clickAllow = true; // 允许点击
        }
      }, 10);
    }

    function switchBtnActive() {
      btnList.forEach((v) => {
        v.className = "unitBtn"; // 设置其他按钮为灰色
      });
      btnList[curIndex].className = "unitBtn active"; // 设置当前按钮为蓝色
    }

    function createBtnGroup(carousel, slideContainer, config) {
      document.getElementById("leftArrow").addEventListener("click", (e) => {
        clearInterval(timer); // 清除定时器,避免手动切换时干扰
        if (clickAllow) slide(slideContainer, curIndex - 1); // 允许点击则切换上一张
        timer = setInterval(() => {
          slide(slideContainer);
        }, config.interval); // 重设定时器
      });
      document.getElementById("rightArrow").addEventListener("click", (e) => {
        clearInterval(timer); // 清除定时器,避免手动切换时干扰
        if (clickAllow) slide(slideContainer, curIndex + 1); // 允许点击则切换下一张
        timer = setInterval(() => {
          slide(slideContainer);
        }, config.interval); // 重设定时器
      });
      var sliderBtn = document.getElementById("sliderBtn"); // 获取按钮容器的引用
      imgArr.forEach((v, i) => {
        let btn = document.createElement("div"); // 制作按钮
        btn.className = i === 0 ? "unitBtn active" : "unitBtn"; // 初设蓝色与灰色按钮样式
        btn.addEventListener("click", (e) => {
          clearInterval(timer); // 清除定时器,避免手动切换时干扰
          if (clickAllow) slide(slideContainer, i); // // 允许点击则切换
          timer = setInterval(() => {
            slide(slideContainer);
          }, config.interval); // 重设定时器
        });
        btnList.push(btn); // 添加按钮到按钮组
        sliderBtn.appendChild(btn); // 追加按钮到按钮容器
      });
    }

    function edgeDispose(slideContainer) {
      var li = document.createElement("li"); // 创建<li>
      var img = document.createElement("img"); // 创建新的<img>
      img.src = imgArr[0].src; // 设置图片src
      li.appendChild(img); // 追加<img>到<li>
      slideContainer.appendChild(li); // 将第一张图片追加到轮播图的最后,作边缘处理
      var li2 = document.createElement("li"); // 创建<li>
      var img2 = document.createElement("img"); // 创建新的<img>
      img2.src = imgArr[imgArr.length - 1].src; // 设置图片src
      li2.appendChild(img2); // 追加<img>到<li>
      slideContainer.insertBefore(li2, slideContainer.firstChild); // 将最后一张图片追加到轮播图的最前,作边缘处理
      slideContainer.style.left = '-${imgArr[0].width}px'; // 重设ul位置
    }

    function eventDispose(carousel, slideContainer, config) {
      document.addEventListener("visibilitychange", function () {
        // 浏览器切换页面会导致动画出现问题,监听页面切换
        if (document.visibilityState == "hidden")
          clearInterval(timer); // 页面隐藏清除定时器
        else
          timer = setInterval(() => {
            slide(slideContainer);
          }, config.interval); // 重设定时器
      });
      carousel.addEventListener("mouseover", function () {
        // 鼠标移动到容器则不切换动画,停止计时器
        clearInterval(timer); // 页面隐藏清除定时器
      });
      carousel.addEventListener("mouseleave", function () {
        // 鼠标移出容器则开始动画
        timer = setInterval(() => {
          slide(slideContainer);
        }, config.interval); // 重设定时器
      });
    }

    (function start() {
      var config = {
        height: "300px", // 配置高度
        interval: 5000 // 配置轮播时间间隔
      };
      var carousel = document.getElementById("carousel"); //获取容器对象的引用
      carousel.style.height = config.height; // 将轮播容器高度设定
      document.querySelectorAll("#carousel img").forEach((v) => imgArr.push(v)); // 获取所有图片组成数组
      var slideContainer = document.querySelector("#carousel > ul"); // 获取ul也就是一行图片的容器
      edgeDispose(slideContainer); // 对边缘处理
      eventDispose(carousel, slideContainer, config); // 对一些浏览器事件处理
      createBtnGroup(carousel, slideContainer, config); // 按钮组的处理
      timer = setInterval(() => {
        slide(slideContainer);
      }, config.interval); // 设置定时器定时切换
    })();
  </script>
</html>

opacity

首先通过对图片绝对定位来使图片堆叠,通过使用opacity来控制图片的显示与隐藏,即不使用Js控制轮播图的切换动画,而使用CSS动画来完成,由于是堆叠完成的,使用z-index也是可行的方案。

实例

<!DOCTYPE html>
<html>
  <head>
    <title>轮播图</title>
    <meta charset="utf-8" />
    <meta name="referrer" content="no-referrer" />
  </head>
  <link
    rel="stylesheet"
    type="text/css"
    href="https://at.alicdn.com/t/font_1582902_u0zm91pv15i.css"
  />
  <style type="text/css">
    body {
      margin: 0;
      padding: 0px;
    }
    #carousel {
      margin: auto; /* 居中 */
      width: 600px; /* 设置宽度 */
      position: relative; /* 相对定位 */
      overflow: hidden; /* 超出隐藏 */
    }
    #carousel img {
      position: absolute; /* 绝对定位 使图片堆叠 */
      width: 600px; /* 设定大小 按比例缩放 */
      transition: all 0.6s; /* 动画 */
      opacity: 0; /* 隐藏 */
    }
    .imgActive {
      opacity: 1 !important; /* 显示图片 最高优先级 */
    }

    /* 控制按钮的样式 */
    #leftArrow,
    #rightArrow {
      position: absolute;
      left: 5px;
      top: 43%;
      width: 25px;
      height: 30px;
      background-color: #eee;
      display: flex;
      justify-content: center;
      align-items: center;
      opacity: 0.7;
      font-size: 20px;
      cursor: pointer;
      z-index: 1000;
    }
    #rightArrow {
      left: auto;
      right: 5px;
    }
    #sliderBtn {
      position: absolute;
      width: 100%;
      bottom: 0;
      display: flex;
      justify-content: flex-end;
      z-index: 1000;
    }
    .unitBtn {
      width: 10px;
      height: 10px;
      background-color: #eee;
      border-radius: 10px;
      margin: 10px;
      cursor: pointer;
    }
    .btnActive {
      background-color: #4c98f7;
    }
  </style>
  <body>
    <!-- 轮播图容器 -->
    <div id="carousel">
      <img
        src="http://www.sdust.edu.cn/__local/9/7A/B1/F29B84DEF72DD329997E8172ABA_664BA3EF_32466.jpg"
      />
      <img
        src="http://www.sdust.edu.cn/__local/B/F3/E4/693AB931C9FFB84646970D53BFE_C506394A_4282CA.jpg"
      />
      <img
        src="http://www.sdust.edu.cn/__local/F/7A/AA/E1459849AA8AB0C89854A41BD41_BF3BD857_BC0D8.jpg"
      />
      <img
        src="http://www.sdust.edu.cn/__local/1/95/CB/EDC1450B8FD1B8A25FAAC726AA4_A36D4253_16C91.jpg"
      />
      <!-- 按钮组 -->
      <div id="leftArrow" class="iconfont icon-arrow-lift"></div>
      <!-- 左箭头切换按钮 -->
      <div id="rightArrow" class="iconfont icon-arrow-right"></div>
      <!-- 右箭头切换按钮 -->
      <div id="sliderBtn"></div>
      <!-- 切换按钮组 -->
    </div>
  </body>
  <script type="text/javascript">
    var imgArr = []; // 图片数组
    var curIndex = 0; // 当前显示图片
    var timer = null; // 定时器
    var btnList = []; // 右下角切换按钮组

    function slide(targetIndex = curIndex + 1) {
      curIndex = targetIndex % imgArr.length; // 获取当前index
      imgArr.forEach((v) => (v.className = "")); // 设置其他图片隐藏
      imgArr[curIndex].className = "imgActive"; // 设置当前index图片显示
      btnList.forEach((v) => (v.className = "unitBtn")); // 设置其他按钮为灰色
      btnList[curIndex].className = "unitBtn btnActive"; // 设置当前按钮为蓝色
    }

    function createBtnGroup(carousel, config) {
      document.getElementById("leftArrow").addEventListener("click", (e) => {
        clearInterval(timer); // 清除定时器,避免手动切换时干扰
        slide(curIndex - 1); // 允许点击则切换上一张
        timer = setInterval(() => {
          slide();
        }, config.interval); // 重设定时器
      });
      document.getElementById("rightArrow").addEventListener("click", (e) => {
        clearInterval(timer); // 清除定时器,避免手动切换时干扰
        slide(curIndex + 1); // 允许点击则切换下一张
        timer = setInterval(() => {
          slide();
        }, config.interval); // 重设定时器
      });
      var sliderBtn = document.getElementById("sliderBtn"); // 获取按钮容器的引用
      imgArr.forEach((v, i) => {
        let btn = document.createElement("div"); // 制作按钮
        btn.className = i === 0 ? "unitBtn btnActive" : "unitBtn"; // 初设蓝色与灰色按钮样式
        btn.addEventListener("click", (e) => {
          clearInterval(timer); // 清除定时器,避免手动切换时干扰
          slide(i); // // 允许点击则切换
          timer = setInterval(() => {
            slide();
          }, config.interval); // 重设定时器
        });
        btnList.push(btn); // 添加按钮到按钮组
        sliderBtn.appendChild(btn); // 追加按钮到按钮容器
      });
    }

    function eventDispose(carousel, config) {
      document.addEventListener("visibilitychange", function () {
        // 浏览器切换页面会导致动画出现问题,监听页面切换
        if (document.visibilityState == "hidden")
          clearInterval(timer); // 页面隐藏清除定时器
        else
          timer = setInterval(() => {
            slide();
          }, config.interval); // 重设定时器
      });
      carousel.addEventListener("mouseover", function () {
        // 鼠标移动到容器则不切换动画,停止计时器
        clearInterval(timer); // 页面隐藏清除定时器
      });
      carousel.addEventListener("mouseleave", function () {
        // 鼠标移出容器则开始动画
        timer = setInterval(() => {
          slide();
        }, config.interval); // 重设定时器
      });
    }

    (function start() {
      var config = {
        height: "300px", // 配置高度
        interval: 5000 // 配置轮播时间间隔
      };
      var carousel = document.getElementById("carousel"); //获取容器对象的引用
      carousel.style.height = config.height; // 将轮播容器高度设定
      document.querySelectorAll("#carousel img").forEach((v, i) => {
        imgArr.push(v); // 获取所有图片组成数组
        v.className = i === 0 ? "imgActive" : "";
      });
      eventDispose(carousel, config); // 对一些浏览器事件处理
      createBtnGroup(carousel, config); // 按钮组的处理
      timer = setInterval(() => {
        slide();
      }, config.interval); // 设置定时器定时切换
    })();
  </script>
</html>

CSS

纯CSS实现轮播图,完全使用CSS3动画完成轮播,主要使用animation属性与@keyframes规则,使用left控制距离,也可以使用opacity,为每个图片设置动画属性即可。

实例

<!DOCTYPE html>
<html>
  <head>
    <title>轮播图</title>
    <meta charset="utf-8" />
    <meta name="referrer" content="no-referrer" />
  </head>
  <link
    rel="stylesheet"
    type="text/css"
    href="https://at.alicdn.com/t/font_1582902_u0zm91pv15i.css"
  />
  <style type="text/css">
    body {
      margin: 0;
      padding: 0px;
    }
    #carousel {
      margin: auto; /* 居中 */
      width: 600px; /* 设置宽度 */
      position: relative; /* 相对定位 */
      overflow: hidden; /* 超出隐藏 */
      height: 300px;
    }
    #carousel img {
      width: 600px; /* 设定大小 按比例缩放 */
    }
    #carousel > ul {
      display: flex; /* 图片处理为一行 */
      position: absolute; /* 设置绝对定位,实现相对于#carousel的绝对定位 */
    }
    #carousel > ul,
    #carousel > ul > li {
      padding: 0;
      margin: 0;
      list-style: none;
    }

    #carousel > ul {
      animation: switch 10s ease 1s infinite alternate; /* 设定动画播放 */
    }

    #carousel > ul:hover {
      animation-play-state: paused; /* 暂停动画 */
    }

    @keyframes switch {
      /* 制定动画规则 */
      0%,
      13% {
        left: 0;
      }
      27%,
      41% {
        left: -600px;
      }
      55%,
      69% {
        left: -1200px;
      }
      83%,
      100% {
        left: -1800px;
      }
    }
  </style>
  <body>
    <!-- 轮播图容器 -->
    <div id="carousel">
      <ul>
        <!-- 图片容器 -->
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/9/7A/B1/F29B84DEF72DD329997E8172ABA_664BA3EF_32466.jpg"
          />
        </li>
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/B/F3/E4/693AB931C9FFB84646970D53BFE_C506394A_4282CA.jpg"
          />
        </li>
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/F/7A/AA/E1459849AA8AB0C89854A41BD41_BF3BD857_BC0D8.jpg"
          />
        </li>
        <li>
          <img
            src="http://www.sdust.edu.cn/__local/1/95/CB/EDC1450B8FD1B8A25FAAC726AA4_A36D4253_16C91.jpg"
          />
        </li>
      </ul>
    </div>
  </body>
</html>
标签: #轮播图 #CSS
推荐文章
HTML5 Canvas是一种强大的Web技术,它允许我们使用JavaScript在网页上创建和...
在这个程序中,我们将使用JavaScript创建一个可以在屏幕上放烟花的效果。我...
轮播图在网站中几乎无处不在,占用地方少,交互性好。今天就来聊聊如何用vu...
大部分网站或APP的首页差不多都运用到了轮播图,下边就探讨一下关于轮播图的...
轮播图实现思路:1、img_ul类里面存放img标签,将需要展示的图片依次排开,在...
推荐专题
如何自己建网站?建网站难不难?其实建网站说难不难,说容易也并不容易,难...
本专题精心收集整理了多种HTML+CSS+JS轮播图实现方案,带详细代码和讲解,正...