视觉艺术JavaScript前端

【前端案例】 19 - 案例:网页轮播图

2020-12-18  本文已影响0人  itlu

案例演示

轮播图

功能需求:

  1. 鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮;

  2. 点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理;

  3. 图片播放的同时,下面小圆圈模块跟随一起变化;

  4. 点击小圆圈,可以播放相应图片;

  5. 鼠标不经过轮播图,轮播图也会自动播放图片;

  6. 鼠标经过,轮播图模块, 自动播放停止。

代码实现

css
* {
  padding: 0;
  margin: 0;
}

a {
  text-decoration: none;
  color: #ccc;
}

ul,
ol {
  list-style: none;
}

.focus {
  position: relative;
  width: 590px;
  /* 需要设置高度之后绝对子元素绝对定位才能使用百分比 */
  height: 470px;
  margin: 100px auto;
  overflow: hidden;
}

.focus li img {
  width: 100%;
}

.arrow-left,
.arrow-right {
  display: none;
  position: absolute;
  top: 50%;
  width: 38px;
  height: 38px;
  line-height: 38px;
  text-align: center;
  color: #fff;
  font-weight: 700;
  cursor: pointer;
  background-color: rgba(0, 0, 0, .3);
  transform: translateY(-50%);
  transition: all 1s linear;
  z-index: 2;
}

.arrow-left:hover,
.arrow-right:hover {
  color: #ccc;
}

.arrow-left {
  left: 0;
  border-radius: 0 15px 15px 0;
}

.arrow-right {
  right: 0;
  border-radius: 15px 0 0 15px;
}

.focus ul {
  position: absolute;
  top: 0;
  left: 0;
  width: 600%;
}

.focus ul li {
  float: left;
}

.focus ol {
  position: absolute;
  bottom: 16px;
  left: 50%;
  /*  移动自身宽度的50% */
  transform: translateX(-50%);
}

.focus ol li {
  float: left;
  margin-right: 10px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  cursor: pointer;
  border: 3px solid rgba(255, 255, 255, .5);
}

.focus ol li.cur_point {
  background-color: #fff;
  border-color: #ffffff;
}

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"
        ,maximum-scale=1.0,minimum-scale=1.0>
  <title>网页轮播图</title>
  <link rel="stylesheet" href="css/index.css">
  <link rel="stylesheet" href="css/iconfont.css">
  <script src="./js/animation.js"></script>
  <script src="./js/index.js"></script>
</head>
<body>

<div class="focus">
  <!-- javascript:void(0); 阻止页面跳转 -->
  <a href="javascript:void(0);" class="arrow-left">
    <i class="iconfont icon-zuoyou"></i>
  </a>
  <a href="javascript:void(0);" class="arrow-right">
    <i class="iconfont icon-icon-you"></i>
  </a>

  <ul>
    <li><a href="javascript:void(0);"><img src="images/focus1.jpg.webp" alt=""></a></li>
    <li><a href="javascript:void(0);"><img src="images/focus4.jpg.webp" alt=""></a></li>
    <li><a href="javascript:void(0);"><img src="images/focus2.jpg.webp" alt=""></a></li>
    <li><a href="javascript:void(0);"><img src="images/focus3.jpg.webp" alt=""></a></li>
  </ul>

  <ol></ol>
</div>

</body>
</html>
javascript
/**
 * 绑定页面加载完成之后再指定js的事件
 */
window.addEventListener('load', () => {
  // 获取元素
  let focus = document.querySelector('.focus');
  let ul = focus.querySelector('ul');
  let arrowRight = focus.querySelector('.arrow-right');
  let arrowLeft = focus.querySelector('.arrow-left');
  let focusWidth = focus.offsetWidth;
  let lisSize = ul.children.length;
  let ol = focus.querySelector('ol');
  let time = 1000;


  /**
   * 当鼠标接触到轮播图的时候显示左右切换按钮
   */
  focus.addEventListener('mouseenter', () => {
    arrowRight.style.display = 'block';
    arrowLeft.style.display = 'block';
    // 当鼠标进入时清除定时器
    clearInterval(timer);
    timer = null;
  })


  /**
   * 当鼠标离开轮播图的时候隐藏左右切换按钮
   */
  focus.addEventListener('mouseleave', () => {
    arrowRight.style.display = 'none';
    arrowLeft.style.display = 'none';
    /**
     * 当鼠标离开的时候重新设置定时器
     * @type {number}
     */
    timer = setInterval(() => {
      arrowRight.click();
    }, time);
  })


  /**
   * 根据ul中 li 的个数创建 ol中li的个数小圆点
   */
  for (let i = 0; i < lisSize; i++) {
    // 创建一个节点
    let li = document.createElement('li');
    // 为每一个 li 设置自定义属性
    li.setAttribute('data-index', i + '');
    // 追加节点
    ol.appendChild(li);

    /**
     * 为每一个小圆点注册点击事件选中时,出现未选中状态
     */
    ol.children[i].addEventListener('click', () => {
      for (let i = 0; i < ol.children.length; i++) {
        ol.children[i].className = '';
      }
      ol.children[i].className = 'cur_point';
      // 获取自定义属性
      let dataIndex = ol.children[i].getAttribute('data-index');
      // 调用动画进行切换
      animation(ul, -dataIndex * focusWidth)
      // 将 num 赋值为当前自定义属性
      num = dataIndex;
      circle = dataIndex;
    })
  }

  // 在这里设置因为上面刚创建了 li 添加到 ol 中
  ol.children[0].className = 'cur_point';

  // 将子第一个节点深拷贝到最后
  let firstLi = ul.children[0].cloneNode(true);
  // 将该节点添加到ul的后面
  ul.appendChild(firstLi);

  let circle = 0;
  let num = 0;
  // 节流阀: 利用回调函数原理需要执行完上一件事之后再执行下一件事
  let flag = true;
  /**
   * 向右切换图片
   */
  arrowRight.addEventListener('click', (e) => {
    if (flag) {
      // 关闭水龙头
      flag = false;
      if (num >= lisSize) {
        num = 0;
        ul.style.left = 0 + 'px';
      }
      num++;
      animation(ul, -(num * focusWidth), () => {
        // 执行回调函数 打开水龙头
        flag = true;
      });
      circle++;
      if (circle >= lisSize) {
        circle = 0
      }
      curPoint(circle);
    }
  })


  /**
   * 向左切换图片
   */
  arrowLeft.addEventListener('click', () => {
    if (flag) {
      flag = false;
      if (num <= 0) {
        num = lisSize;
        // 当前 ul 距离左侧的距离是
        ul.style.left = -(num * focusWidth) + 'px';
      }
      num--;
      animation(ul, -(num * focusWidth), () => {
        flag = true;
      });
      circle--;
      if (circle < 0) {
        circle = lisSize - 1;
      }
      curPoint(circle);
    }
  })


  /**
   * 将当前点设置为选中状态
   * @param index
   */
  function curPoint(index) {
    for (let i = 0; i < ol.children.length; i++) {
      ol.children[i].className = '';
      ol.children[index].className = 'cur_point';
    }
  }

  /**
   * 向右切换的 调用默认点击
   * @type {number}
   */
  let timer = setInterval(() => {
    arrowRight.click();
  }, time)

})
animation.js 实现切换图片动画,实现了一个缓动动画
function animation(obj,target,callback) {
  clearInterval(obj.timer);
  obj.timer = setInterval(()=> {
    // 计算步长
    let step = (target - obj.offsetLeft) / 10;
    // 判断当前的步长是否大于 0 大于0 则向上取整,反之向下取整
    step = step > 0 ? Math.ceil(step) : Math.floor(step);
    // 设置 元素对象的 left 属性使盒子移动
    obj.style.left = obj.offsetLeft + step + 'px';
    // 判断移动的距离是否查出目标值 如果超出则将定时器移除
    if (obj.offsetLeft === target) {
      clearInterval(obj.timer);
      callback && callback(); // 相当于 if(callback) {callback()}
      // 动画执行完成之后再执行回调函数
    }
  },15)
}
上一篇下一篇

猜你喜欢

热点阅读