几种原生js轮播图

由于各种各样的原因(比如说懒),本文直接在代码里面用注释+序号记录实现的思路

1.普通版

原理:一个包含多张图片的ul,其中所有的li左浮动成一排,实际过程就是将ul往左(右)边移动,改变left值。

效果图:实际应用的时候.screen的overflow:hidden。只能看到中间方框的部分
在线demo
clipboard.png

HTML

<div class="all" id="box">
  <div class="screen">
    <ul>
      <li><a href="javascript:;"><img src="images/01.jpg" ></a></li>
      <li><a href="javascript:;"><img src="images/02.jpg"></a></li>
      <li><a href="javascript:;"><img src="images/03.jpg"></a></li>
      <li><a href="javascript:;"><img src="images/04.jpg"></a></li>
      <li><a href="javascript:;"><img src="images/05.jpg"></a></li>
    </ul>
    <ol>
                
    </ol>
   </div>
   <div id="arr"><span class="left">&lt;</span><span class="right">&gt;</span></div>
</div>

其中<ol></ol>用来存放动态生成的小方块。

css部分代码

.screen li {
  width: 200px;
  height: 200px;
  overflow: hidden;
  float: left;
}
.all ol li {
  float: left;
  width: 20px;
  height: 20px;
  background: #fff;
  border: 1px solid red;
  margin-left: 10px;
  cursor: pointer;
}
.all ol li.current {
  background: yellow;
}

js(有用了自己封装的一个动画函数)

//动画函数
function animate(el, target){
    if(el.timer) {
        clearInterval(el.timer);
    }
    el.timer = setInterval(function () {
        //leader = leader + step
        var leader = el.offsetLeft;
        var step = 30;
        if(target < leader) {
            step = -step;
        }
        //如果到达终点的距离已经小于一步了,就直接跨到终点。
        if(Math.abs(target-leader) >= Math.abs(step)) {
            leader = leader + step;
            el.style.left = leader + "px";
        }else {
            clearInterval(el.timer);
            el.style.left = target + "px";
        }
    }, 15);
}
    //1. 找对象
    var box = document.querySelector(".all");
    var screen = document.querySelector(".screen");
    var ul = screen.children[0];
    var ullis = ul.children;
    var ol = screen.children[1];
    var arr = document.querySelector("#arr");
    var leftArr = arr.querySelector(".left");
    var rightArr = arr.querySelector(".right");
    var imgwidth = screen.offsetWidth;

    var pic = fk = 0;
    var timer;
    //2. 动态创建结构
    //2.1 创建小方块,ulLis
    //根据ul中li的个数创建小方块
    for(var i = 0; i < ullis.length; i++){
        var li = document.createElement("li");
        ol.appendChild(li);
        li.innerHTML = i + 1;
    }
    var ollis = ol.children;
    ollis[0].className = "current";

    //2.2 创建假图片
    //2.2.1 克隆ul下的第一个li
    var cloneli = ullis[0].cloneNode(true);
    ul.appendChild(cloneli);
    //3. 简单轮播功能
    //3.1 给小方块注册点击事件
    for(var i=0;i<ollis.length;i++){
        ollis[i].index=i;//存索引
        ollis[i].addEventListener("click", function(){
            //3.2 小方块高亮排他
            for(var i=0;i<ollis.length;i++){
                ollis[i].className="";
            }
            this.className="current";
            //3.3. 移动ul
            var target=-this.index*imgwidth;
            animate(ul,target);

            pic=fk=this.index;
        })
    }

    //4. 左右焦点功能(无缝)
    //4.1 鼠标经过盒子,显示箭头
    box.onmouseover = function(){
        arr.style.display = "block";
        //清除定时器
        clearInterval(timer);
    }
    //4.2 鼠标离开盒子,隐藏箭头
    box.onmouseleave = function(){
        arr.style.display = "none";
        timer = setInterval(function(){
            rightArr.onclick();
        },1000)
    }
    //4.3 点击右箭头
    rightArr.onclick = function(){
        //如果已经到了最后一张假图片,让ul瞬移到第一张真图片
        if(pic === ollis.length){
            ul.style.left = 0;
            pic = 0;
        }
        pic++;//记录出去的图片张数

        fk++;
        if(fk === ollis.length){
            fk = 0;
        }
        for(var i = 0; i < ollis.length;i++){
            ollis[i].className = "";
        }
        ollis[fk].className = "current";
        var target = -pic*imgwidth;
        animate(ul,target);
    }
    //4.4 点击左箭头
    leftArr.onclick = function(){
        if(pic === 0){
            ul.style.left = -(ullis.length - 1)*imgwidth + "px";
            pic = ullis.length - 1;
        }
        pic--;

        //同步小方块
        fk--;
        if(fk === -1){
            fk = ollis.length - 1;
        }
        for(var i = 0; i < ollis.length; i++){
            ollis[i].className = "";
        }
        ollis[fk].className = "current";
        var target = -pic*imgwidth;
        animate(ul,target);
    }
    //5. 自动播放的功能
    timer = setInterval(function(){
        rightArr.onclick();
    },1000)
    //6. 同步问题
    //6.1 点击右箭头,同步
    //6.2 点击左箭头,同步
    //6.3 点击小方块,同步

2. 3D版

原理:切割的思路其实是让四个图片拼成一个图片 ,并且让每一张图片都往左走一定的距离结合了css3动画

效果图:在线demo

clipboard.png

HTML

<div class="box">
  <ul>
    <li><img src="imgs/1.jpg"></li>
    <li><img src="imgs/2.jpg"></li>
    <li><img src="imgs/3.jpg"></li>
    <li><img src="imgs/4.jpg"></li>
  </ul>
  <ul>
    <li><img src="imgs/1.jpg"></li>
    <li><img src="imgs/2.jpg"></li>
    <li><img src="imgs/3.jpg"></li>
    <li><img src="imgs/4.jpg"></li>
  </ul>
  <ul>
    <li><img src="imgs/1.jpg"></li>
    <li><img src="imgs/2.jpg"></li>
    <li><img src="imgs/3.jpg"></li>
    <li><img src="imgs/4.jpg"></li>
  </ul>
  <ul>
    <li><img src="imgs/1.jpg"></li>
    <li><img src="imgs/2.jpg"></li>
    <li><img src="imgs/3.jpg"></li>
    <li><img src="imgs/4.jpg"></li>
  </ul>    
</div>
<div class="btn_wrap">
  <button>向上翻转按钮</button>
  <button>向下翻转按钮</button>
</div>

不要把按钮放到box里面,一旦放到这里面,它默认就会成为一个项目,从而影响整个的ul。

css部分代码

    *{
        padding:0;
        margin:0;
        list-style-type: none;
    }
    .box{
        width:533px;
        height:300px;
        margin:100px auto 0;
        border: 1px solid #000;
        /* 让盒子变成一个伸缩容器 */
        display:flex;
    }
    /* 第一步  需要制作出一个长方体 */
    .box ul{
        width:533px;
        height:300px;
        position:relative;
        transform-style: preserve-3d;
        transition: transform 1s;
    }
    .box ul:nth-child(1){
        transition-delay: 0s;
    }
    .box ul:nth-child(2){
        transition-delay: 0.2s;
    }
    .box ul:nth-child(3){
        transition-delay: 0.4s;
    }
    .box ul:nth-child(4){
        transition-delay: 0.6s;
    }
    .box > ul > li{
        /* 这里最好是设置成width:100%  让它继承收缩后的UL的宽度*/
        width:100%;
        height:100%;
        position:absolute;
        left:0;
        top:0;
        /* 这个切割一定是加给li的 ul加的话会把3D空间给干掉*/
        overflow:hidden;
    }
    .box > ul > li:nth-child(1){
        transform:rotateX(90deg) translateZ(150px);/* 上面 */
    }
    .box > ul > li:nth-child(2){
        transform:rotateX(-90deg) translateZ(150px);/* 下面 */
    }
    .box > ul > li:nth-child(3){
        transform:translateZ(150px);/* 正面 */
    }
    .box > ul > li:nth-child(4){
        transform:rotateX(180deg) translateZ(150px);/* 背面 */
    }
    .box > ul:nth-child(2) img{
        margin-left: -134px;
    }
    .box > ul:nth-child(3) img{
        margin-left: -268px;
    }
    .box > ul:nth-child(4) img{
        margin-left: -402px;
    }
    .btn_wrap{
        width:760px;
        height:0px;
        margin:0 auto;
        position:relative;
        top:-250px;
    }
    .btn_wrap button{
        width:100px;
        height:100px;
    }
    .btn_wrap button:nth-child(1){
        float: left;
    }
    .btn_wrap button:nth-child(2){
        float: right;
    }

js部分

    // 需求 点击按钮一次,就让长方体沿着X轴旋转90度(是基于上一次的角度累加或者累减)
    var box = document.querySelector('.box');
    var _ul = box.querySelectorAll('ul');
    var _li = box.querySelectorAll('li');
    var btns = document.querySelectorAll('button');
    // 声明一个信号量,以便计算需要旋转的度数
    var num = 0;
    // 当用户暴力点击的时候会出现过度执行不过来的BUG情况,需要函数节流。声明一个开关变量
    var flag = true;
    
    _ul[_ul.length -1].addEventListener('transitionend',function(){
        console.log(1);
        // 在过渡执行完毕之后重新打开开关
        flag = true;
    })

    for(var i = 0; i < btns.length; i++){
        btns[i].setAttribute('data-index', i);
        btns[i].addEventListener('click',function(){
            if(flag){
                flag = false;
                // 每次点击进行一次判断后在累加或者累减
                // 通过this去找到当前对象的自定义下标
                var index = this.dataset['index'];
                if(index == 1){
                    num++;
                }else if(index == 0){
                    num--;
                }
                // 给所有的UL添加翻转效果
                for(var i = 0; i < _ul.length; i++){
                    _ul[i].style.transform = 'rotateX('+num*90+'deg)';
                }
            }
        })
    }

3. 移动端

原理:利用定位,分为左中右

效果图:在线demo

clipboard.png

HTML

同普通版

css部分代码

.carouse-wrap {
    position: relative;
    min-height: 143px;
}

.carouse-wrap li {
    width: 100%;
    position: absolute;
    left: 0;
    top: 0;
    transform : translateX(100%);
}

js部分(代码较长,只放了重点部分,完整代码见文末)

// 将最初始的位置赋值
left = carouseWrapLi.length - 1;
center = 0;
right = 1;
// 将最开始的三张先就位
carouseWrapLi[left].style.transform = 'translateX('+ -windowWidth +'px)';
carouseWrapLi[center].style.transform = 'translateX(0px)';
carouseWrapLi[right].style.transform = 'translateX('+ windowWidth +'px)';
// 看到下一张的逻辑
function showNext(){
    // 轮转下标
    left = center;
    center = right;
    right++;

    // 极值判断
    if(right > carouseWrapLi.length - 1){
        right = 0;
    }

....

// 手指touch的时候去切换图片
jdCarouse.addEventListener('touchstart',touchstartHandler);
jdCarouse.addEventListener('touchmove',touchmoveHandler);
jdCarouse.addEventListener('touchend',touchendHandler);

var startX = 0;  // 记录开始的时候的手指落点
var moveX = 0;    // 记录移动最终的手指落点
var starTime = null;

function touchstartHandler(event){
    // 记录滑动开始的时间
    starTime = new Date();
    // 在最开始的时候清除定时器
    clearInterval(carouseTimer);
    // 获取手指的落点
    startX = event.touches[0].pageX;

4. 纯css3无缝滚动版

原理:结合CSS3的@keyframes

效果图:在线demo

clipboard.png

HTML

<div class="box">
    <ul>
        <li><a href="#"><img src="imgs/1.jpg" alt=""></a></li>
        <li><a href="#"><img src="imgs/2.jpg" alt=""></a></li>
        <li><a href="#"><img src="imgs/3.jpg" alt=""></a></li>
        <li><a href="#"><img src="imgs/4.jpg" alt=""></a></li>
        <!-- 复制两个临时工 -->
        <li><a href="#"><img src="imgs/1.jpg" ></a></li>
        <li><a href="#"><img src="imgs/2.jpg" alt=""></a></li>
    </ul>
</div>

css

* {
    padding: 0;
    margin: 0;
    list-style-type: none;
}
.box {
    width: 533px;
    height: 200px;
    border: 1px solid #000;
    margin: 100px auto;
    position: relative;
    overflow: hidden;
}
.box:hover ul{
    /* 在hover的时候让动画暂停 */
    animation-play-state:paused;
}
img{
    display: block;
}
ul {
    width: 3198px;
    height: 200px;
    position: absolute;
    left: 0;
    top: 0;
    animation: wufeng 10s linear infinite;
}
@keyframes wufeng{
    0%{
        left: 0;
    }
    100%{
        left: -2132px;
    }
}
ul li{
    float: left;
}

完整代码可以去:
https://github.com/aloe2014/s...
https://github.com/aloe2014/s... (移动版)

(此文献与对原生js动画保有热爱的我们......)

阅读 8.2k

推荐阅读
目录