有一点点酷的swiper

原生js开发一个swiper

前言

最近没啥事儿干,想着在公司闲着也是闲着,写个轮播图来玩玩儿吧,还没手写过呢,想法有了,再来想想思路,嗯......有几张图片,要知道当前浏览的是哪一个,相邻的之间有个大小透明的差异化,再来两个切换按钮,嗯......就很ok啦,开撸!!!

先看效果图

一个可以左右切换,点击图片切换的轮播图

准备

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>轮播图</title>
    <link rel="stylesheet" href="./index.css" />
  </head>
  <body>
    <div class="swiper-wrap">
      <div class="prev">
        <img src="./image/方向-左-双线.png" alt="" />
      </div>
      <div class="swiper-content">
        <div class="swiper-item">
          <span style="position: absolute; top: 50px; left: 50px">
            index:0
          </span>
          <img src="./image/1.png" alt="" />
        </div>
        <div class="swiper-item">
          <span style="position: absolute; top: 50px; left: 50px">
            index:1
          </span>
          <img src="./image/3.png" alt="" />
        </div>
        <div class="swiper-item">
          <span style="position: absolute; top: 50px; left: 50px">
            index:2
          </span>
          <img src="./image/2.png" alt="" />
        </div>
        <div class="swiper-item">
          <span style="position: absolute; top: 50px; left: 50px">
            index:3
          </span>
          <img src="./image/4.png" alt="" />
        </div>
        <div class="swiper-item">
          <span style="position: absolute; top: 50px; left: 50px">
            index:4
          </span>
          <img src="./image/5.png" alt="" />
        </div>
        <div class="swiper-item">
          <span style="position: absolute; top: 50px; left: 50px">
            index:5
          </span>
          <img src="./image/6.png" alt="" />
        </div>
        <div class="swiper-item">
          <span style="position: absolute; top: 50px; left: 50px">
            index:6
          </span>
          <img src="./image/7.png" alt="" />
        </div>
        <div class="swiper-item">
          <span style="position: absolute; top: 50px; left: 50px">
            index:7
          </span>
          <img src="./image/8.png" alt="" />
        </div>
      </div>
      <div class="next">
        <img src="./image/方向-右-双线.png" alt="" />
      </div>
    </div>
    <script src="./index.js"></script>
  </body>
</html>
css 复制代码
body {
  background: rgba(0, 0, 0, 0.7);
}
.swiper-wrap {
  position: relative;
  width: 1000px;
  height: 500px;
}
.swiper-wrap .prev,
.swiper-wrap .next {
  position: absolute;
  width: 50px;
  height: 50px;
  cursor: pointer;
  z-index: 999;
  opacity: 0.5;
}

.swiper-wrap .prev:hover,
.swiper-wrap .next:hover {
  opacity: 1;
}

.swiper-wrap .prev img,
.swiper-wrap .next img {
  width: 100%;
  height: 100%;
}

.swiper-wrap .prev {
  top: 50%;
  left: 20px;
  transform: translateY(-50%);
}

.swiper-wrap .next {
  top: 50%;
  right: 20px;
  transform: translateY(-50%);
}

.swiper-wrap .swiper-content {
  perspective: 1000px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.swiper-wrap .swiper-content .swiper-item {
  position: absolute;
  transition: all 0.33s;
}

.swiper-wrap .swiper-content .swiper-item img {
  width: 400px;
  height: 300px;
}

js核心逻辑

具体的逻辑实现我在注释中已基本说明,主要就是用transform来改变元素的位置,在加点动画,就完事儿。

js 复制代码
// 获取按钮每一张轮播图
const swiperItems = document.querySelectorAll('.swiper-item')

// 获取按钮
const prev = document.querySelector('.prev')
const next = document.querySelector('.next')

// 当前显示的索引号
let index = 3

// 布局
const layout = () => {
    let xStep = 100  // 水平方向的边偏移
    const scaleStep = 0.6  // 缩放的倍数
    const opacitytep = 0.4 // 透明度的倍数
    const len = swiperItems.length // 轮播图数据的长度

    for (let i = 0; i < swiperItems.length; i++) {
        const item = swiperItems[i]
        const diff = i - index // 计算在显示元素的左边或右边的第几个身位
        const sign = Math.sign(diff) // 取正负值 返回 -1 或 1

        let offsetX = xStep * diff // 计算与当前显示元素的边偏移

        if (i !== index) {
            // 这里是为了兼容边偏移距离过近或者过远的补偿,如果倍数与尺寸设计的好,也可以不必这样写,可以直接使用
            offsetX = offsetX + 100 * sign
        }

        // 计算rotate沿y轴的旋转角度,如果是当前显示的则不旋转,旋转45度
        // sign为负数则逆时针,为正数则顺时针 
        // 注意:记得在样式加入perspective属性,好久没写3d了,上了它的鬼日当,不然没有视距差异
        const rotate = i === index ? 0 : 45 * (-sign)

        // 计算缩放大小,这里一定要取绝对值,不然就是放大了,详细见图形分解
        const scale = Math.pow(scaleStep, Math.abs(diff))

        item.style.transform = `translateX(${offsetX}px) scale(${scale}) rotateY(${rotate}deg)`

        // zIndex的计算与scale同理,可以用任何数值来计算,len可以等于1000,也可以100,主要还是看有没有其他元素层级的影响
        item.style.zIndex = len - Math.abs(diff)

        // opacity的计算也与scale同理
        const opacity = Math.pow(opacitytep, Math.abs(diff))
        item.style.opacity = opacity
    }
}

// 初始化布局
layout()

// 事件处理,不过多赘述
for (let i = 0; i < swiperItems.length; i++) {
    const item = swiperItems[i]
    item.addEventListener('click', function () {
        index = i
        layout()
    })
}

prev.addEventListener('click', function () {
    index--
    if (index < 0) {
        index = swiperItems.length - 1
    }
    layout()
})

next.addEventListener('click', function () {
    index++
    if (index >= swiperItems.length) {
        index = 0
    }
    layout()
})

这里主要就是运用了数学的幂次方算法,偏移几个身位,就是多少次方,计算两个相邻的元素的大小,及透明图的变化

计算大小的逻辑实现,图解:

结尾

是不是很简单!!!

别人问我为啥我这个不可以滑动切换,别问,问就是还没想好怎么写,等我想好了再加进来!!!

相关推荐
吃杠碰小鸡6 分钟前
commitlint校验git提交信息
前端
虾球xz37 分钟前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇42 分钟前
HTML常用表格与标签
前端·html
疯狂的沙粒1 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员1 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐1 小时前
前端图像处理(一)
前端
程序猿阿伟1 小时前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
疯狂的沙粒1 小时前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪1 小时前
AJAX的基本使用
前端·javascript·ajax
力透键背1 小时前
display: none和visibility: hidden的区别
开发语言·前端·javascript