纯手打高颜值轮播图,HTML5+CSS3+JQUERY

相信我,这是你能找到的,除了模板之外,纯手打的最强轮播图源码。

不论B站,还是imooc,除了模板我干不过(他们太专业了)。

我还是很自信吊打其他的轮播图组件的。

首先我的轮播图没有任何BUG,不论你怎么按,怎么玩,都不会有问题。

然后我给轮播图增加了一个进度条控件,然后追加了一些小细节作为彩蛋。

1、连续快速点击左右键,会进入快速切图模式(就是CSS3的动画不一样了)

2、鼠标放在指示器上,读条会停止。

3、没有使用任何定时器或者计时器一类的工具,我用两个回调函数设计了一个死循环。

4、因为第三点的存在,所以不论你切出浏览器,还是tab到其他标签页,过多久回来,我的轮播图依然能够正常运行。

5、点击指示器时,切图效果与快速浏览模式不同(就是CSS3的动画不一样了)。

6、用到了锁的概念,确保轮播图的稳定运行。

7、用到了三个算法,对z-index的排序进行纠正,所以哪怕遇到BUG,也可以自动修复。

8、CSS代码用的是LESS,如果要追加图片可以修改一下循环的参数即可。

然后HTML标签中的ID属性和CLASS属性命名按照规范书写,既可实现添加和删减图片。

是不是心动了呀,那就上代码了哟~

图就不发了,太晚了,搞不动了。

 

转载需注明,使用无需授权,但因使用遇到BUG造成的损失概不负责。(尽管我很自信没有BUG,但是保不齐)

结构:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>轮播图</title>
    <script type="text/javascript" src="./js/jquery.js"></script>
    <link rel="stylesheet" href="./css/carousel-figure.css">
    <link rel="stylesheet" href="./font/font.css">
</head>
<body>
    <div class="carousel-figure-container">
        <ul class="carousel-content-list" id="carousel-content-list">
            <li><a><img src="images/01.jpg" alt=""></a></li>
            <li><a><img src="images/02.jpg" alt=""></a></li>
            <li><a><img src="images/03.jpg" alt=""></a></li>
            <li><a><img src="images/04.jpg" alt=""></a></li>
            <li><a><img src="images/05.jpg" alt=""></a></li>
            <li><a><img src="images/06.jpg" alt=""></a></li>
        </ul>
        <div class="carousel-previous-button" id="carousel-previous-button">
            <i class="iconfont">&#xe629;</i>
        </div>
        <div class="carousel-next-button" id="carousel-next-button">
            <i class="iconfont">&#xe62a;</i>
        </div>
        <ul class="carousel-pointer-list" id="carousel-pointer-list">
            <li id="carousel-pointer-0"><div class="carousel-progress" id="carousel-progress-0"></div></li>
            <li id="carousel-pointer-1"><div class="carousel-progress" id="carousel-progress-1"></div></li>
            <li id="carousel-pointer-2"><div class="carousel-progress" id="carousel-progress-2"></div></li>
            <li id="carousel-pointer-3"><div class="carousel-progress" id="carousel-progress-3"></div></li>
            <li id="carousel-pointer-4"><div class="carousel-progress" id="carousel-progress-4"></div></li>
            <li id="carousel-pointer-5"><div class="carousel-progress" id="carousel-progress-5"></div></li>
        </ul>
    </div>
    <script src="js/carousel_figure.js"></script>
</body>
</html>

样式(LESS):

@import "./mixin/carousel-figure.less";

* {
  font-size: 12px;
  //margin: 0;
  //border: none;
  //padding: 0;
}

body {
  margin: 0;
  height: 100vh;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* 轮播图盒子 */
.carousel-figure-container {
  @box_width: 1226px;
  width: @box_width;
  height: 460px;
  position: relative;
  //border: 1px red solid;
  //行内元素居中 主要针对 ul2
  text-align: center;
  //margin-top: 100px;
  margin-left: auto;
  margin-right: auto;

  /* 轮播图内容组 */
  .carousel-content-list {
    width: 100%;
    height: 100%;
    position: relative;
    z-index: 1;
    //overflow: visible !important;

    &>li {
      position: absolute;
      top: 0;
      left: 0;

      /* 层级 */
      &:first-child {
        z-index: 6;
      }
      &:nth-child(2) {
        z-index: 5;
      }
      &:nth-child(3) {
        z-index: 4;
      }
      &:nth-child(4) {
        z-index: 3;
      }
      &:nth-child(5) {
        z-index: 2;
      }
      &:nth-child(6) {
        z-index: 1;
      }

      // 图片上浮
      &.float-upward {
        animation: float-upward 1s;
      }

      // 快速浮现
      &.float-upward-quick {
        animation: float-upward-quick 500ms;
      }

      // 点击浮现
      &.float-for-click {
        animation: float-for-click 100ms;
      }

      /* a标签 */
      a {
        /* 图组 */
        img {
          width: 100%;
          height: 100%;
        }
      }
    }
  }

  /* 后退按钮 */
  .carousel-previous-button {
    .center(35px, 70px, #00000050);
    left: 0;
    -webkit-border-radius: 0 5px 5px 0;
    -moz-border-radius: 0 5px 5px 0;
    border-radius: 0 5px 5px 0;
  }

  /* 前进按钮 */
  .carousel-next-button {
    .center(35px, 70px, #00000050);
    right: 0;
    -webkit-border-radius: 5px 0 0 5px;
    -moz-border-radius: 5px 0 0 5px;
    border-radius: 5px 0 0 5px;
  }

  /* 指示器组 */
  .carousel-pointer-list {
    position: relative;
    bottom: 60px;
    display: inline-block;
    z-index: 999;

    &>li {
      width: 60px;
      height: 6px;
      background: rgba(255,255,255,0.6);
      //opacity:.6;
      text-align: center;
      line-height: 20px;
      float: left;
      cursor: pointer;

      // 指示器 click 样式
      &.selected {
        background-color: white;
      }
      
      // 指示器悬停背景
      &:hover {
        background-color: white;
      }

      // 进度条停止
      .carousel-progress:hover {
        animation-play-state: paused;
      }

      // 进度条播放样式
      div.progress-play {
        height: 100%;
        background: #e74c3c;
        -webkit-animation: countdown 3s linear;
        -o-animation: countdown 3s linear;
        animation: countdown 3s linear;
        pointer-events: none;
      }
    }

    &>li:not(:last-child) {
      // 间距
      margin-right: 10px;
    }
  }
}

// 关键帧
// 主图浮现
@keyframes float-upward {
  100% {
    transform: scale(1);
    opacity: 0;
  }
}

// 主图快速浮现
@keyframes float-upward-quick {
  100% {
    transform: scale(1.05);
    opacity: 0;
  }
}

// 主图点击浮现
@keyframes float-for-click {
  100% {
    transform: scale(.9);
    opacity: 0;
  }
}

// 进度条倒计时
@-webkit-keyframes countdown{
  0% {
    width: 0;
  }
  90% {
    opacity: .8;
  }
  100% {
    width: 100%;
    opacity: .6;
  }
}
@pointer-columns: 6;

.center(@w, @h, @c) {
  position: absolute;
  top: 0;
  //right: 0;
  bottom: 0;
  //left: 0;
  margin: auto;
  width: @w;
  height: @h;
  background-color: @c;
  color: #fff;
  font-size: 27px;
  text-align: center;
  line-height: 70px;
  z-index: 9999;
  -moz-user-select: none; /*火狐*/
  -webkit-user-select: none; /*webkit浏览器*/
  -ms-user-select: none; /*IE10*/
  user-select: none;
  cursor: pointer;
}


.make-carousel-pointer() {
  .pointer(@index) { // initial 初始化
    @item: ~".carousel-pointer-@{index}:hover";
    .pointer((@index + 1), @item);
  }
  .pointer(@index, @list) when (@index =< @pointer-columns) {
    @item: ~".carousel-pointer-@{index}:hover";
    .pointer((@index + 1), ~"@{list}, @{item}");
  }
  .pointer(@index, @list) when (@index > @pointer-columns) {
    @{list} {
      background: white;
    }
  }
  .pointer(0); // 根据你的需要修改
}
const images = $("#carousel-content-list").children();
const pointer_dock_list = $("#carousel-pointer-list").children();
const progress_list = pointer_dock_list.children();
// 当前图片和进度条下标(数值统一)
let current_index = 0;
// 图片数组长度
let length = images.length;
// 是否在播放
let isPlay = false;
// 上一次按键时间
let older = 0;
// 是否快速模式
let isQuickModel = false;
// 模式 1 下一张 2 上一张 3 跳跃 默认下一张
let model = 1;
// 上一张图片
let jumpBeforeIndex;

// 页面打开执行
setTimeout(function(){
    addProgressStyle(0);
}, 0);

// 进度条样式
let addProgressStyle = (index) => {
    // 进度条动画
    $(getPointerDock(index)).addClass("selected");
    $(getPointerProgress(index)).addClass("progress-play");
};

// 获取指示器底座
let getPointerDock = (index) => {
    return "#carousel-pointer-" + index;
};

// 获取指示器读条
let getPointerProgress = (index) => {
    return "#carousel-progress-" + index;
};

// 移除进度条样式
let removeProgressStyle = (index) => {
    $(getPointerDock(index)).removeClass("selected");
    $(getPointerProgress(index)).removeClass("progress-play");
};

// 播放下一个进度条
let playProgressOfNext = () => {
    addProgressStyle(current_index);
};

// 中断当前进度条 更安全
let breakProgressOfAll = () => {
    // 撤销所有的正在播放的动画
    for (let i=0; i<length; i++){
        removeProgressStyle(i);
    }
};

// 中断当前进度条 不推荐
let breakProgressOfCurrent = (index) => {
    if (index === undefined) {
        index = current_index;
    }
    removeProgressStyle(index);
};

// 点击 播放下一个
let clickNext = (quick) => {
    // 当前元素执行动画
    $(images[current_index]).addClass(quick ? 'float-upward-quick' : 'float-upward');
};

// 指定更新下标
let updateIndex = (value) => {
    if (value === undefined || value < 0 || value > length-1) return;
    current_index = value;
};

// 更新下标 递增
let updateIncreaseIndex = () => {
    if (current_index + 1 === images.length) {
        current_index = 0;
    } else {
        ++current_index;
    }
};

// 更新下标 递增
let updatePreviousIndex = () => {
    if (current_index - 1 < 0) {
        current_index = images.length - 1;
    } else {
        --current_index;
    }
};

// 获取上一张index 不影响 current
let getPreviousIndex = () => {
    let index;
    index = current_index - 1;
    if (index < 0){
        index = length - 1;
    }
    return index;
};

// 获取下一张index 不影响 current
let getNextIndex = (temp_index) => {
    let index;
    if (temp_index !== undefined) {
        index = temp_index + 1;
    } else {
        index = current_index + 1;
    }
    return index >= images.length ? 0 : index;
};

// 立刻提升图片层级
// 参数:当前下标,目标下标
// old的下个索引 与 点击的进行交换
let immediatelyUpLevel = (old_index, target_index) => {
    // 获取下一个元素索引
    let nextIndex = getNextIndex(old_index);
    // 如果下一个元素与目标元素一致不用交换
    if(nextIndex === target_index) return;
    // 下个元素的 z-index
    let next_z_index = $(images[nextIndex]).css('z-index');
    images[nextIndex].style.cssText = "z-index:" + parseInt($(images[target_index]).css('z-index')) + ";";
    images[target_index].style.cssText = "z-index:" + next_z_index + ";";
};

// 点击 播放上一个
let clickPrevious = (quick) => {
    // 获取前一个元素索引
    let pIndex = getPreviousIndex();
    // 获取下一个元素索引
    let nIndex = getNextIndex();
    // 交换前后元素的层级
    let temp = $(images[nIndex]).css('z-index');
    images[nIndex].style.cssText = "z-index:" + parseInt($(images[pIndex]).css('z-index')) + ";";
    images[pIndex].style.cssText = "z-index:" + temp + ";";
    // 当前元素执行动画
    $(images[current_index]).addClass(quick ? 'float-upward-quick' : 'float-upward');
};

// 检查快速点击
let check_quickly = () => {
    const current = new Date();
    // 记录第一次点击
    if(!older) {
        older = current;
        return;
    }
    // 是否在高速模式下维持600点击
    let speed = current.getTime() - older.getTime();
    let flag = true;
    // 是否低于 600
    if (speed < 800){
        // 维持高速模式
        older = current;
        return true;
    }
    if (isQuickModel && flag) {
        // 结束快速模式
        isQuickModel = false;
        older = current;
        return false;
    }
    // 时间在1100毫秒内且非快速模式
    if (speed < 1200 && !isQuickModel){
        // 进入快速模式
        isQuickModel = true;
        // 更新时间
        older = current;
        return true;
    } else {
        older = current;
        return false;
    }
};

// 获取目标的下标
let getIndexForTarget = (target)=> {
    return $("#carousel-content-list li").index(target);
};

// 函数声明
// 图片切换动画回调函数
function pictureAnimationCallback(e) {
    console.log("10 回调函数");
    // 获取当前元素下标
    let index = getIndexForTarget(e.target);
    // 下标备份
    let cursor = index;
    // 模式判断
    switch(model) {
        case 1:
            console.log("模式1");
            // 当前元素移除动画
            $(e.target).removeClass('float-upward-quick float-upward');
            // 当前元素置底 立刻隐藏
            e.target.style.cssText = "z-index: 0;";
            // 元素重排
            for (let i=0; i<images.length; i++){
                if (cursor >= 0){
                    images[i].style.cssText = "z-index:" + cursor + ";";
                    cursor--;
                } else {
                    images[i].style.cssText = "z-index:" + (images.length - i + index) + ";";
                }
            }
            console.log("之后层级");
            for (let i=0; i<images.length; i++) {
                let z = $(images[i]).css('z-index');
                console.log("层级列表", z);
            }
            // 更新标记位
            updateIncreaseIndex();
            break;
        case 2:
            console.log("模式2");
            // 当前元素移除动画
            $(e.target).removeClass('float-upward-quick float-upward');
            // 当前元素置底 立刻隐藏
            e.target.style.cssText = "z-index: 0;";
            // 设置起点
            let breakpoint = (index === 0 ? images.length : index);
            // 设置递减
            let temp = images.length;
            for (let i=breakpoint; i<=images.length; i++){    // 4
                images[i-1].style.cssText = "z-index:" + temp + ";";
                temp--;
            }
            for (let i=0; i<breakpoint-1; i++){
                images[i].style.cssText = "z-index:" + temp + ";";
                temp--;
            }
            model = 1;
            // 更新标记位
            updatePreviousIndex();
            break;
        case 3:
            cursor = current_index;
            console.log("11 模式3回调函数");
            // 当前元素移除动画
            $(images[jumpBeforeIndex]).removeClass("float-for-click");
            // 当前元素置底 立刻隐藏
            images[jumpBeforeIndex].style.cssText = "z-index: 0;";
            // 后半部分
            let level = length - 1;
            for (let i=cursor; i<length; i++) {
                images[i].style.cssText = "z-index:" + level + ";";
                level--;
            }
            for (let i=0; i<cursor; i++){
                images[i].style.cssText = "z-index:" + level + ";";
                level--;
            }
            model = 1;
            break;
    }
    // 重置图片播放标记位
    isPlay = false;
    // 开始播放下一个进度条
    playProgressOfNext();
}

(function(){
    // 注册动画结束监听事件
    for (let j=0; j<length; j++){
        // 进度条点击函数
        pointer_dock_list[j].addEventListener("click", function(e){
            console.log("1 点击");
            // 拒绝播放
            if (isPlay) {
                console.log("1.1 正在播放图片,拒绝切换");
                return;
            }
            // 获取目标下标
            let target_index = $(pointer_dock_list).index(e.target);
            console.log("2 获取目标下标", target_index);
            // 拒绝跳转
            if (target_index === current_index){
                console.log("2.1 就在本页");
                return;
            }
            // 正在播放
            isPlay = true;
            console.log("3 正在播放锁");
            // 暂停进度条
            $("#carousel-progress-" + j).css("animation-play-state","paused");
            // 中断进度条 需要 current_index
            breakProgressOfAll();
            console.log("4 中断所有进度条");
            // 切换播放模式
            model = 3;
            console.log("5 设置模式");
            // 备份需要切换的图片的下标
            jumpBeforeIndex = current_index;
            console.log("6 备份索引");
            // 立刻提升目标图片层级 需要 current_index
            immediatelyUpLevel(current_index, target_index);
            console.log("7 提升图片层级");
            // 更新下标
            updateIndex(target_index);
            console.log("8 更新当前下标");
            // current_index 图片立刻动画
            $(images[jumpBeforeIndex]).addClass("float-for-click");
            console.log("8.1 jumpBeforeIndex", jumpBeforeIndex);
            console.log("9 执行动画");

        });

        // 进度条动画回调函数
        progress_list[j].addEventListener("webkitAnimationEnd", function() {
            // 正在播放
            isPlay = true;
            // 当前图片执行动画
            $(images[current_index]).addClass('float-upward');
            // 移除进度条
            removeProgressStyle(current_index);
        });

        // 主图动画回调函数
        images[j].addEventListener("webkitAnimationEnd", pictureAnimationCallback);

        // 进度条悬停事件
        $("#carousel-pointer-" + j).hover(() => {
            $("#carousel-progress-" + j).css("animation-play-state","paused");
        },() => {
            $("#carousel-progress-" + j).css("animation-play-state","running");
        });
    }
})();

$(document).ready(function(){
    // 点击事件
    $("#carousel-next-button").on("click", function(){
        // 拒绝播放
        if (isPlay) return;
        // 正在播放
        isPlay = true;
        // 中断进度条
        breakProgressOfCurrent();
        // 进度条选择器
        $(getPointerDock(getNextIndex())).addClass("selected");
        // 检查是否是快速点击
        const isQuick = check_quickly();
        // 切图
        clickNext(isQuick);
    });

    // 点击事件
    $("#carousel-previous-button").on("click",function(){
        // 拒绝播放
        if (isPlay) return;
        // 正在播放
        isPlay = true;
        // 修改播放顺序标记位
        model = 2;
        // 中断进度条
        breakProgressOfCurrent();
        // 进度条选择器
        $(getPointerDock(getPreviousIndex())).addClass("selected");
        // 检查是否是快速点击
        const isQuick = check_quickly();
        // 执行动画
        clickPrevious(isQuick);
    });
});

// ready();

// 进度条部分
// duration: 3000 只是一个测试
// $({property: 0}).animate({property: 100}, {
//     duration: 3000,
//     step: function() {
//         let percentage = Math.round(this.property);
//         $("#progress").css("width", percentage + "%");
//         if (percentage == 100) {
//             $("#progress").addClass("done");
//         }
//     }
// });

代码完整,正确配置即可顺利食用,晚安~

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值