相关文章推荐
销魂的水桶  ·  subprocess时报sudo: ...·  1 年前    · 
老实的水煮肉  ·  git push 出现Everything ...·  1 年前    · 
重情义的八宝粥  ·  Java给出一个 32 ...·  1 年前    · 
酷酷的扁豆  ·  Remove Disabled Users ...·  1 年前    · 
首发于 风拂前端
JS实现无缝切换轮播图(自动+手动)

JS实现无缝切换轮播图(自动+手动)

一、背景

说起轮播图,大家应该都不陌生,各大购物网站和面试题里都能看到它的身影。

实现上也并不困难,而写这篇文章是想整理一下自己心血来潮写的代码,以及实现过程中的一些思考,大家也可以顺便复习巩固一下。

今天给大家带来的是 过渡动画等效果都由JS实现 的无缝轮播图。CSS实现轮播图等以后再写。


二、概述

(一) 实现的效果

①自动播放

②鼠标停留时停止播放,并显示左右切换按钮

③点击左右按钮或者圆形下标时可手动切换

④图片可无缝切换,首尾图片切换时无违和感

(二) 布局

所有图片横向排列 ,然后 依次向左移动 至显示区域内(红框),借助 overflow: hidden; 让显示区域以外的内容不显示,基本布局就成型了。

(三) 动画效果

通过JS实现动画效果,要借助定时器 setInterval() 固定的时间间隔等距移动图片 (如10ms移动10px),直至达到目标位置。

(四) 无缝切换

所谓无缝切换就是轮播图翻页时,用户不会感受到明显的跳动,而是均匀、平缓的变化。

首先,将第一张图片 复制一份 ,添加至所有图片的末尾( 即图⑥ ),这张图片将起到过渡作用:

  • 当要从 图① 翻至 图⑤ 时【 向左翻页 】,改变偏移量 -> 将当前图片变为 图⑥ ,再执行翻页动作;
  • 当要从 图⑥ 翻至 图② 时【 向右翻页 】,改变偏移量 -> 将当前图片变为 图① ,再执行翻页动作;

也就是 首尾图片更替时 ,要多做一些处理。文字描述起来有点绕,结合 代码 实际效果 会好理解一些。


三、实现(详细代码见文末链接)

(一) HTML

这部分代码比较简单:

<!DOCTYPE html>
        <title>Auto Image Silder</title>
        <link href="css/slider.css" rel="stylesheet" type="text/css" />
        <script src="js/slider.js" type="text/javascript"></script>
    </head>
        <div id="slider">
            <ul class="slieder-item-container">
                <li><a href="#"><img src="images/1.jpg" /></a></li>
                <li><a href="#"><img src="images/2.jpg" /></a></li>
                <li><a href="#"><img src="images/3.jpg" /></a></li>
                <li><a href="#"><img src="images/4.jpg" /></a></li>
                <li><a href="#"><img src="images/5.jpg" /></a></li>
            <div class="arrow-container">
                <span class="left-arrow"><</span>
                <span class="right-arrow">></span>
            </div>
            <div class="indicator-container">
                <span class="indicator active"></span>
                <span class="indicator"></span>
                <span class="indicator"></span>
                <span class="indicator"></span>
                <span class="indicator"></span>
            </div>
        </div>
    </body>
</html>

注:一般来说点击轮播图,会跳转到该图片对应的详情页面,所以用 <a> 标签包裹图片

(二) 部分CSS

#slider, ul, a {
    width: 600px;
    height: 400px;
#slider {
    position: absolute;
    border: 2px solid black;
    /*padding: 3px;*/
    margin: 10px 0 0 10px;
    overflow: hidden;
    -webkit-user-select:none;
    -moz-user-select:none;
    -ms-user-select:none;
    user-select:none;
ul {
    position: absolute;
    list-style-type: none;
    width: 6000px;
    /*transition-duration: 0.3s;*/
li {
    float: left;
    display: inline-block;
img {
    width: 100%;
    height: 100%;
}

(三) 动画效果

调用 animation() 函数,传入的形参为要移动的元素及移动的目标值。

默认每10ms移动10px,当跨序翻页时(如点击轮播图下方的圆形下标,直接从第1页跳到最后一页),则移动的时间会缩短,每次移动的step值会增大。

function animate(element, target) {
    var step = 10;
    var time = 10;
    var gap = (Math.abs(target - element.offsetLeft) / slider_item_width);
    if (gap > 1) {
        step = step * gap;
        time = time / gap;
    if (element) {
        step = (element.offsetLeft > target) ? -step : step;
        clearInterval(intervalId);
        setCurrentActiveIndicator(curIndex);
        intervalId = setInterval(function () {
            if (Math.abs(element.offsetLeft + step) < Math.abs(target)) {
                element.style.left = element.offsetLeft + step + "px";
            } else {
                if (Math.abs(target - element.offsetLeft) > Math.abs(step)) {
                    element.style.left = element.offsetLeft + step + "px";
                } else {
                    clearInterval(intervalId);
                    intervalId = -1;
                    element.style.left = target + "px";
                    // 移动到目标位置,继续自动播放
                    if (autoplay) {
                        startAnimation(element);
        }, time);

(四) 无缝切换及自动播放

概述中提到过,轮播图首尾图片图片更替时,通过改变轮播图的 left 值,改变当前显示的图片,再进行翻页动作,使用户感受不过明显的跳转变化,这也就是 prev() next() 函数中所做的事。

  • 点击左、右翻页按钮,也就是单次调用 prev() next() 函数;
  • 点击小圆点,也是单次调用 next() 函数,但需将要跳转的下标值传入;
  • 而自动播放,则是每次轮播图移动到目标位置后,持续调用 startAnimation() 函数,而其内部也是调用 next() 函数。
function prev() {
    var element = slider_item_container;
    var li = element.children;
    curIndex = curIndex - 1;
    if (curIndex < 0) {
        element.style.left = -((li.length-1)*slider_item_width) + "px";
        curIndex = li.length-2;
    animate(element, -(curIndex*slider_item_width));
function next(nextIndex) {
    var element = slider_item_container;
    var li = element.children;
    if ((nextIndex != null) && (typeof(nextIndex) != "undefined")) {
        curIndex = nextIndex;
    } else {
        curIndex = curIndex + 1;
        if (curIndex > (li.length-1)) {
            element.style.left = 0 + "px";
            curIndex = 1;
    animate(element, -(curIndex*slider_item_width));
function startAnimation(element) {
    if (autoplayId) {
        clearTimeout(autoplayId);
    autoplayId = setTimeout(function () {
        next();
    }, autoplay_Delay);

四、总结

以上就是实现JS动画效果的无缝轮播图的要点,大家有疑问或者有更好的实现方式,也请提出来一起探讨。

最后和大家分享一下仅针对本文代码的一些小知识点(如下),更深层次的内容就留给大家挖掘了。

<span> 设宽高无效,但设了 position: absolute; 或者 display: inline-block; 就有效了

②子元素设置了 float:left ,父元素的 text-align 就失效了

③圆形: border-radius: 50%;

④不脱离文档流,或者相对布局可使用 margin; 0 auto; 水平居中

⑤元素上下左右居中:

.content {
    positon: absolute;
    width: 200px;
    height: 100px;