用 jQuery 做个轮播

初次体验jQuery 之后,体验一下jQuery强大之处,做一个简单的轮播,实现图片切换。

点击按钮切换轮播

页面上面有三个img标签用两个div便签包裹好,class=images是用来布局的,一般不在布局的标签上面做任何操作,class=window是用来做轮播窗口的。三个button按钮,用于切换图片。

首先把图片一次排开,用class=images做布局,给它加上display:flex就可以实现浮动,如果图片浮动起来变形厉害,可以给它加上align-items:flex-start
class=window是轮播用的可视窗口,设置为图片的宽度;并加上overflow:hidden,隐藏超出可视窗口部分;
用JS 来控制CSS来实现图片切换,当我点击按钮,出现对应图片,当我点击第1张按钮按钮时,触发.on事件后执行后面的函数,把图片向左移动到指定位置,其余两个按钮也是做类似效果;

这样做你会发现切换图片太生硬了,这事我们可以加上一点动画过渡transtion:transform 0.5s,让它切换时平缓一点。

<script src="https://code.jquery.com/jquery-3.1.0.js"></script> //jQuery 文件
<style>
    .images{
        display: flex;  /*让图片浮动起来*/
        align-items:flex-start; /*图片浮动起来后,会变形*/
        border: 1px solid red;
        transition:transform 0.5s;  /*图片切换时加上过渡*/
    }
    .window{
        border: 1px solid green;
        width:279px;    /*设置为图片的宽度*/
        overflow: hidden;   /*超出的部分隐藏起来*/
    }
</style>
<div class="window">
    <div class="images" id="images1">
        <img src="images/dog1.jpg" width=279>
        <img src="images/dog2.jpg" width=279>
        <img src="images/dog3.jpg" width=279>
    </div>
</div>
<button id='p1'>第1张</button>
<button id='p2'>第2张</button>
<button id='p3'>第3张</button>
<script>
    //当按钮被点击时,触发后面的函数,将id为images1的元素向左移动一段距离
    $(p1).on('click',function(){    
        $(images1).css({transform:'translateX(0)'})
    });
    $(p2).on('click',function({
        $(images1).css({transform:'translateX(-279px)'})
    });
    $(p3).on('click',function(){
        $(images1).css({transform:'translateX(-558px)'})
    })
</script>

jQuery API 用法
.on()语法:.on( events, handler(eventObject) )
events类型是String,一个或多个空格分隔的事件,比如clickkeydown.myPlugin
handler(eventObject)类型是Function,事件被出发时执行函数

.css()用法:获取匹配元素集合中的第一个元素的样式属性的值设置每个匹配元素的一个或多个CSS属性

CSS样式:
display:flex; flex布局
align-items:flex-stare; 往侧轴起点靠
transition:transform 0.5s 动画过渡

样式行为分离

用上面的方法,有一个问题就是HTML 和CSS 分离了,但是CSS 和JS 没有分离,但是为什么img标签会有图片的宽度呢?

其实img是一个可替换元素,在img里面的下载下来之前,浏览器不知道img长什么样,所以需要先做一个占位符来占位,等图片下载下来时替换掉占位符,一旦页面下载错了就会看到占位符;如果不用这个占位符,浏览器就会随便找个占位符来占位,等图片下载下来后在替换这个占位符,在替换的过程中,后面的内容要让位置,这就是重排的过程,特别消耗CPU,所以图片的宽高很重要,知道图片宽高就要写上去。

如果做成CSS 和JS 分离,可以像下面这样写,就可以做到行为和样式分离:

<style>
    .position-1{
        transform:translate(0);
    }
    .position-2{
        transform:translate(-279px);
    }
    .position-3{
        transform:translate(-558px);
    }
</style>
<script>
    $(p1).on('click',function(){
        $(images1).removeClass('position-2').removeClass('position-3').addClass('position-1')
    });
    $(p2).on('click',function(){
        $(images1).removeClass('position-3').removeClass('position-1').addClass('position-2')
    });
    $(p3).on('click',function(){
        $(images1).removeClass('position-2').removeClass('position-1').addClass('position-3')
    });
</script>

但是这有一个问题,如果你页面有很多图片时,removeClass就会有很多,代码就没有那么整洁了,这个时候就最好还是用行为控制样式,因为没有办法部把所有的状态都写到JS 里面,所以只有用JS 动态生成CSS,所以不到万不得已最好不要用。

重复代码优化

用JS 控制样式的代码,可以改写一下,变得更简洁。

button标签外面在包裹一层div,如果用DOM 获取里面的button的顺序该怎么做呢?

<div id='buttons'>
    <button id='p1'>第1张</button>
    <button id='p2'>第2张</button>
    <button id='p3'>第3张</button>
</div>
var n;  //n存储的是:p3是第几个元素
var allButtons = p3.parentNode.children;    //先获取到p3的所有兄弟元素
for(var i = 0; i < allButton.length; i++){  //遍历这个数组
    if(allButtons[i] === p3){        //如果这数组中的第i个等于p3,那么i 的值就是p3的位置
        n = i+1;        //因为i 取值是0,1,2 所以需要加上1才能得到最后的结果
        break;      //找到就跳出if循环;
    }
}

如果不用jQuery,用DOM 提供的API 是要用6行代码才能实现。
那看看有jQuery 怎么做呢

<div class="window">
    <div class="images" id="images1">
        <img src="images/dog1.jpg" width=279>
        <img src="images/dog2.jpg" width=279>
        <img src="images/dog3.jpg" width=279>
    </div>
<div id='buttons'>
    <button>第1张</button>
    <button>第2张</button>
    <button>第3张</button>
</div>
<script>
    var allButtons = $('#buttons > button');    //用jQuery 方法获取所有子元素
    for(var i = 0; i < allButtons.length; i++){ //遍历这个数组
        $(allButtons[i]).on('click',function(x){    //这里要注意allButton[i]是DOM 对象,是没有.on()方法的;用DOM 的话,要使用.onclick()方法,所以这里要用$()来封装,变成jQuery对象
            var index = $(x.currentTarget).index(); //jQuery 提供的信息都传递给了函数参数,currentTarget是监听的那个按钮,用index就能找到你要操作元素的位置
            var n = index * -279;   //因为index 取值为[0,1,2]乘上图片大小就能到达相应位置
            $('#images1').css({
                transform:'translate(' + n + 'px)'  //点击时添加css
            })
        })
    }
</script>

jQuery API语法:
event.traget用户点击的那个按钮
event.currentTarget监听的那个按钮
index()从匹配的元素中搜索给定元素的索引值,从0开始计数。

用上面方法就可以把代码变的更简洁。

自动轮播

下面来看下,如果我要做成自动播放应该怎弄呢?
先来做一个数数的过程,每1s加1

var n = 0;
console.log(n);
setInteral(() => {
    n+=1;
    console.log(n);
},1000)

那如果我要实现0、1、2循环数数呢?

var n = 0;
console.log(n%3);   //用取余就可以
setInterval(()=>{
    n+=1;
    console.log(n%3);
},1000)

用它来做元素循环时不也很简单

循环播放

var n = 0;
var size = allButtons.length;   //有多少个按钮可以这样获取
allButton.eq(n%size).trigger('clcik');   //用DOM API 可以这样写parentNode.children[n%size],如果用jQuery 的话allButton[n%size]还是DOM 对象,这样的还要在封装,jQuery 提供了一个.eq()的方法
setInterval(()=>{
    n+=1;
    allButton.eq(n%size).trigger('clcik');
},1000)

jQuery API语法:
.eq(index)index是一个整数,指示元素的位置,以0为基数。
.trigger(eventType [, extraParameters ]) eventType类型是String,包含JS事件的字符串,比如clicksubmit

这样就可以实现自动轮播了,美中不足的是按钮变化我们看不见,那把按钮添加class看看

<style>
    .red{
        color:red;
    }
</style>
var n = 0;
var size = allButtons.length;
allButtons.eq(n%size).trigger('click').addClass('red');
var timerId = setInterval(function(){
    n+=1;
    allButtons.eq(n%size).trigger('click').addClass('red').siblings('.red').removeClass('red');   //siblings('.red').removeClass('red')获取当前元素的兄弟元素,删除它的class
})

jQuery API语法:
.siblings( [selector ] )类型是Selector,可以获取每个元素的兄弟元素

现在可以看到每张图片轮流播放,按钮颜色也随着改变。

进入或离开轮播窗口也能播放

但是现在有一个问题,当我鼠标进入轮播页面,它不能停止播放,那下面来看看怎么实现

$('.window').on('mouseenter',function(){
    window.clearsetInterval(timerId)    //当鼠标进入'class=window'窗口时,触发清除延时执行函数
})
$('.window').on('mouseleave',function(){
    timerId = setInterval(function(){
        allButtons.eq(n%size).trigger('click').addClass('red').siblings('.red').removerClass('red');  //当鼠标离开'class=window'窗口时,继续执行上面的延时执行函数
    },1000)
})

.mouseenter( handler(eventObject) )类型是Function,当鼠标进入触发函数
.mouseleave( handler(eventObject) )类型是Function,当鼠标离开进入触发函数

修复一个小bug

这里面有一个小bug,轮播的 trigger('click')时间和.on('click')产生了冲突。在for循环中.on('click')的最后加上

n = index;
allButtons.eq(n).addClass('red').siblings('.red').removeClass('red');

如下:

var allButtons = $('#buttons > button');
for(var i = 0; i < allButtons.length; i++){
    $(allButtons[i]).on('click',function(x){
        var index = $(x.currentTarget).index();
        var p = index * -279;
        $(images1).css({
            transform:'translate('+ p + 'px)'
        });
        n = index;
        allButtons.eq(n).addClass('red').siblings('.red').removeClass('red');
    })
}

整理代码

整理下刚刚写的自动轮播的代码

<script src="https://code.jquery.com/jquery-3.1.0.js"></script> //jQuery 文件
<style>
    .images{
        display: flex;  /*让图片浮动起来*/
        align-items:flex-start; /*图片浮动起来后,会变形*/
        border: 1px solid red;
        transition:transform 0.5s;  /*图片切换时加上过渡*/
    }
    .window{
        border: 1px solid green;
        width:279px;    /*设置为图片的宽度*/
        overflow: hidden;   /*超出的部分隐藏起来*/
    }
    .red{
        color:red;
    }
</style>
<div class="window">
    <div class="images" id="images1">
        <img src="images/dog1.jpg" width=279>
        <img src="images/dog2.jpg" width=279>
        <img src="images/dog3.jpg" width=279>
    </div>
</div>
<button id='p1'>第1张</button>
<button id='p2'>第2张</button>
<button id='p3'>第3张</button>
<script>
    //点击按钮切换
    var allButtons = $('#buttons > button');
    for(var i = 0; i < allButtons.length; i++){
        $(allButtons[i]).on('click',function(x){
            var index = $(x.currentTarget).index();
            var p = index * -279;
            $(images1).css({
                transform:'translate('+ p + 'px)'
            });
            n = index;
            allButtons.eq(n).addClass('red').siblings('.red').removeClass('red');
        })
    }
    //自动轮播
    var n = 0;
    var size = allButtons.length;
    allButtons.eq(n%size).trigger('click').addClass('red');
    var timerId = setInterval(function(){
        n+=1;
        allButtons.eq(n%size).trigger('click').addClass('red').siblings('.red').removeClass('red');   //siblings('.red').removeClass('red')获取当前元素的兄弟元素,删除它的class
    })
    
    //当鼠标进入轮播时,停止轮播
    $('.window').on('mouseenter',function(){
    window.clearsetInterval(timerId)    //当鼠标进入'class=window'窗口时,触发清除延时执行函数
})

    //当鼠标离开轮播时,进行进行轮播
    $('.window').on('mouseleave',function(){
    timerId = setInterval(function(){
        allButtons.eq(n%size).trigger('click').addClass('red').siblings('.red').removerClass('red');  //当鼠标离开'class=window'窗口时,继续执行上面的延时执行函数
    },1000)
})
</script>

优化代码

刚刚写的自动轮播部分,有很多重复的代码,将它们优化一下

<script src="https://code.jquery.com/jquery-3.1.0.js"></script> //jQuery 文件
<style>
    .images{
        display: flex;  /*让图片浮动起来*/
        align-items:flex-start; /*图片浮动起来后,会变形*/
        border: 1px solid red;
        transition:transform 0.5s;  /*图片切换时加上过渡*/
    }
    .window{
        border: 1px solid green;
        width:279px;    /*设置为图片的宽度*/
        overflow: hidden;   /*超出的部分隐藏起来*/
    }
    .red{
        color:red;
    }
</style>
<div class="window">
    <div class="images" id="images1">
        <img src="images/dog1.jpg" width=279>
        <img src="images/dog2.jpg" width=279>
        <img src="images/dog3.jpg" width=279>
    </div>
</div>
<button id='p1'>第1张</button>
<button id='p2'>第2张</button>
<button id='p3'>第3张</button>
<script>

    //点击按钮切换图片
    var allButtons = $('#buttons > button');
    for(var i = 0; i < allButtons.length; i++){
        $(allButtons[i]).on('click',function(x){
            var index = $(x.currentTarget).index();
            var p = index * -279;
            $(images1).css({
                transform:'translate('+ p + 'px)'
            });
            n = index;
            activeButton(allButtons.eq(n));
        })
    }
    
    //自动轮播
    var n = 0;
    var size = allButtons.length;
    allButtons.eq(n%size).trigger('click').addClass('red');
    var timerId = serTimer();
    
    //当鼠标进入轮播时,停止轮播
    $('.window').on('mouseenter',function(){
        window.clearsetInterval(timerId)    
    })

    //当鼠标离开轮播时,进行进行轮播
    $('.window').on('mouseleave',function(){
        timerId = serTimer();
    })
    
    
    //设置自动轮播
    function serTimer(){
        return setInterval(function(){
            n+=1;
            playSlide(n%size);
        }
    }

    //轮播时切换图片
    function playSlide(index){
        allButtons.eq(index).trigger('click'); 
    }
    
    //点击按钮图片切换时,激活class
    function activeButton($button){
        $button.addClass('red').siblings('.red').removerClass('red');
    }
</script>

用到的jQuery API

最后整理下这里面用到的jQuery API

  1. .on()语法:.on( events, handler(eventObject) )
  2. events类型是String,一个或多个空格分隔的事件,比如clickkeydown.myPlugin
  3. handler(eventObject)类型是Function,事件被出发时执行函数
  4. .css()用法:获取匹配元素集合中的第一个元素的样式属性的值设置每个匹配元素的一个或多个CSS属性
  5. event.traget用户点击的那个按
  6. event.currentTarget监听的那个按钮
  7. index()从匹配的元素中搜索给定元素的索引值,从0开始计数。
  8. .eq(index)index是一个整数,指示元素的位置,以0为基数。
  9. .trigger(eventType [, extraParameters ]) eventType类型是String,包含JS事件的字符串,比如clicksubmit
  10. .siblings( [selector ] )类型是Selector,可以获取每个元素的兄弟元素

总结

轮播所用的图片一字排开,通过移动位置,把相应的图片呈现在视窗上。
自动轮播的关键是循环,只要会自然计数方法就能掌握其中的道理。

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

推荐阅读更多精彩内容

  • 这次我们将用jQuery做一个轮播 在遵循原则:内容(HTML)、样式(CSS)、行为(JavaScript)分离...
    半斋阅读 196评论 0 0
  • querySelector 全局变量可耻,不能用用全局属性,那么要么会不小心覆盖别人,要么会不小心被别人覆盖用局部...
    tsl1127阅读 200评论 0 0
  • 课堂笔记 设计页面的原则: 内容、样式、行为的分离;即html负责内容,css负责样式,JavaScript负责行...
    Ga611阅读 889评论 0 1
  • 1.JQuery 基础 改变web开发人员创造搞交互性界面的方式。设计者无需花费时间纠缠JS复杂的高级特性。 1....
    LaBaby_阅读 1,341评论 0 2
  • 爱,到底是什么? 可能是我性格孤僻而又善良吧,和喜欢的人千言万语,和不喜欢的人一字不提。自从经历了一...
    风花雪月_befe阅读 414评论 0 1