两种思路实现无缝滚动幻灯片

1.无缝滚动幻灯片思路一

无缝滚动幻灯片思路一:

  • 每次图片切换到最后一张再进行点击时,就没有图片了;
  • 所以加一张图片和第一张图片一样,也就是第二组第一张图片(实际就是加完图片后的最后一张);
  • 每次点击到这张图片时,将图片的索引序号瞬间切换到第一张(设置等于第一张的序号),因为图片一样的所以形成无缝的感觉
  • 重点:切换图片索引序号时,必须同时切换图片的位置
  • 注意这里的navs.length一定不要和lis.length混用,长度不一样
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
ul {
    margin: 0;
    padding: 0;
    list-style: none;
    /* transition: .2s linear; */
} 
img {
    vertical-align: top;
}
#wrap {
    margin: 40px auto;
    position: relative;
    width: 600px;
    height: 400px;
    border: 2px solid #000;
    overflow: hidden;
}    
#pics {
    position: absolute;
    left: 0;
    top: 0;
    display: flex;
    height: 400px;
    z-index: 1;
}
#pics li{
    width: 600px;
    height: 400px;
    overflow: hidden;
}
#pics img {
    width: 600px;
    height: 400px;
}
.btn {
    position: absolute;
    top: 170px;
    z-index: 2;
    width: 60px;
    font: 40px/60px "宋体";
    text-align: center;
    background: rgba(255, 255, 255, .6);
    text-decoration: none;
    color: #000;
}
.btn:hover {
    background: #fff;
}
.prev {
    left: 0;
}
.next {
    right: 0;
}
#navs {
    position: absolute;
    left: 0;
    bottom: 10px;
    z-index: 3;
    width: 100%;
    text-align: center;
}
#navs a {
    display: inline-block;
    width: 12px;
    height: 12px;
    background: #fff;
}
#navs .active {
    background: #f60;
}
</style>
</head>
<body>
<div id="wrap">
    <ul id="pics">
        <li>
            <img src="img2/img (1).jpg" />
        </li>
        <li>
            <img src="img2/img (2).jpg" />
        </li>
        <li>
            <img src="img2/img (3).jpg" />
        </li>
        <li>
            <img src="img2/img (4).jpg" />
        </li>
        <li>
            <img src="img2/img (5).jpg" />
        </li>
        <li>
            <img src="img2/img (1).jpg" />
        </li>
    </ul>
    <a href="javascript:;" class="btn prev"><</a>
    <a href="javascript:;" class="btn next">></a>
    <nav id="navs">
        <a class="active"></a>
        <a></a>
        <a></a>
        <a></a>
        <a></a>
    </nav>
</div>
<script src="mTween.js"></script>
<script>
    /*
        无缝滚动幻灯片思路一:
            每次图片切换到最后一张再进行点击时,就没有图片了;
            所以加一张图片和第一张图片一样,也就是第二组第一张图片(实际就是加完图片后的最后一张);
            每次点击到这张图片时,将图片的索引序号瞬间切换到第一张(设置等于第一张的序号),因为图片一样的所以形成无缝的感觉
            重点:切换图片索引序号时,必须同时切换图片的位置
            注意这里的navs.length一定不要和lis.length混用,长度不一样
    */
    {
      var wrap = document.querySelector("#wrap");
      var navs = wrap.querySelectorAll("#navs a");
      var prev = wrap.querySelector(".prev");
      var next = wrap.querySelector(".next");
      var ul = wrap.querySelector("#pics");
      var lis = wrap.querySelectorAll("#pics li");
       //通过改变translateX切换图片
      var img = lis[0].querySelector("img");
      var imgW = css(img,"width");

      css(ul,"translateX",0);
      var num = 0;//用于记录当前索引
      navs.forEach((item,index) => {
          item.onclick = () => {
               //首先清空所有的当前样式
               num = index;
               //切换图片并改变位置
                changePic();
          };

        //点击上一张
        prev.onclick = function(){
            //无缝处理:当点击上一张时,如果是第一组第0张,瞬间切换到第二组最后一张
            if(num==0){
                num = navs.length;
                //切换num同时还要切换图片位置
                css(ul,"translateX",-imgW * num);
            }
            num--;
            //切换图片并改变位置
            changePic();
        };
        
          //点击下一张:通过改变left值或者translateX切换图片
        next.onclick = function(){
            num++;
            //无缝处理:当切换到第二组第一张时,瞬间切换到第一组第一张
            //这里添加后就没有无缝效果了
            // if(num>=navs.length){
            //     num = 0;
            //     //切换num同时还要切换图片位置
            //     css(ul,"translateX",-imgW * num);
            // }
            
            //切换图片并改变位置
            changePic();
        };

        let changePic =()=>{
            //处理nav
            navs.forEach((item,index) =>{
                navs[index].classList.remove("active");
            });
            //给当前选中项加上active,需要加上过界处理
            navs[num%navs.length].classList.add("active");

            //点击nav时需切换到对应图片
            mTween({
                   el:ul,
                   attr:{
                    translateX:-imgW * num
                   },
                    cb(){
                        if(num >= navs.length){ //如果现在已经是 第二个第0张了,后边就空了
                            num = 0; // 这时回到第一个第0张,然后,继续往下走
                            css(ul,"translateX",0);
                        }   
                    }
               });
        };
      });
    }
</script>
</body>
</html>

2.无缝滚动幻灯片-思路二(比较复杂)

            无缝滚动幻灯片思路二:
                总共只有两张图片,一张为当前显示的图片,另一张为要切换的图片;
                每次点击后,当前显示图片序号设置为原本下一张图片的序号,而下一张的序号设置为原本下下张的图片序号;
                注意不是累加nowIndex和nextIndex,而是依次将nextIndex的值赋给nowIndex;
                图片index只有0和1,图片位置只有0和-600px,并通过mTween设置位置及动画效果;
                快速点击时会有跳跃感:因为点击下一张时,上一张动画还没有执行完,可以设置标识,动画还没执行完时,不能结束,当再回调函数中cb 中执行完后才能切换下一张;
                优化封装各个方法;
            步骤:
                1:实现上一张和下一张;
                    下一张:
                        设置当前显示的图片nowIndex和下一张要显示的图片nextIndex;
                        两张图片显示顺序为:nowIndex  nextIndex;(nextIndex表示下一张,nowIndex表示当前张)
                        每次点击下一张时,nowIndex变为nextIndex,而nextIndex则在nowIndex基础上+1;
                        当nextIndex显示的为最后一张图片时,将nextIndex设置为0,从头开始;
                        将所有图片设置在数组中,并通过innerHTML显示图片。再通过mTween设置位置及动画效果-600px-0;(**注意通过transform设置需先获取再设置,因为transform的值时无法直接获取的)
                        注意这里的动画是设置在父级ul上的,而不是li上
                        注意动画效果不要弄反了-600px-0,-600会显示,0会不显示。所以下一张时,是ul从-600到0,而上一张是ul从0到-600
                    上一张:
                        设置当前显示的图片nowIndex和下一张要显示的图片nextIndex;
                        两张图片显示顺序为:nextIndex nowIndex;(nextIndex表示上一张,nowIndex表示当前张)
                        每次点击下一张时,nowIndex变为nextIndex,而nextIndex则在nowIndex基础上-1;
                        当nextIndex显示的为第0张图片时,将nextIndex设置为最后一张,从最后再开始;
                        将所有图片设置在数组中,并通过innerHTML显示图片。再通过mTween设置位置及动画效果0-600px;
                2:实现点击a标签切换对应图片
                    点击nav时,会实现a标签样式变化,且切换到对应图片;
                    上一张下一张切换时,a标签也要对应改变;注意:需要nowIndex = nextIndex;后,即当前图片已经切换到nowIndex后再改变才能改变到当前的样式;
                    实现点击a标签时同步切换图片:
                        因为切换图片时同样要往前或者往后走,所以可以将点击a标签时的index传递给nextIndex,再传给上一张下一张切换即可;
                        所以需要封装上一张和下一张方法;
                    通过判断nextIndex nowIndex之间的大小(注意:需要将index传递给nextIndex),判断点击的按钮是在当前页的上一页还是下一页,再调用对应的方法。
                    如果nextIndex>nowIndex说明要切换到当页后面,反之相反;
                3:快速切换上一张和下一张时,图片之间有跳动
                    原因:每次切换时,前一张的动画还没有执行完成,就开始执行下一张的动画,就会产生跳动
                    解决:设置标识,判断如果动画已经执行完成,才能执行下一张的动画。
                    执行完成需在动画效果回调函数cb中设置
                4:将所有重复的代码进行封装
                    上下张切换中有重复代码可进行封装;
                    两个方法中不同的参数只有:nowIndex,nextIndex的位置,及translateX的两个值
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        ul {
            margin: 0;
            padding: 0;
            list-style: none;
        }

        img {
            vertical-align: top;
        }

        #wrap {
            margin: 40px auto;
            position: relative;
            width: 600px;
            height: 400px;
            border: 2px solid #000;
            overflow: hidden;
        }

        #pics {
            position: absolute;
            left: 0;
            top: 0;
            display: flex;
            height: 400px;
            z-index: 1;
        }

        #pics li {
            width: 600px;
            height: 400px;
            overflow: hidden;
        }

        #pics img {
            width: 600px;
            height: 400px;
        }

        .btn {
            position: absolute;
            top: 170px;
            z-index: 2;
            width: 60px;
            font: 40px/60px "宋体";
            text-align: center;
            background: rgba(255, 255, 255, .6);
            text-decoration: none;
            color: #000;
        }

        .btn:hover {
            background: #fff;
        }

        .prev {
            left: 0;
        }

        .next {
            right: 0;
        }

        #navs {
            position: absolute;
            left: 0;
            bottom: 10px;
            z-index: 3;
            width: 100%;
            text-align: center;
        }

        #navs a {
            display: inline-block;
            width: 12px;
            height: 12px;
            background: #fff;
        }

        #navs .active {
            background: #f60;
        }
    </style>
</head>

<body>
    <div id="wrap">
        <ul id="pics">
            <li>
                <img src="img2/img (1).jpg" />
            </li>
            <li>
                <img src="img2/img (2).jpg" />
            </li>
        </ul>
        <a href="javascript:;" class="btn prev">
            <</a> <a href="javascript:;" class="btn next">>
        </a>
        <nav id="navs">
            <a class="active"></a>
            <a></a>
            <a></a>
            <a></a>
            <a></a>
        </nav>
    </div>
    <script src="mTween.js"></script>
    <script>
        /*
            无缝滚动幻灯片思路二:
                总共只有两张图片,一张为当前显示的图片,另一张为要切换的图片;
                每次点击后,当前显示图片序号设置为原本下一张图片的序号,而下一张的序号设置为原本下下张的图片序号;
                注意不是累加nowIndex和nextIndex,而是依次将nextIndex的值赋给nowIndex;
                图片index只有0和1,图片位置只有0和-600px,并通过mTween设置位置及动画效果;
                快速点击时会有跳跃感:因为点击下一张时,上一张动画还没有执行完,可以设置标识,动画还没执行完时,不能结束,当再回调函数中cb 中执行完后才能切换下一张;
                优化封装各个方法;
            步骤:
                1:实现上一张和下一张;
                    下一张:
                        设置当前显示的图片nowIndex和下一张要显示的图片nextIndex;
                        两张图片显示顺序为:nowIndex  nextIndex;(nextIndex表示下一张,nowIndex表示当前张)
                        每次点击下一张时,nowIndex变为nextIndex,而nextIndex则在nowIndex基础上+1;
                        当nextIndex显示的为最后一张图片时,将nextIndex设置为0,从头开始;
                        将所有图片设置在数组中,并通过innerHTML显示图片。再通过mTween设置位置及动画效果-600px-0;(**注意通过transform设置需先获取再设置,因为transform的值时无法直接获取的)
                        注意这里的动画是设置在父级ul上的,而不是li上
                        注意动画效果不要弄反了-600px-0,-600会显示,0会不显示。所以下一张时,是ul从-600到0,而上一张是ul从0到-600
                    上一张:
                        设置当前显示的图片nowIndex和下一张要显示的图片nextIndex;
                        两张图片显示顺序为:nextIndex nowIndex;(nextIndex表示上一张,nowIndex表示当前张)
                        每次点击下一张时,nowIndex变为nextIndex,而nextIndex则在nowIndex基础上-1;
                        当nextIndex显示的为第0张图片时,将nextIndex设置为最后一张,从最后再开始;
                        将所有图片设置在数组中,并通过innerHTML显示图片。再通过mTween设置位置及动画效果0-600px;
                2:实现点击a标签切换对应图片
                    点击nav时,会实现a标签样式变化,且切换到对应图片;
                    上一张下一张切换时,a标签也要对应改变;注意:需要nowIndex = nextIndex;后,即当前图片已经切换到nowIndex后再改变才能改变到当前的样式;
                    实现点击a标签时同步切换图片:
                        因为切换图片时同样要往前或者往后走,所以可以将点击a标签时的index传递给nextIndex,再传给上一张下一张切换即可;
                        所以需要封装上一张和下一张方法;
                    通过判断nextIndex nowIndex之间的大小(注意:需要将index传递给nextIndex),判断点击的按钮是在当前页的上一页还是下一页,再调用对应的方法。
                    如果nextIndex>nowIndex说明要切换到当页后面,反之相反;
                3:快速切换上一张和下一张时,图片之间有跳动
                    原因:每次切换时,前一张的动画还没有执行完成,就开始执行下一张的动画,就会产生跳动
                    解决:设置标识,判断如果动画已经执行完成,才能执行下一张的动画。
                    执行完成需在动画效果回调函数cb中设置
                4:将所有重复的代码进行封装
                    上下张切换中有重复代码可进行封装;
                    两个方法中不同的参数只有:nowIndex,nextIndex的位置,及translateX的两个值
        */
        {
            let wrap = document.querySelector("#wrap");
            let pics = wrap.querySelector("#pics");

            let lis = wrap.querySelectorAll("#pics li");
            let navs = wrap.querySelectorAll("#navs a");

            let prev = wrap.querySelector(".prev");
            let next = wrap.querySelector(".next");

            let picW = css(lis[0], "width");
            let picAll = [
                "img2/img (1).jpg",
                "img2/img (2).jpg",
                "img2/img (3).jpg",
                "img2/img (4).jpg",
                "img2/img (5).jpg"
            ];

            let nowIndex = 0;//当前显示的图片
            let nextIndex = 0;//下一张要显示的图片

            let isMove = false;//用于判断动画是否已经执行完成,并可以开始执行下一张的动画

            //对上下张切换中的重复代码进行封装
            let changePic = (pic1, pic2, from, to) => {
                if (isMove) {
                    return;
                }
                isMove = true;
                //设置并显示图片
                lis[0].innerHTML = '<img src="' + pic1 + '" />';
                lis[1].innerHTML = '<img src="' + pic2 + '" />';

                // //设置图片的位置及动画效果
                css(pics, "translateX", from);
                mTween({
                    el: pics,
                    attr: {
                        translateX: to
                    },
                    cb: function () {
                        //动画执行完成后,将标识设置为false,才开始执行下一张的动画
                        isMove = false;
                    }
                });
                nowIndex = nextIndex;

                //切换时,改变a标签样式
                //首先清除所有的item样式
                navs.forEach((item, index) => {
                    item.classList.remove("active");
                });
                //给当前a标签加上active
                navs[nowIndex].classList.add("active");
            }

            // 封装上一张方法
            let toPrev = () => {
                changePic(picAll[nextIndex], picAll[nowIndex], -picW, 0);
            }

            //封装下一张方法
            let toNext = () => {
                changePic(picAll[nowIndex], picAll[nextIndex], 0, -picW);
            }

            //实现上一张
            prev.onclick = () => {
                // 每次点击上一张时,nextIndex在nowIndex基础上-1;
                nextIndex = nowIndex - 1;
                // 当nextIndex显示的为最后一张图片时,将nextIndex设置为0,从头开始;
                nextIndex = nextIndex < 0 ? navs.length - 1 : nextIndex;

                //实现上一张切换
                toPrev();
            };

            //实现下一张
            next.onclick = () => {
                // 每次点击下一张时,nextIndex在nowIndex基础上+1;
                nextIndex = nowIndex + 1;
                // 当nextIndex显示的为最后一张图片时,将nextIndex设置为0,从头开始;
                nextIndex = nextIndex > navs.length - 1 ? 0 : nextIndex;

                //实现下一张切换
                toNext();
            };

            //nav点击事件
            navs.forEach((item, index) => {
                item.onclick = () => {
                    nextIndex = index;
                    //nextIndex>nowIndex说明要切换到当前页后面
                    if (nextIndex > nowIndex) {
                        toNext();
                    } else if (nextIndex < nowIndex) {
                        toPrev();
                    }
                };
            });
        }
    </script>
</body>

</html>
发布了95 篇原创文章 · 获赞 115 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_34569497/article/details/98076616