jQuery 幻灯片的实现原理

淡入淡出的轮播

  • slide-ul 是幻灯片的盒子 包括了所有的img position: relative;
  • img position: absolute; 全部隐藏,默认显示第一张图片
  • pageIndex 分页索引对应 img 的索引
  • 在点击分页索引时 给对应的 img 显示,其它的 img 隐藏
  • 设置一个定时器函数每三秒执行一次,每次都传入 pageIndex 实现定时切换 默认是 0 判断 (pageIndex++ >= img.length) ? 0 : pageIndex++
  • 鼠标移入图片清除定时器 鼠标移出时重启定时器

实例代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>jQuery-slide-fadeIn</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        body {
            font-family: "Droid Serif","Helvetica Neue",Helvetica,Arial,sans-serif;
            font-size: 14px;
        }
        .clearfix:after{
            content: "";
            display: block;
            clear: both;
        }
        input,button,select,textarea{
            outline:none;border: none;
        }
        a{
            text-decoration: none;
            color: #fff;
        }
        ul,li{
            list-style: none;
        }
        img{
            border: none;
        }
        .wrap{
            width: 790px;
            margin: 20px auto;
        }
        .slide-box{
            height: 340px;
            overflow: hidden;
            position: relative;
        }
        .slide-left{
            width: 100%;
            position: relative;
        }
        .slide-left li{
            position: absolute;
            display: none;
        }
        .slide-left li a{
            display: block;
        }
        .slide-left li a img{
            width: 100%;
        }
      
        .slider-indicator{
            position: absolute;
            z-index: 1;
            left: 50%;
            transform: translateX(-50%);
            bottom: 20px;
            font-size: 0;
            padding: 4px 8px;
            border-radius: 12px;
            background-color: rgba(255, 255, 255, 0.3);
        }
        .slider-indicator i{
            display: inline-block;
            margin-right: 10px;
            width: 12px;
            height: 12px;
            border-radius: 100%;
            background-color: #fff;
            cursor: pointer;
        }
        .slider-indicator i.page-active{
            background-color: #2196F3;
        }
        .slide-btn{
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            z-index: 1;
            display: block;
            width: 40px;
            height: 50px;
            line-height: 45px;
            background-color: rgba(0,0,0,.2);
            font-size: 20px;
            text-align: center;
            display: none;
        }
        .slider-prev{
            left: 0;
            border-top-right-radius: 6px;
            border-bottom-right-radius: 6px;
        }
        .slider-next{
            right: 0;
            border-top-left-radius: 6px;
            border-bottom-left-radius: 6px;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="slide-box clearfix">
            <ul class="slide-left"></ul>
            <div class="slider-indicator"></div>
            <a href="javascript:void(0)" class="slide-btn slider-prev">&lt;</a>
            <a href="javascript:void(0)" class="slide-btn slider-next">&gt;</a>
        </div>
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
    <script>
    $(function(){
        var data = [{
            url: '#1',
            img: '//img11.360buyimg.com/da/jfs/t4657/90/3561484677/83893/f05ac312/59004d0dNc66933b4.png'
        },
        {
            url: '#2',
            img: '//img1.360buyimg.com/da/jfs/t5122/78/482212244/90225/c4ccd3b7/59001933Nb4a11a00.jpg'
        },
        {
            url: '#3',
            img: '//img12.360buyimg.com/da/jfs/t3172/29/7532815266/78514/96c6e177/58ba3348N479cafe1.jpg'
        },
        {
            url: '#4',
            img: '//img20.360buyimg.com/da/jfs/t4249/102/1331521120/224199/40dcb547/58c0b221N5acfd3c6.jpg'
        },
        {
            url: '#5',
            img: '//img13.360buyimg.com/da/jfs/t5518/250/560655744/102051/9f4965b2/5901d835N6c3481c7.jpg'
        }];

        var slide = $('.slide-box');
        var prev = $('.slider-prev');
        var next = $('.slider-next');
        var slideLeftData = $('.slide-left');
        var slideIndicator = $('.slider-indicator');
        var index = 0,slideAuto=null,isAnimate=false;

        var slideData = '';     // 数据
        var pageIndicator = ''; // page的小点
        $.each(data, function(index, val) {
            slideData += "<li data-id="+index+"><a href="+val.url+">![](+val.img+)</a></li>";
            pageIndicator += "<i></i>";
        });
        slideLeftData.append(slideData);    // 给左边盒子添加图片信息

        slideIndicator.append(pageIndicator).find('i').eq(0).addClass('page-active'); // 给第一个小点添加样式
        $('.slide-left li').eq(0).show();

        prev.on('click', prevPage);     // 点击上一页
        next.on('click', nextPage); // 点击下一页
        // 自动运行函数
        var autoRun = function(){
            slideAuto = setInterval(function(){
                nextPage(index);
            }, 3000)
        }
        autoRun();
        // 上一页
        function prevPage(){
            if(isAnimate){ return;}
            isAnimate = true;
            index--;
            if(index < 0){
                index = data.length -1;
            }
            slideLeftData.find('li').eq(index).fadeIn().siblings().fadeOut();
            slidePage(index);
            isAnimate = false;
        }
        
        // 下一页
        function nextPage(){
            if(isAnimate){ return;}
            isAnimate = true;
            index++;
            if(index >= data.length){
                index = 0;
            }
            slideLeftData.find('li').eq(index).fadeIn().siblings().fadeOut();
            slidePage(index);
            isAnimate = false;
        }
        // page
        slideIndicator.on('mouseenter', 'i', function(){
            var pageIndex = $(this).index();
            index = pageIndex;
            $(this).addClass('page-active').siblings().removeClass('page-active');
            slideLeftData.find('li').eq(pageIndex).fadeIn().siblings().fadeOut();
        });
        // 获取当前page 并添加样式
        function slidePage(){
            slideIndicator.find('i').eq(index).addClass('page-active').siblings().removeClass('page-active')
        }
        // 鼠标移入时
        slide.on('mouseenter', function(){
            $('.slide-btn').show();     // 显示左右的按钮
            clearInterval(slideAuto);   // 清除定时器
        });
        // 鼠标移出时
        slide.on('mouseleave', function(){
            $('.slide-btn').hide();     // 隐藏左右的按钮
            autoRun();                  // 继续运行定时器
        }); 
    });
    </script>
</body>
</html>

轮播1在线查看

左右无缝切换的轮播

  • slide-box 是包括幻灯片的盒子,设置overflow: hidden;
  • slide-ul 是幻灯片的盒子(宽度为img的宽度*img的length) 包括了所有的img(浮动在一行)
  • 分别给 幻灯片的盒子 最前面克隆 img 的最后一个,最后面克隆 img 的第一个 4,0,1,2,3,4,0
  • 此时克隆了两个,重新给图片盒子宽度添加总长度, 给第0个写一个 left -img (一个宽度)就显示真正的第一个图片
  • 每点击下一页时 (pageIndex++ > imgLength -1) ? 0 : pageIndex++; 根据对应的pageIndex操作 left
  • 每点击上一页时 (pageIndex-- < 0) ? imgLength-1 : pageIndex--; 在对应的pageIndex操作 left
  • 点击到最后一个和最前面一个图片时,在动画效果结果后操作css让元素left值变成对应克隆的对象left,造成一个无限切换的错觉

实例代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>jQuery-slide-无缝滚动</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        body {
            font-family: "Droid Serif","Helvetica Neue",Helvetica,Arial,sans-serif;
            font-size: 14px;
        }
        .clearfix:after{
            content: "";
            display: block;
            clear: both;
        }
        input,button,select,textarea{
            outline:none;border: none;
        }
        a{
            text-decoration: none;
            color: #fff;
        }
        ul,li{
            list-style: none;
        }
        img{
            border: none;
        }
        .wrap{
            width: 790px;
            margin: 20px auto;
        }
        .slide-box{
            height: 340px;
            overflow: hidden;
            position: relative;
        }
        .slide-ul{
            width: 100%;
            position: relative;
        }
        .slide-ul li{
            width: 790px;
            float: left;
        }
        .slide-ul li a{
            display: block;
        }
        .slide-ul li a img{
            width: 100%;
        }
      
        .slider-indicator{
            position: absolute;
            z-index: 1;
            left: 50%;
            transform: translateX(-50%);
            bottom: 20px;
            font-size: 0;
            padding: 4px 8px;
            border-radius: 12px;
            background-color: rgba(255, 255, 255, 0.3);
        }
        .slider-indicator i{
            display: inline-block;
            margin-right: 10px;
            width: 12px;
            height: 12px;
            border-radius: 100%;
            background-color: #fff;
            cursor: pointer;
        }
        .slider-indicator i.page-active{
            background-color: #2196F3;
        }
        .slide-btn{
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            z-index: 1;
            display: block;
            width: 40px;
            height: 50px;
            line-height: 45px;
            background-color: rgba(0,0,0,.2);
            font-size: 20px;
            text-align: center;
            display: none;
        }
        .slider-prev{
            left: 0;
            border-top-right-radius: 6px;
            border-bottom-right-radius: 6px;
        }
        .slider-next{
            right: 0;
            border-top-left-radius: 6px;
            border-bottom-left-radius: 6px;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="slide-box clearfix">
            <ul class="slide-ul"></ul>
            <div class="slider-indicator"></div>
            <a href="javascript:void(0)" class="slide-btn slider-prev">&lt;</a>
            <a href="javascript:void(0)" class="slide-btn slider-next">&gt;</a>
        </div>
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
    <script>
    $(function(){
        var data = [{
            url: '#1',
            img: '//img11.360buyimg.com/da/jfs/t4657/90/3561484677/83893/f05ac312/59004d0dNc66933b4.png'
        },
        {
            url: '#2',
            img: '//img1.360buyimg.com/da/jfs/t5122/78/482212244/90225/c4ccd3b7/59001933Nb4a11a00.jpg'
        },
        {
            url: '#3',
            img: '//img12.360buyimg.com/da/jfs/t3172/29/7532815266/78514/96c6e177/58ba3348N479cafe1.jpg'
        },
        {
            url: '#4',
            img: '//img20.360buyimg.com/da/jfs/t4249/102/1331521120/224199/40dcb547/58c0b221N5acfd3c6.jpg'
        },
        {
            url: '#5',
            img: '//img13.360buyimg.com/da/jfs/t5518/250/560655744/102051/9f4965b2/5901d835N6c3481c7.jpg'
        }];

        var slide = $('.slide-box'),    // 幻灯片盒子
            prev = $('.slider-prev'),   // 上一页按钮
            next = $('.slider-next'),   // 下一页按钮
            slideUl = $('.slide-ul'),   // 图片盒子
            slideIndicator = $('.slider-indicator'),    // 中部page盒子
            pageIndex = 0,      // page索引
            slideAuto=null,     // 自动滚动方法
            isAnimate=false,    // 事件锁
            slideData = '',     // img数据变量
            pageIndicator = ''; // page的小点变量

        // 循环添加img数据和page小点的个数
        $.each(data, function(index, val) {
            slideData += "<li data-id="+index+"><a href="+val.url+">![](+val.img+)</a></li>";
            pageIndicator += "<i></i>";
        });
        // 给盒子添加图片信息
        slideUl.append(slideData);  
        // 给page盒子添加小点并给第一个添加 page-active 样式
        slideIndicator.append(pageIndicator).find('i').eq(0).addClass('page-active'); 
        // 默认给第一个li添加显示
        $('.slide-ul li').eq(0).show();
        // 获取图片盒子里面的 li 个数
        var imgLength = slideUl.children().length;
        // 分别给 图片盒子 最前面克隆 li 最后一个,最后面克隆 li 第一个 [4,0,1,2,3,4,0]
        var lastLi = slideUl.find('li').last(); 
        var firstLi = slideUl.find('li').first();
        slideUl.prepend(lastLi.clone())
        slideUl.append(firstLi.clone());

        // 获取克隆后图片盒子里面的 li 个数 
        var countLength = slideUl.children().length;
        // 单独一个li的盒子宽度
        var slideLiWidth = slideUl.find('li').width();
        // 重新计算出 图片盒子 的宽度 让 li 浮动在一行 
        var boxWidth = countLength * slideLiWidth;
        // 给图片盒子宽度添加总长度 然后第一个看到的是克隆的那个,所以给个 - 一个li宽度 就显示真正的第一个 
        slideUl.css({'left': -slide.width(), width: boxWidth});

        // 点击上一页
        prev.on('click', function(){
            prevPage(1)
        });     
        // 点击下一页
        next.on('click', function(){
            nextPage(1);
        });
        
        // 自动运行函数
        var autoRun = function(){
            slideAuto = setInterval(function(){
                nextPage(1);
            }, 3000)
        }
        autoRun();
        // 上一页
        function prevPage(len){
            if(isAnimate){ return;}
            isAnimate = true;
            pageIndex -=len;
            // '-='+slideLiWidth 0 -790px -1580px -2370px -3160px -3950px
            slideUl.animate({left: '+='+len*slideLiWidth },function(){
                if( pageIndex < 0){
                    pageIndex = imgLength-1; // 获取最后一个
                    slideUl.css({left: -slideLiWidth*imgLength}); // 默认回到 -3950px 也就是第后一个
                }
                isAnimate = false;
                slidePage(pageIndex); // 获取当前的 小点 状态 
            });

        }
        // 下一页
        function nextPage(len){
            if(isAnimate){ return;}
            isAnimate = true;
            pageIndex += len;
            console.log( pageIndex )
            // '-='+slideLiWidth -790px -1580px -2370px -3160px -3950px
            slideUl.animate({left: '-='+len*slideLiWidth },function(){
                // 判断当前索引是否等于img图片的长度(没克隆前的长度)
                if(pageIndex > imgLength -1 ){
                    pageIndex = 0;  // 给索引值设置为0 也就是当前一个
                    slideUl.css({left: -slideLiWidth}); // 默认回到 -790px 也就是第0个
                }
                isAnimate = false;
                slidePage(pageIndex); // 获取当前的 小点 状态 
            });
        }
        // 点击切换
        slideIndicator.on('click', 'i', function(){
            var index = $(this).index();
            $(this).addClass('page-active').siblings().removeClass('page-active');
            if(pageIndex > index){          // 当前page 大于 当前索引
                prevPage(pageIndex - index); // 向后移动
            }else{
                nextPage(index - pageIndex); // 向前移动
            }
        });
        // 获取当前page 并添加样式
        function slidePage(){
            slideIndicator.find('i').removeClass('page-active').eq(pageIndex).addClass('page-active')
        }
        // 鼠标移入时
        slide.on('mouseenter', function(){
            $('.slide-btn').show();     // 显示左右的按钮
            clearInterval(slideAuto);   // 清除定时器
        });
        // 鼠标移出时
        slide.on('mouseleave', function(){
            $('.slide-btn').hide();     // 隐藏左右的按钮
            autoRun();                  // 继续运行定时器
        }); 
    });
    </script>
</body>
</html>

轮播2在线查看

制作简书首页的幻灯片

  • 功能结合了淡入淡出和无缝滚动

轮播3在线查看

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352

推荐阅读更多精彩内容