用 jQuery 做个轮播

Jensony 2019-06-27

初次体验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,可以获取每个元素的兄弟元素

总结

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

相关推荐