JS 轮播图实现效果

封装好的公共代码:

//Create  in  2020/9/11  by LX 
//获取元素非行内样式的方法  用法:getStyle(元素,样式名)
function getStyle (ele,prop){
    //1.编写主要代码
    //如果 元素.currentStyle == undefined  标准浏览器中
    if(ele.currentStyle == undefined){
        //为了让 别人 在函数外面 也能得到我们获取的属性值 我们要把属性值返回出来
        return getComputedStyle(ele)[prop];
    }else{
        return ele.currentStyle[prop];
    }
    //2.分析不确定的值 提取出来 作为参数  元素 属性
    //3.将参数带入到 函数中
}


//2.封装一个动画函数 可以来回运动  用法:move(元素,属性.终点,步长)
var timer = null;
function move (ele,prop,end,step){
    clearInterval(timer);
    //1.写入主要代码
    //1.设置三要素  准备工作
    var start = parseInt(getStyle(ele,prop));
    //处理步长
    step = end>start ? step : -step;
    //2.设置定时器  真正开始运动
    timer = setInterval(function(){
        //3.走一步的代码
        //3.1更新起点
        start += step;
        //3.3判断到达终点 
        //当前只判断了 从小走到大  也有可能 从大走到小
        //步长是正数 10  并且 起点>=终点 证明到终点
        //步长是负数 -10 并且 起点<=终点 证明到终点
        if((step>0&&start>=end) || (step<0&&start<=end)){
            clearInterval(timer);
            start = end;
        }
        //3.2定位到具体的 位置
        ele.style[prop] = start + 'px';
    },30)
    //2.分析不确定的值 提成参数  元素 属性 终点值 步长
    //3.将参数 带入到 函数中
}

//3.缓冲动画函数  bufferMove(元素,{属性名1:终点值,属性名2:终点值....},动画结束执行的函数)
function bufferMove(ele, obj, fun) {
    //0.防止定时器的叠加
    clearInterval(ele.timer);
    //1.设置定时器
    ele.timer = setInterval(function () {
        //声明一个变量  用来记录 当前所有属性 是否都到达终点  假设大家都到了
        var flag = '都到了';
        //2.循环 obj对象
        for (var key in obj) {//{500,height:500,opacity:0.3}
            //获取三要素
            //判断 如果是透明度 需要处理
            if(key=="opacity"){
                var start = parseFloat(getStyle(ele,key))*100;
                var end = obj[key]*100;
            }else{
                var start = parseInt(getStyle(ele,key));
                var end = obj[key];
            }
            var step = (end-start)/10;
            //处理步长
            step = step>0 ? Math.ceil(step) : Math.floor(step);

            //更新起点
            start += step;
            //判断没有到达终点
            if(start!=end){
                // clearInterval(ele.timer);
                flag = "有人没到";
            }
            //设置样式  
            //如果是透明度 要单独处理
            if(key=="opacity"){
                ele.style[key] = start / 100;
            }else{
                ele.style[key] = start + 'px';
            }

        }
        //判断一下 flag状态是什么  如果是 都到了  证明大家都到了
        if(flag == "都到了"){
            clearInterval(ele.timer);//这里动画彻底结束
            if(typeof fun=="function"){
                fun();
            }
        }

    }, 30)
}

轮播图代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>轮播图</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            list-style: none
        }

        #wrap {
            width: 960px;
            height: 320px;
            border: 2px solid red;
            margin: 50px auto;
            position: relative;
            overflow: hidden;
        }
        #left{
            position: absolute;
            width: 50px;
            height: 50px;
            top: 135px;
            left: 10px;
            font-size: 30px;
        }
        #right{
            position: absolute;
            width: 50px;
            height: 50px;
            top: 135px;
            right: 10px;
            font-size: 30px;
        }

        #wrap img {
            width: 960px;
            height: 320px;
        }

        #wrap ul {
            width: 4800px;
            position: absolute;
        }

        #wrap li {
            float: left;
        }

        #wrap p {
            position: absolute;
            bottom: 20px;
            width: 100%;
            text-align: center;
        }

        #wrap span {
            padding: 2px 8px;
            background: blue;
            color: #fff;
            margin-right: 4px;
        }

        #wrap .active {
            background: red;
        }
    </style>
</head>
<body>
    <!--1.可视区:一张图片的大小-->
    <div id="wrap">
        <!--2.图片列表-->
        <ul>
            <!-- <li><img src="img/1.jpg" alt=""></li>
            <li><img src="img/2.jpg" alt=""></li>
            <li><img src="img/3.jpg" alt=""></li>
            <li><img src="img/4.jpg" alt=""></li>-->
        </ul>
        <p>
            <!--<span class="active">1</span><span>2</span><span>3</span><span>4</span>-->
        </p>
        <button id="left">&lt;</button>
        <button id="right">&gt;</button>
    </div>
    <script src="./common.js"></script>
    <script>
        //1.获取元素
        var ul = document.querySelector("ul");
        var p = document.querySelector("p");
        var btns = document.querySelectorAll("button");
        var wrap = document.querySelector("#wrap");

        //2.动态渲染结构
        var imgArr = [
            "./img/1.jpg",
            "./img/2.jpg",
            "./img/3.jpg",
            "./img/4.jpg"
        ];
        //3.根据数据 添加li 和 序号span
        for(var i=0; i<imgArr.length; i++){
            //创建li
            var li = document.createElement("li");
            li.innerHTML = '<img src="'+imgArr[i]+'" alt="">';
            ul.appendChild(li);

            //创建span
            var span = document.createElement("span");
            span.innerHTML = i+1;
            p.appendChild(span);
        }
        var spans = p.children;//获取所有序号span
        spans[0].className = "active";

        //获取图片宽度
        var imgWid = ul.children[0].offsetWidth;
        //4.自动轮播
        var n = 0;//要显示的图片的索引
        function auto(){ 
            n++;
            //判断 如果当前已经是假0  并且还要往后走 就直接定位到真0  并向真1 走
            if(n>=5){
                ul.style.left = 0;
                n = 1;
            }
            //已经在第0张图片 还要向前走 就要立即定位到假0 向最后一张走
            if(n<0){
                ul.style.left = -4*imgWid + 'px';
                n = 3;
            }
            bufferMove(ul,{left:-n*imgWid});

            for(var j=0; j<spans.length; j++){
                spans[j].className = "";
            }
            if(n==4){
                spans[0].className = "active";
            }else{
                spans[n].className = "active";
            }
            
        }
        var timer = setInterval(auto,3000);

        //5.无缝轮播
        //放假图片
        var fade = ul.children[0].cloneNode(true);
        ul.appendChild(fade);

        //鼠标移入停止鼠标移出继续
        wrap.onmouseover = function(){
            clearInterval(timer);
        }
        wrap.onmouseout = function(){
            timer = setInterval(auto,3000)
        }

        //箭头轮播
        //点击右箭头 切换下一张
        btns[1].onclick = auto;
        //点击左箭头 切换上一张
        btns[0].onclick = function(){
            n-=2;
            
            auto();
        }

        //序号轮播
        for(var k=0; k<spans.length; k++){
            spans[k].idx = k;
            spans[k].onclick = function(){
                //判断  如果是假0 定位到真0
                if(n==4){
                    ul.style.left = 0;
                }
                //切换到对应的图片
                bufferMove(ul,{left:-this.idx*imgWid});
                //让序号亮起
                for(var l=0; l<spans.length; l++){
                    spans[l].className = ""
                }
                this.className = "active";
                //关联自动轮播
                n = this.idx;

            }
        }
    </script>
</body>
</html>
原文地址:https://www.cnblogs.com/shihaiying/p/13723705.html