zoukankan      html  css  js  c++  java
  • 三种方式实现轮播图功能

    手动实现轮播图

    使用纯HTMLCSSJavaScript实现轮播图功能。

    position

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

    实例

    <!-- 
        简单DEMO,未实现任何控制,单纯图片轮播 
    -->
    
    <!DOCTYPE html>
    <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; /* 居中 */
             600px; /* 设置宽度 */
            position: relative; /* 相对定位 */
            overflow: hidden; /* 超出隐藏 */
        }
        #carousel img{
             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"); // 创建<li>
                var img = document.createElement("img"); // 创建新的<img>
                img.src = imgArr[0].src; // 设置图片src
                li.appendChild(img); // 追加<img>到<li>
                slideContainer.appendChild(li); // 将第一张图片追加到轮播图的最后,作边缘处理
                timer = setInterval(() => {slide(slideContainer)},config.interval); // 设置定时器定时切换
            })();
        </script>
    </html>
    
    <!-- 
        加入控制按钮,上一张与下一张,直接切换按钮
        将第一张图片的边缘化进行处理
        对浏览器页面显隐与鼠标移入移出事件的支持
    -->
    
    <!DOCTYPE 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; /* 居中 */
             600px; /* 设置宽度 */
            position: relative; /* 相对定位 */
            overflow: hidden; /* 超出隐藏 */
        }
        #carousel img{
             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%;
             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;
             100%;
            bottom: 0;
            display: flex;
            justify-content: flex-end;
        }
        .unitBtn{
             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"); // 创建<li>
                var img = document.createElement("img"); // 创建新的<img>
                img.src = imgArr[0].src; // 设置图片src
                li.appendChild(img); // 追加<img>到<li>
                slideContainer.appendChild(li); // 将第一张图片追加到轮播图的最后,作边缘处理
                var li2 = document.createElement("li"); // 创建<li>
                var img2 = document.createElement("img"); // 创建新的<img>
                img2.src = imgArr[imgArr.length-1].src; // 设置图片src
                li2.appendChild(img2); // 追加<img>到<li>
                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也是可行的方案。

    实例

    <!DOCTYPE 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; /* 居中 */
             600px; /* 设置宽度 */
            position: relative; /* 相对定位 */
            overflow: hidden; /* 超出隐藏 */
        }
        #carousel img{
            position: absolute; /* 绝对定位 使图片堆叠 */
             600px; /* 设定大小 按比例缩放 */
            transition: all .6s; /* 动画 */
            opacity: 0; /* 隐藏 */
        }
        .imgActive{
            opacity: 1 !important; /* 显示图片 最高优先级 */
        }
    
        /* 控制按钮的样式 */
        #leftArrow,
        #rightArrow{
            position: absolute;
            left: 5px;
            top: 43%;
             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;
             100%;
            bottom: 0;
            display: flex;
            justify-content: flex-end;
            z-index: 1000;
        }
        .unitBtn{
             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,为每个图片设置动画属性即可。

    实例

    <!DOCTYPE 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; /* 居中 */
             600px; /* 设置宽度 */
            position: relative; /* 相对定位 */
            overflow: hidden; /* 超出隐藏 */
            height: 300px;
        }
        #carousel img{
             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>
    
  • 相关阅读:
    Sum Root to Leaf Numbers 解答
    459. Repeated Substring Pattern
    71. Simplify Path
    89. Gray Code
    73. Set Matrix Zeroes
    297. Serialize and Deserialize Binary Tree
    449. Serialize and Deserialize BST
    451. Sort Characters By Frequency
    165. Compare Version Numbers
    447. Number of Boomerangs
  • 原文地址:https://www.cnblogs.com/WindrunnerMax/p/12638005.html
Copyright © 2011-2022 走看看