手把手教你十分钟写出两个轮播

本文将手把手教你快速地实现两个简单常用的轮播效果,一个是无限滚动效果,一个是无限渐进渐出轮播效果
首先来看下两种效果的简单预览:
1.无限滚动

无限滚动

2.无限渐进渐出

渐进渐出

我们首先来实现相对更加简单的无限渐进渐出的效果

原理

首先,我们需要一个固定大小的用来展示轮播内容的窗口,然后将所有图片堆积在这个窗口中。
立体图如图

手把手教你十分钟写出两个轮播_第1张图片
立体图

我们可以使用绝对定位来实现
父容器使用position:relative,图片子代们使用position:absolute



首先我们需要将所有的图片都设置为display:none,先隐藏所有的图片,而后在JQ中fadeOut不需要展示的图片,fadeIn需要展示的图片即可。
我们先来写一个playNext(),在点击 展示后一张图片 的按钮后,这个函数会被调用~
代码的逻辑很简单,淡出当前的图片,淡入下一张图片
首先定义currentIndex变量,用作记录目前播放的是第几张图片

var currentIndex =0
$nextbtn.on('click', function(e){
         e.preventDefault()//阻止a链接的默认刷新事件,防止一点击a链接就刷新页面
         playNext()
    })
 //当前页fadeout,下一张fadein
   function playNext(){
        if(isFading){
            return //表示正在进行fadein/fadeout
        }
        isFading = true//给fadein/fadeout效果上锁
        $imgList.eq(currentIndex).fadeOut(500)//先让现在的图片消失
        currentIndex++
        $imgList.eq(currentIndex).fadeIn(500, function(){
            isFading = false
        })

    }

我们可以发现,这里仅仅简单粗暴地将currentIndex++,但是多加几次之后,currentIndex很快就会大于整个图片列表的长度,所以我们需要(currentIndex+1)%$imgLength,这样一取余,currentIndex永远不会超过图片列表的长度~
所以我们可以再多设置一个变量targetIndex
于是升级之后的playNext()为:

function playNext(){
        var targetIndex = (currentIndex+1)%$imgLength

        if(isFading){
            return //表示正在进行fadein/fadeout
        }
        isFading = true
        $imgList.eq(currentIndex).fadeOut(500)//先让现在的图片消失
        $imgList.eq(targetIndex).fadeIn(500, function(){
            isFading = false
        })

        currentIndex = targetIndex//改变currentIndex,使其依旧表示目前在展示的图片
    

相信聪明的你一定发现了, 播放前一张图片的逻辑和 我们才写完的播放后一张图片的逻辑是一模一样的,都是淡出当前的图片,淡入需要展示的图片
只不过相应的targetIndex需要改变
先来看看规律~

手把手教你十分钟写出两个轮播_第2张图片
图片.png

可以观察得出,targetIndex = (currentIndex+$imgLength-1)%$imgLength
这里考察的是简单的数学哈哈哈~
因此我们可以抽象出一个Play函数,需要播放前一张和播放后一张时,只需要改变相应的参数即可

$prebtn.on('click', function(e){
       
         e.preventDefault()//阻止a链接的默认刷新事件,防止一点击a链接就刷新页面
         playPre()
    })

    $nextbtn.on('click', function(e){
         e.preventDefault()
         playNext()
    })

  
    //当前页fadeout,下一张fadein
    function playNext(){
        play((currentIndex+1)%$imgLength)
    }
    //当前页fadeout,前一张fadein
    function playPre(){
        play((currentIndex+$imgLength-1)%$imgLength)
    }


    function play(targetIndex){
        if(isFading){
            return //表示正在进行fadein/fadeout
        }
        isFading = true
        $imgList.eq(currentIndex).fadeOut(500)//先让现在的图片消失
        $imgList.eq(targetIndex).fadeIn(500, function(){
            isFading = false
        })

        currentIndex = targetIndex
   
    }

写到这里,效果就基本已经实现了~
在线demo
完整代码请看:
https://github.com/dandanloveJM/jirengu_gyd/blob/master/%E8%BF%9B%E9%98%B617%20%E8%BD%AE%E6%92%AD/fade.html

接下来,我们来写无限滚动的轮播

无限滚动轮播的原理

同样,我们需要一个固定大小的供轮播展示图片的窗口
不同于渐进渐出的时,这次我们需要把图片排成一行,假定每张窗口只能展示一张图片,当需要展示上一张图片时,将所有图片整体右移, 当需要展示下一张图片时,将所有的图片整体左移,同时在图片列表的首部复制最后一张图片,当移动到这种图片时,给读者营造出一种这是最后一张图片的假象,然后快速地整体移动图片列表的位置至真正的最后一张图片那里,同理,我们也需要在图片列表的尾部复制第一张图片
用图片表示更加直观:

手把手教你十分钟写出两个轮播_第3张图片
滚动轮播

首先复制首尾等等准备工作:

 var $imgList = $('.img-list')
 var $preBtn = $('.btn-pre')
 var $nextBtn = $('.btn-next')
 var $bullet = $('.bullet')
 var $firstImg = $imgList.find('li').first(),
     $lastImg = $imgList.find('li').last()

 $imgList.prepend($lastImg.clone())
 $imgList.append($firstImg.clone())

var currPageIndex = 0//知道当前在第几页
var imgLength = $imgList.children().length
$imgList.width($firstImg.width() * $imgList.children().length)//动态设定图片列表的长度~

同样,我们先来写playNext()函数
代码逻辑同样也比较简单
为了播放下一张图片,将整体图片左移一个图片的宽度即可
但这里有个神坑!!!千万不要用眼睛编程 QAQ

function playNext(){
  if(isAnimate){
    return //如果正在轮播则退出
  }

  isAnimate = true //表示轮播开始
  $imgList.animate({
    left:'-=310'
  }, function(){
    currPageIndex++;
    if(currPageIndex === imgLength){//当达到图片列表的下界,即到达最后一个我们复制的第一张图片了
      $imgList.css('left', '-310px')//强行设置整体图片列表的宽度
      currPageIndex = 0
    }
    isAnimate = false //轮播结束
    setBullet()
  })
 
}

这里我的图片的宽度是写定为310px.
有两个注意点:

  1. .animate方法可以接受参数值为-=10,这表示在原长度的基础上减少10
  2. .css() 方法的大坑:
    如果不想要写定宽度,而希望用变量表示图片的宽度:
    var imgWidth = $firstImg.width()
    此时的左移的写法为!!!
    $imgList.css('left', '-'+ imgWidth() + 'px')
    我在写的时候看到之前写-=10没有带像素,所以这里也没有带px,然后调了好久的bug。。。泪目。。
    这里的css方法里面的写法其实是跟平常写CSS的语法是一样的,平时都记得写了像素!这里也不能忘!

接下来我们来写playPre()
为了播放上一张图片,我们需要将图片整理右移,还有一个易错点,就是当播放到图片列表的上界时,即我们复制到首部的最后一张图片时的left的值应该为多少

function playPre(){

  if(isAnimate){
    return //如果正在轮播则退出
  }

  isAnimate = true //表示轮播开始
  $imgList.animate({
    left: '+=' + $firstImg.width()
  }, function(){
    currPageIndex--
    console.log('currPageIndex'+currPageIndex)
    if(currPageIndex < 0){
      $imgList.css({'left': -(imgLength*$firstImg.width())})
      currPageIndex = imgLength - 1
    }
    isAnimate = false //轮播结束
    setBullet()
  })
  
}

写到这里,轮播效果基本已经实现了

在线demo
完整代码

在此总结一下.css('width': 'value')和 .width()的区别
.width()返回一个没有单位的数值!类型为number
而前者的value可以为number也可以为string
所以!
第一种写法是直接在width()返回值前加负号,这样这个value的类型为number

$imgList.css('left', -$firstImg.width())

第二种写法是

$imgList.css('left', '-' + $firstImg.width() + 'px')

如果负号是用引号包裹,则这个value的值的类型为String,此时就需要添加px单位!!!

而在.animate()方法中用到的css属性时,-=+=只需要 数值即可,不需要单位

$imgList.animate({
left:'-=' + $firstImg.width()
},xxx...)

你可能感兴趣的:(手把手教你十分钟写出两个轮播)