首页 > javascript > >手把手教你用原生js来写一个swiper滑块插件(上)原理

手把手教你用原生js来写一个swiper滑块插件(上)原理

时间:2022-04-27浏览次数:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>demo</title>
  <style>
    * {
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }

    #swiper {
      width: 960px;
      height: 400px;
      position: relative;
      margin: 0 auto;
      overflow: hidden;
    }

    .swiper-container {
      position: absolute;
      height: 400px;
      left: 0;
      top: 0;
      display: flex;
      transition: all 0.3s;
      user-select: none;
      display: flex;
      align-items: center;
    }

    li {
      width: 300px;
      height: 300px;
      list-style: none;
    }

    li.magnify {
      transform: scale(1.1);
      transition: all 1s;
    }

    li.lessen {
      transform: scale(0.9);
      transition: all 1s;
    }

    li img {
      width: 300px;
      height: 300px;
    }

    li:not(last-child) {
      margin-right: 30px;
    }
  </style>
</head>

<body>
  <div id="swiper">
  </div>
</body>

<script>
  // 首先获取视图层元素
  const swiperEl = document.querySelector('#swiper');
  const createUl = document.createElement('ul')
  createUl.innerHTML = `
    <ul class="swiper-container">
      <li>
        <img draggable="false" src="./img/01.jpg" alt="">
      </li>
      <li>
        <img draggable="false" src="./img/02.jpg" alt="">
      </li>
      <li>
        <img draggable="false" src="./img/03.jpg" alt="">
      </li>
      <li>
        <img draggable="false" src="./img/04.jpg" alt="">
      </li>
      <li>
        <img draggable="false" src="./img/05.jpg" alt="">
      </li>
      <li>
        <img draggable="false" src="./img/06.jpg" alt="">
      </li>
      <li>
        <img draggable="false" src="./img/07.jpg" alt="">
      </li>
      <li>
        <img draggable="false" src="./img/08.jpg" alt="">
      </li>
      <li>
        <img draggable="false" src="./img/09.jpg" alt="">
      </li>
    </ul>`
  swiperEl.appendChild(createUl)

  // 在视图层里边查找容器元素
  const containerEl = swiperEl.querySelector('.swiper-container');
  let state = 0;  // 鼠标默认状态
  let index = 0
  let oldEvent = null;    // 用来记录鼠标上次的位置
  // 获取到所有的滑块元素
  const itemEls = containerEl.querySelectorAll('li');
  itemEls[1].classList.add('magnify')
  itemEls[0].classList.add('lessen')
  itemEls[2].classList.add('lessen')
  // 获取到滑块的宽度
  const itemWidth = itemEls[0].offsetWidth;
  // let left = containerEl.offsetLeft;
  // 存储容器的left,这里我们根据index来计算初始容器的left值
  let left = 0 - (itemWidth + 30) * index;
  // 设置容器的初始位置
  containerEl.style.left = left + 'px';
  containerEl.addEventListener('mousedown', (event) => {
    state = 1;  // 设置为1表示按下了鼠标
    startEvent = oldEvent = event;   // 当鼠标按下时候记录初始位置

  });
  containerEl.addEventListener('mousemove', (event) => {
    if (state != 1) return; // 只有当state == 1时候才允许执行该事件
    if (event.pageX < oldEvent.pageX) {
      left -= oldEvent.pageX - event.pageX;
    }
    else {
      left += event.pageX - oldEvent.pageX;
    }
    // 完事之后记得把当前鼠标的位置赋值给oldEvent
    oldEvent = event;
    // 最后再把left赋值给容器
    containerEl.style.left = left + 'px';
  });
  containerEl.addEventListener('mouseup', (event) => {
    state = 0;  // 恢复默认状态
    if (event.pageX < startEvent.pageX) {
      index++;
    }
    else {
      index--;
    }
    if (index < 0) {
      index = 0;
    }
    else if (index > itemEls.length - 3) {
      index = itemEls.length - 3;
    }
    left = 0 - (itemWidth + 30) * index;
    containerEl.style.left = left + 'px';
    animation(index)
  });

  // 自动播放状态
  let autoplay = true;

  setInterval(() => {
    if (!autoplay) return
    index++;
    if (index > itemEls.length - 3) {
      index = 0;
    }
    left = 0 - (itemWidth + 30) * index;
    containerEl.style.left = left + 'px';

    animation(index)
  }, 2000);
  containerEl.addEventListener('mouseover', () => {
    // 鼠标移动到容器上,停止播放
    autoplay = false;
  });
  containerEl.addEventListener('mouseout', () => {
    // 鼠标从容器上移开,恢复播放
    autoplay = true;
  });


  const animation = (index) => {
    for (let i = 0; i < itemEls.length; i++) {
      ADD_DELETE_ClASS('remove', i, 'magnify')
      ADD_DELETE_ClASS('remove', i, 'lessen')
    }
    ADD_DELETE_ClASS('add', index + 1, 'magnify')
    ADD_DELETE_ClASS('add', index, 'lessen')
    ADD_DELETE_ClASS('add', index + 2, 'lessen')
  }

  const ADD_DELETE_ClASS = (state, index, name) => {
    if (state === 'add') {
      return itemEls[index].classList.add(name)
    } else {
      itemEls[index].classList.remove(name)
    }
  }
</script>

</html>