Native JS simple carousel diagram

Carousel

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
    
    
            margin: 0;
            padding: 0;
        }
        ul,li{
    
    
            list-style: none;
        }
        .slider{
    
    
            width: 1130px;
            height: 286px;
            margin: 50px auto;
            position: relative;
            overflow: hidden;
        }
        .slider_img{
    
    
            width: 1130px;
            height: 286px;
        }
        .slider li{
    
    
            position: absolute;
            top: 0;
            left: 0;
            width: 1130px;
            height: 286px;
        }
        .slider li img{
    
    
            width: 100%;
            height: 100%;
        }
        .slider_btn{
    
    
            text-align: center;
        }
        .slider_btn .prev{
    
    
            background: url(https://static.zcool.cn/git_z/z/widget/slider/images/svg/left_arrow.svg?v=2);
            width: 52px;
            height: 52px;
            position: absolute;
            z-index: 100;
            top: 50%;
            margin-top: -26px;
            left: 10px;
            cursor: pointer;
        }
        .slider_btn .next{
    
    
            background: url(https://static.zcool.cn/git_z/z/widget/slider/images/svg/right_arrow.svg?v=2);
            width: 52px;
            height: 52px;
            position: absolute;
            z-index: 100;
            top: 50%;
            margin-top: -26px;
            right: 10px;
            cursor: pointer;
        }
        .xbtn{
    
    
            position: absolute;
            top: 93%;
            left: 50%;
            transform:translate(-50%,-50%);
        }
        .dot{
    
    
            display: inline-block;
            width: 15px;
            height: 15px;
            border: 1px solid yellow;
            border-radius: 50%;
            margin: 0 20px ;
            box-shadow: 0 0 5px black;
            cursor: pointer;
        }
        .dot_color{
    
    
            background-color: red;
        }
    </style>
</head>
<body>
    <div class="slider">
        <div class="slider_img">
            <ul>
                <li><a href="#"><img src="https://img.zcool.cn/community/01d6405f59b89111013e3187e86597.png@1380w" alt=""></a></li>
                <li><a href="#"><img src="https://img.zcool.cn/community/0102135f5c387111013e3187f5cafc.jpg@1380w" alt=""></a></li>
                <li><a href="#"><img src="https://img.zcool.cn/community/018a0a5f5c31f811013e3187ce23a5.jpg@1380w" alt=""></a></li>
                <li><a href="#"><img src="https://img.zcool.cn/community/01a6c05f599e5611013f1a647af2fc.jpg@1380w" alt=""></a></li>
                <li><a href="#"><img src="https://img.zcool.cn/community/015e555f5c394711013f1a64a7ea3f.jpg@1380w" alt=""></a></li>
                <li><a href="#"><img src="https://img.zcool.cn/community/01a2545f59b87e11013f1a645c4e01.png@1380w" alt=""></a></li>
                <li><a href="#"><img src="https://img.zcool.cn/community/0160515f59b8f311013f1a649a62bc.png@1380w" alt=""></a></li>
            </ul>
        </div>
        <div class="slider_btn">
            <span class="prev"></span>
            <span class="next"></span>
            <div class="xbtn">

            </div>
        </div>
    </div>
</body>
<script>

    /*
        需求分析:
            1 根据图片的数量自动生成小圆点(类名:dot)
            2 点亮第一个小圆点(当前小圆点:dot_color)
            3 显示第一个图片(li),其他里都放到右边(左边left:-容器宽度,右边left:容器宽度)
            4 点击小圆点显示相应的图片
            5 点击prev箭头,显示上一张
            6 点击next箭头,显示下一张
            7 轮播图会自动轮播
            8 鼠标移入slider盒子,停止轮播,鼠标移出slider盒子,继续轮播
    */

    //获取相关元素
    var slider = $id('.slider');//轮播图容器
    var WIDTH = slider.offsetWidth;//容器/图片的宽度
    var ImgArr = slider.children[0].children[0].children;//所有图片所在li的集合
    // console.log(ImgArr)
    var xbtn = $id('.xbtn')
    var slider_btn = slider.children[1];//轮播图控制按钮存放容器
    var prev_btn = $id('.prev');//上一张按钮
    var next_btn = $id('.next')
    var index = 0;//index是一个全局变量,记录当前显示的图片的索引

    for(var i=0 ; i<ImgArr.length ; i++){
    
    
        //建立小按钮节点
        var span = document.createElement('span');
        //给小按钮添加类名
        span.className = "dot";
        // span.innerHTML = i;
        span.index = i;//为了后期点击span的时候能够知道他是第几个
        //希望把span插入到xbtn的子元素
        xbtn.appendChild(span);


        //3 其他li都放到右边(左边left:-WIDTH,右边left:WIDTHpx)
        ImgArr[i].style.left = WIDTH + 'px';
    }
    
    //2 点亮第一个小圆点(当前小圆点:dot_color)
    var spanArr = xbtn.children;
    spanArr[index].className = "dot dot_color";
    //3 显示第一个li
    ImgArr[index].style.left = 0;

    //4 把小圆点,作用箭头的事件都委托给父元素slider_btn
    slider_btn.onclick = function(e){
    
    
        e = e||window.event;
        var target = e.target||e.srcElement;
        if(target.className=="prev"){
    
    
            console.log("你点击了上一张按钮");
            //如果当前图片索引是index,那么现在要看的索引是newIndex
            var newIndex = index-1;
            //如果newIndex<0,就是想看最后一张
            if(newIndex<0){
    
    
                newIndex = ImgArr.length-1;
            }
            //那么我要看的图一定在左边
            ImgArr[newIndex].style.left = -WIDTH + "px"
            //原来索引是index的图去右边
            animate(ImgArr[index],{
    
    left:WIDTH})
            //现在索引newIndex的图去中间
            animate(ImgArr[newIndex],{
    
    left:0});
            //更新最新的索引
            index = newIndex;
            //点亮小圆点
            light();
        }else if(target.className=="next"){
    
    
            console.log("你点击了下一张按钮")
            nextImg();
        }else if(target.className.indexOf("dot")>-1){
    
    
            console.log("你点击了小圆点,点击的小圆点的索引是"+target.index);
            //你要看的索引是newIndex
            var newIndex = target.index;
            //如果要看到索引newIndex>index,索引newIndex必须在右边
            if(newIndex>index){
    
    
                //索引是newIndex的图片必须在右边
                ImgArr[newIndex].style.left = WIDTH + "px";
                //原来索引是index的图去左边
                animate(ImgArr[index],{
    
    left:-WIDTH})
                //现在的索引是newIndex的图去中间
                animate(ImgArr[newIndex],{
    
    left:0})
            }
            //如果要看的索引newIndex<index,索引newIndex必须在左边
            else if(newIndex<index){
    
    
                //索引是newIndex的图片必须在左边
                ImgArr[newIndex].style.left = -WIDTH + "px"
                //原来索引是index的去右边
                animate(ImgArr[index],{
    
    left:WIDTH})
                //现在索引是newIndex的去中间
                animate(ImgArr[newIndex],{
    
    left:0})
            }
            //不管是newIndex<index还是newIndex>index,运动完以后都要更新索引index,并点亮小圆点
            index = newIndex;
            light();
        }
    }

    // 7 轮播图会自动轮播
    var timer = setInterval(nextImg,2000);
    document.onvisibilitychange = function(){
    
    
        if(document.visibilityState=="hidden"){
    
    
            clearInterval(timer)
        }
        if(document.visibilityState=="visible"){
    
    
            timer = setInterval(nextImg,2000);
        }
    }
    //8 鼠标移入slider盒子,停止轮播,鼠标移出slider盒子,继续轮播
    slider.onmouseenter = function(){
    
    
        clearInterval(timer);
    }
    slider.onmouseleave = function(){
    
    
        clearInterval(timer);
        timer = setInterval(nextImg,3000)
    }

    //点亮小圆点
    function light(){
    
    
        for(var i=0 ; i<ImgArr.length ;i++){
    
    
            //图片有几个,小圆点就有几个
            spanArr[i].className = "dot"
        }
        spanArr[index].className = "dot dot_color"
    }
    //显示下一张
    function nextImg(){
    
    
        //如果当前图片索引是index,那么现在要看的索引是newIndex
        var newIndex = +index + 1;//在这一个字符串前面写加号表示正号
        //如果newIndex>ImgArr.length-1
        if(newIndex>ImgArr.length-1){
    
    
            newIndex = 0;
        }
        //那么我要看的图一定在右边
        ImgArr[newIndex].style.left = WIDTH + "px";
        //原来索引index的图片去左边
        //现在索引newIndex的图片去中间
        animate(ImgArr[index],{
    
    left:-WIDTH})
        animate(ImgArr[newIndex],{
    
    left:0})
        //更新当前索引index
        index = newIndex;
        //点亮小圆点
        light();
    }
    //获取元素
    function $id(id){
    
    
    return document.querySelector(id)
}
function $ids(id){
    
    
    return document.querySelectorAll(id)
}
//获取指定dom的指定样式值 dom:元素 , attr:要获取的属性
function getStyle(dom,attr){
    
    
    if(window.getComputedStyle){
    
    
        return window.getComputedStyle(dom,null)[attr];
    }else{
    
    
        return dom.currentStyle[attr]
    }
}
/* 
    animate:让指定元素的多属性同时缓动到指定目标
        ==>参数1:dom 要缓动的元素节点
        ==>参数2:json 动画属性:属性值的目标值
            {
                width:400,
                height:500,
                left:100,
                top:300,
            }
        ==>参数3:fn 动画完成以后执行的函数
*/
function animate(dom,json,fn){
    
    
    clearInterval(dom.timer)
    //每隔一段时间,json里面的每个属性都变化一点
    dom.timer = setInterval(function(){
    
    
        //每次运动开始
        var flag = true; //如果后面有哪个属性值没有达到目标属性值,就把flag变成false
        //json里面有几个键值对,就要运动几次
        for(var attr in json){
    
    
            //1 获取当前位置
            if(attr == "opacity"){
    
    
                var current = parseInt(getStyle(dom,attr)*100)
            }else{
    
    
                var current = parseInt(getStyle(dom,attr))
            }

            //2 计算速度
            var target = parseInt(json[attr]);
            var speed = target>current?Math.ceil((target-current)/10):Math.floor((target-current)/10)

            //3 计算下一次位置
            if(attr == "zIndex"){
    
    
                var next = target;//如果缓动的属性是zIndex,直接一步到位,不用缓动
            }else{
    
    
                var next = current + speed;
            }

            //4 定位元素
            if(attr == "opacity"){
    
    
                dom.style.opacity = next/100;
                dom.style.filter = "alpha(opacity="+next+")"
            }else if(attr == "zIndex"){
    
    
                dom.style.zIndex = next;
            }else{
    
    
                dom.style[attr] = next + "px";
            }
            if(next != target){
    
    
                flag = false;
            }
        }
        //本次运动结束,检查flag的值
        if(flag){
    
    
            clearInterval(dom.timer);
            if(fn){
    
    
                fn()
            }
        }
    },1000/60)
}
</script>
</html>

Guess you like

Origin blog.csdn.net/Bob_Yan623/article/details/109254027