使用三种方式实现轮播图功能,分别为js控制切换与动画,js控制切换与css控制动画,纯css实现轮播效果


手动实现轮播图

使用纯​​HTML​​​、​​CSS​​​、​​JavaScript​​实现轮播图功能。

position

使用​​position​​​的绝对定位与相对定位实现轮播图,首先将图片全部拼接成为一行,使用​​overflow: hidden;​​​将其他图片隐藏,将这一行图片加入定时任务不断进行左移,从而只显示中间的图片,对于边缘特殊处理,将第一张轮播图追加到一行图片之后,当切换到最后一张轮播图时,下一张即播放第一张图,当此图轮播完成后,将所有图片归位,提供两个​​DEMO​​,第一个是单纯的轮播不存在任何控制按钮,第二个则比较完善。

实例




<html>
<head>
<title>轮播图title>
<meta charset="utf-8">
<meta name="referrer" content="no-referrer">
head>
<style type="text/css">
body{
margin: 0;
padding: 0px;
}
#carousel{
margin: auto; /* 居中 */
width: 600px; /* 设置宽度 */
position: relative; /* 相对定位 */
overflow: hidden; /* 超出隐藏 */
}
#carousel img{
width: 600px; /* 设定大小 按比例缩放 */
}
#carousel > ul {
display: flex; /* 图片处理为一行 */
position: absolute; /* 设置绝对定位,实现相对于#carousel的绝对定位 */
}
#carousel > ul,
#carousel > ul > li{
padding: 0;
margin: 0;
list-style:none;
}
style>
<body>

<div id="carousel">
<ul>
<li>
<img src="http://www.sdust.edu.cn/__local/9/7A/B1/F29B84DEF72DD329997E8172ABA_664BA3EF_32466.jpg">
li>
<li>
<img src="http://www.sdust.edu.cn/__local/B/F3/E4/693AB931C9FFB84646970D53BFE_C506394A_4282CA.jpg">
li>
<li>
<img src="http://www.sdust.edu.cn/__local/F/7A/AA/E1459849AA8AB0C89854A41BD41_BF3BD857_BC0D8.jpg">
li>
<li>
<img src="http://www.sdust.edu.cn/__local/1/95/CB/EDC1450B8FD1B8A25FAAC726AA4_A36D4253_16C91.jpg">
li>
ul>
div>
body>
<script type="text/javascript">
var imgArr = []; // 图片数组
var curIndex = 0; // 当前显示图片
var timer = null; // 定时器

function slide(slideContainer){
var width = imgArr[curIndex].width; // 获取图片宽度,也就是每次切换图片要滑动的距离
var distanceMoved = 0; // 已经移动的距离
var step = 10; //切换的步长
var curConLeft = slideContainer.offsetLeft; // 获取ul的left
var slideInterval = setInterval(function (){ // 此定时器是为了实现切换动画
if(Math.abs(width - distanceMoved) > step){ // 边界判定,判断已移动距离以及应移动距离的差与步长关系
curConLeft -= step; // 大于步长则不断移动
slideContainer.style.left = `${curConLeft}px`; // 移动
distanceMoved += step; // 已移动距离加步长
}else{
clearInterval(slideInterval); // 若最后移动距离不足步长,则清除动画定时器
slideContainer.style.left = `${curConLeft - width + distanceMoved }px`; // 直接完成此次动画
distanceMoved = 0; // 重设移动距离为0
if(++curIndex === imgArr.length){ // index加1,判断是否为最后一张来作边缘处理
curIndex = 0; // 最后一张则重置index
slideContainer.style.left = 0; // 重置ul
}
}
}, 10);
}

(function start() {
var config = {
height: "300px", // 配置高度
interval: 5000 // 配置轮播时间间隔
}
document.getElementById("carousel").style.height = config.height; // 将轮播容器高度设定
document.querySelectorAll("#carousel img").forEach(v => imgArr.push(v)); // 获取所有图片组成数组
var slideContainer = document.querySelector("#carousel > ul"); // 获取ul也就是一行图片的容器
var li = document.createElement("li"); // 创建

  • var img = document.createElement("img"); // 创建新的
    img.src = imgArr[0].src; // 设置图片src
    li.appendChild(img); // 追加

  • slideContainer.appendChild(li); // 将第一张图片追加到轮播图的最后,作边缘处理
    timer = setInterval(() => {slide(slideContainer)},config.interval); // 设置定时器定时切换
    })();
    script>
    html>



  • <html>
    <head>
    <title>轮播图title>
    <meta charset="utf-8">
    <meta name="referrer" content="no-referrer">
    head>
    <link rel="stylesheet" type="text/css" href="https://at.alicdn.com/t/font_1582902_u0zm91pv15i.css">
    <style type="text/css">
    body{
    margin: 0;
    padding: 0px;
    }
    #carousel{
    margin: auto; /* 居中 */
    width: 600px; /* 设置宽度 */
    position: relative; /* 相对定位 */
    overflow: hidden; /* 超出隐藏 */
    }
    #carousel img{
    width: 600px; /* 设定大小 按比例缩放 */
    }
    #carousel > ul {
    display: flex; /* 图片处理为一行 */
    position: absolute; /* 设置绝对定位,实现相对于#carousel的绝对定位 */
    }
    #carousel > ul,
    #carousel > ul > li{
    padding: 0;
    margin: 0;
    list-style:none;
    }

    /* 控制按钮的样式 */
    #leftArrow,
    #rightArrow{
    position: absolute;
    left: 5px;
    top: 43%;
    width: 25px;
    height: 30px;
    background-color: #eee;
    display: flex;
    justify-content: center;
    align-items: center;
    opacity: 0.7;
    font-size: 20px;
    cursor: pointer;
    }
    #rightArrow{
    left: auto;
    right: 5px;
    }
    #sliderBtn{
    position: absolute;
    width: 100%;
    bottom: 0;
    display: flex;
    justify-content: flex-end;
    }
    .unitBtn{
    width: 10px;
    height: 10px;
    background-color: #eee;
    border-radius: 10px;
    margin: 10px;
    cursor: pointer;
    }
    .active{
    background-color: #4C98F7;
    }
    style>
    <body>

    <div id="carousel">
    <ul>
    <li>
    <img src="http://www.sdust.edu.cn/__local/9/7A/B1/F29B84DEF72DD329997E8172ABA_664BA3EF_32466.jpg">
    li>
    <li>
    <img src="http://www.sdust.edu.cn/__local/B/F3/E4/693AB931C9FFB84646970D53BFE_C506394A_4282CA.jpg">
    li>
    <li>
    <img src="http://www.sdust.edu.cn/__local/F/7A/AA/E1459849AA8AB0C89854A41BD41_BF3BD857_BC0D8.jpg">
    li>
    <li>
    <img src="http://www.sdust.edu.cn/__local/1/95/CB/EDC1450B8FD1B8A25FAAC726AA4_A36D4253_16C91.jpg">
    li>
    ul>

    <div id="leftArrow" class="iconfont icon-arrow-lift">div>
    <div id="rightArrow" class="iconfont icon-arrow-right">div>
    <div id="sliderBtn">div>
    div>
    body>
    <script type="text/javascript">
    var imgArr = []; // 图片数组
    var curIndex = 0; // 当前显示图片
    var timer = null; // 定时器
    var clickAllow = true; // 锁,是否允许用户点击
    var btnList = []; // 右下角切换按钮组

    function slide(slideContainer , targetIndex = curIndex + 1){
    var width = 0; // 计算切换图片要滑动的距离
    if(targetIndex > curIndex){
    for(let i=curIndex;i<targetIndex;++i) width+=imgArr[i].width; // 正向切换则计算本图片到后续图片宽度
    }else{
    if(targetIndex === -1) width = imgArr[imgArr.length-1].width; // 特殊处理第一张图片
    else for(let i=targetIndex;i<curIndex;++i) width+=imgArr[i].width; // 逆向切换处理宽度
    }
    clickAllow = false; // 不允许用户点击
    var step = width/60; // 动态设置步长
    step = targetIndex > curIndex ? step : -step; // 正向逆向切换
    var curConLeft = slideContainer.offsetLeft; // 获取ul的left
    var distanceMoved = 0; // 已经移动的距离
    var slideInterval = setInterval(function (){ // 此定时器是为了实现切换动画
    if(Math.abs(width - distanceMoved) > Math.abs(step)){ // 边界判定,判断已移动距离以及应移动距离的差与步长关系
    curConLeft -= step; // 大于步长则不断移动
    slideContainer.style.left = `${curConLeft - step}px`; // 移动
    distanceMoved += Math.abs(step); // 已移动距离加步长
    }else{
    clearInterval(slideInterval); // 若最后移动距离不足步长,则清除动画定时器
    var directMove = step > 0 ? (curConLeft - width + distanceMoved) : (curConLeft + width - distanceMoved); // 正向移动与逆向移动的计算方式不同
    slideContainer.style.left = `${directMove}px`; // 直接完成此次动画
    distanceMoved = 0; // 重设移动距离为0
    curIndex = targetIndex; // 设置当前index
    if(curIndex === imgArr.length){ // index加1,判断是否为最后一张来作边缘处理
    curIndex = 0; // 最后一张则重置index
    slideContainer.style.left = `-${imgArr[0].width}px`; // 重置ul
    }else if (curIndex === -1) {
    curIndex = imgArr.length-1; // 第一张重置index
    slideContainer.style.left = `-${slideContainer.offsetWidth - imgArr[imgArr.length-1].width - imgArr[0].width}px`; // 重置ul
    }
    switchBtnActive(); // 右下角按钮的切换
    clickAllow = true; // 允许点击
    }
    }, 10);
    }

    function switchBtnActive(){
    btnList.forEach((v) => {
    v.className = "unitBtn"; // 设置其他按钮为灰色
    })
    btnList[curIndex] .className = "unitBtn active"; // 设置当前按钮为蓝色
    }

    function createBtnGroup(carousel,slideContainer,config){
    document.getElementById("leftArrow").addEventListener('click',(e) => {
    clearInterval(timer); // 清除定时器,避免手动切换时干扰
    if(clickAllow) slide(slideContainer,curIndex-1); // 允许点击则切换上一张
    timer = setInterval(() => {slide(slideContainer)},config.interval); // 重设定时器
    })
    document.getElementById("rightArrow").addEventListener('click',(e) => {
    clearInterval(timer); // 清除定时器,避免手动切换时干扰
    if(clickAllow) slide(slideContainer,curIndex+1); // 允许点击则切换下一张
    timer = setInterval(() => {slide(slideContainer)},config.interval); // 重设定时器
    })
    var sliderBtn = document.getElementById("sliderBtn"); // 获取按钮容器的引用
    imgArr.forEach((v,i) => {
    let btn = document.createElement("div"); // 制作按钮
    btn.className = i === 0 ? "unitBtn active" : "unitBtn"; // 初设蓝色与灰色按钮样式
    btn.addEventListener('click',(e) => {
    clearInterval(timer); // 清除定时器,避免手动切换时干扰
    if(clickAllow) slide(slideContainer,i); // // 允许点击则切换
    timer = setInterval(() => {slide(slideContainer)},config.interval); // 重设定时器
    })
    btnList.push(btn); // 添加按钮到按钮组
    sliderBtn.appendChild(btn); // 追加按钮到按钮容器
    })
    }


    function edgeDispose(slideContainer){
    var li = document.createElement("li"); // 创建

  • var img = document.createElement("img"); // 创建新的
    img.src = imgArr[0].src; // 设置图片src
    li.appendChild(img); // 追加

  • slideContainer.appendChild(li); // 将第一张图片追加到轮播图的最后,作边缘处理
    var li2 = document.createElement("li"); // 创建

  • var img2 = document.createElement("img"); // 创建新的
    img2.src = imgArr[imgArr.length-1].src; // 设置图片src
    li2.appendChild(img2); // 追加

  • slideContainer.insertBefore(li2,slideContainer.firstChild); // 将最后一张图片追加到轮播图的最前,作边缘处理
    slideContainer.style.left = `-${imgArr[0].width}px`; // 重设ul位置
    }

    function eventDispose(carousel,slideContainer,config){
    document.addEventListener('visibilitychange',function(){ // 浏览器切换页面会导致动画出现问题,监听页面切换
    if(document.visibilityState=='hidden') clearInterval(timer); // 页面隐藏清除定时器
    else timer = setInterval(() => {slide(slideContainer)},config.interval); // 重设定时器
    });
    carousel.addEventListener('mouseover',function(){ // 鼠标移动到容器则不切换动画,停止计时器
    clearInterval(timer); // 页面隐藏清除定时器
    });
    carousel.addEventListener('mouseleave',function(){ // 鼠标移出容器则开始动画
    timer = setInterval(() => {slide(slideContainer)},config.interval); // 重设定时器
    });
    }


    (function start() {
    var config = {
    height: "300px", // 配置高度
    interval: 5000 // 配置轮播时间间隔
    }
    var carousel = document.getElementById("carousel"); //获取容器对象的引用
    carousel.style.height = config.height; // 将轮播容器高度设定
    document.querySelectorAll("#carousel img").forEach(v => imgArr.push(v)); // 获取所有图片组成数组
    var slideContainer = document.querySelector("#carousel > ul"); // 获取ul也就是一行图片的容器
    edgeDispose(slideContainer); // 对边缘处理
    eventDispose(carousel,slideContainer,config); // 对一些浏览器事件处理
    createBtnGroup(carousel,slideContainer,config); // 按钮组的处理
    timer = setInterval(() => {slide(slideContainer)},config.interval); // 设置定时器定时切换
    })();
    script>
    html>
  • opacity

    首先通过对图片绝对定位来使图片堆叠,通过使用​​opacity​​​来控制图片的显示与隐藏,即不使用​​Js​​​控制轮播图的切换动画,而使用​​CSS​​​动画来完成,由于是堆叠完成的,使用​​z-index​​也是可行的方案。

    实例


    <html>
    <head>
    <title>轮播图title>
    <meta charset="utf-8">
    <meta name="referrer" content="no-referrer">
    head>
    <link rel="stylesheet" type="text/css" href="https://at.alicdn.com/t/font_1582902_u0zm91pv15i.css">
    <style type="text/css">
    body{
    margin: 0;
    padding: 0px;
    }
    #carousel{
    margin: auto; /* 居中 */
    width: 600px; /* 设置宽度 */
    position: relative; /* 相对定位 */
    overflow: hidden; /* 超出隐藏 */
    }
    #carousel img{
    position: absolute; /* 绝对定位 使图片堆叠 */
    width: 600px; /* 设定大小 按比例缩放 */
    transition: all .6s; /* 动画 */
    opacity: 0; /* 隐藏 */
    }
    .imgActive{
    opacity: 1 !important; /* 显示图片 最高优先级 */
    }

    /* 控制按钮的样式 */
    #leftArrow,
    #rightArrow{
    position: absolute;
    left: 5px;
    top: 43%;
    width: 25px;
    height: 30px;
    background-color: #eee;
    display: flex;
    justify-content: center;
    align-items: center;
    opacity: 0.7;
    font-size: 20px;
    cursor: pointer;
    z-index: 1000;
    }
    #rightArrow{
    left: auto;
    right: 5px;
    }
    #sliderBtn{
    position: absolute;
    width: 100%;
    bottom: 0;
    display: flex;
    justify-content: flex-end;
    z-index: 1000;
    }
    .unitBtn{
    width: 10px;
    height: 10px;
    background-color: #eee;
    border-radius: 10px;
    margin: 10px;
    cursor: pointer;
    }
    .btnActive{
    background-color: #4C98F7;
    }
    style>
    <body>

    <div id="carousel">
    <img src="http://www.sdust.edu.cn/__local/9/7A/B1/F29B84DEF72DD329997E8172ABA_664BA3EF_32466.jpg">
    <img src="http://www.sdust.edu.cn/__local/B/F3/E4/693AB931C9FFB84646970D53BFE_C506394A_4282CA.jpg">
    <img src="http://www.sdust.edu.cn/__local/F/7A/AA/E1459849AA8AB0C89854A41BD41_BF3BD857_BC0D8.jpg">
    <img src="http://www.sdust.edu.cn/__local/1/95/CB/EDC1450B8FD1B8A25FAAC726AA4_A36D4253_16C91.jpg">

    <div id="leftArrow" class="iconfont icon-arrow-lift">div>
    <div id="rightArrow" class="iconfont icon-arrow-right">div>
    <div id="sliderBtn">div>
    div>
    body>
    <script type="text/javascript">
    var imgArr = []; // 图片数组
    var curIndex = 0; // 当前显示图片
    var timer = null; // 定时器
    var btnList = []; // 右下角切换按钮组

    function slide(targetIndex = curIndex + 1){
    curIndex = targetIndex % imgArr.length; // 获取当前index
    imgArr.forEach((v) => v.className = "" ); // 设置其他图片隐藏
    imgArr[curIndex] .className = "imgActive"; // 设置当前index图片显示
    btnList.forEach(v => v.className = "unitBtn") // 设置其他按钮为灰色
    btnList[curIndex] .className = "unitBtn btnActive"; // 设置当前按钮为蓝色
    }

    function createBtnGroup(carousel,config){
    document.getElementById("leftArrow").addEventListener('click',(e) => {
    clearInterval(timer); // 清除定时器,避免手动切换时干扰
    slide(curIndex-1); // 允许点击则切换上一张
    timer = setInterval(() => {slide()},config.interval); // 重设定时器
    })
    document.getElementById("rightArrow").addEventListener('click',(e) => {
    clearInterval(timer); // 清除定时器,避免手动切换时干扰
    slide(curIndex+1); // 允许点击则切换下一张
    timer = setInterval(() => {slide()},config.interval); // 重设定时器
    })
    var sliderBtn = document.getElementById("sliderBtn"); // 获取按钮容器的引用
    imgArr.forEach((v,i) => {
    let btn = document.createElement("div"); // 制作按钮
    btn.className = i === 0 ? "unitBtn btnActive" : "unitBtn"; // 初设蓝色与灰色按钮样式
    btn.addEventListener('click',(e) => {
    clearInterval(timer); // 清除定时器,避免手动切换时干扰
    slide(i); // // 允许点击则切换
    timer = setInterval(() => {slide()},config.interval); // 重设定时器
    })
    btnList.push(btn); // 添加按钮到按钮组
    sliderBtn.appendChild(btn); // 追加按钮到按钮容器
    })
    }

    function eventDispose(carousel,config){
    document.addEventListener('visibilitychange',function(){ // 浏览器切换页面会导致动画出现问题,监听页面切换
    if(document.visibilityState=='hidden') clearInterval(timer); // 页面隐藏清除定时器
    else timer = setInterval(() => {slide()},config.interval); // 重设定时器
    });
    carousel.addEventListener('mouseover',function(){ // 鼠标移动到容器则不切换动画,停止计时器
    clearInterval(timer); // 页面隐藏清除定时器
    });
    carousel.addEventListener('mouseleave',function(){ // 鼠标移出容器则开始动画
    timer = setInterval(() => {slide()},config.interval); // 重设定时器
    });
    }


    (function start() {
    var config = {
    height: "300px", // 配置高度
    interval: 5000 // 配置轮播时间间隔
    }
    var carousel = document.getElementById("carousel"); //获取容器对象的引用
    carousel.style.height = config.height; // 将轮播容器高度设定
    document.querySelectorAll("#carousel img").forEach((v,i) => {
    imgArr.push(v); // 获取所有图片组成数组
    v.className = i === 0 ? "imgActive" : "";
    });
    eventDispose(carousel,config); // 对一些浏览器事件处理
    createBtnGroup(carousel,config); // 按钮组的处理
    timer = setInterval(() => {slide()},config.interval); // 设置定时器定时切换
    })();
    script>
    html>

    CSS

    纯​​CSS​​​实现轮播图,完全使用​​CSS3​​​动画完成轮播,主要使用​​animation​​​属性与​​@keyframes​​​规则,使用​​left​​​控制距离,也可以使用​​opacity​​,为每个图片设置动画属性即可。

    实例


    <html>
    <head>
    <title>轮播图title>
    <meta charset="utf-8">
    <meta name="referrer" content="no-referrer">
    head>
    <link rel="stylesheet" type="text/css" href="https://at.alicdn.com/t/font_1582902_u0zm91pv15i.css">
    <style type="text/css">
    body{
    margin: 0;
    padding: 0px;
    }
    #carousel{
    margin: auto; /* 居中 */
    width: 600px; /* 设置宽度 */
    position: relative; /* 相对定位 */
    overflow: hidden; /* 超出隐藏 */
    height: 300px;
    }
    #carousel img{
    width: 600px; /* 设定大小 按比例缩放 */
    }
    #carousel > ul {
    display: flex; /* 图片处理为一行 */
    position: absolute; /* 设置绝对定位,实现相对于#carousel的绝对定位 */
    }
    #carousel > ul,
    #carousel > ul > li{
    padding: 0;
    margin: 0;
    list-style:none;
    }

    #carousel > ul{
    animation: switch 10s ease 1s infinite alternate; /* 设定动画播放 */
    }

    #carousel > ul:hover{
    animation-play-state: paused; /* 暂停动画 */
    }

    @keyframes switch{ /* 制定动画规则 */
    0%,13%{
    left: 0;
    }
    27%,41%{
    left: -600px;
    }
    55%,69%{
    left: -1200px;
    }
    83%,100% {
    left: -1800px;
    }
    }
    style>
    <body>

    <div id="carousel">
    <ul>
    <li>
    <img src="http://www.sdust.edu.cn/__local/9/7A/B1/F29B84DEF72DD329997E8172ABA_664BA3EF_32466.jpg">
    li>
    <li>
    <img src="http://www.sdust.edu.cn/__local/B/F3/E4/693AB931C9FFB84646970D53BFE_C506394A_4282CA.jpg">
    li>
    <li>
    <img src="http://www.sdust.edu.cn/__local/F/7A/AA/E1459849AA8AB0C89854A41BD41_BF3BD857_BC0D8.jpg">
    li>
    <li>
    <img src="http://www.sdust.edu.cn/__local/1/95/CB/EDC1450B8FD1B8A25FAAC726AA4_A36D4253_16C91.jpg">
    li>
    ul>
    div>
    body>
    html>

    每日一题

    https://github.com/WindrunnerMax/EveryDay