函数练习轮播图超长版

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        
        // 1、布局
        // 2、定义当前第几张图片和应该向什么方向运动
        // 3、将需要放置的图片根据方向放在前面或者后面
        // 4、将整个容器向左或者向右移动,
        // 5、完成后将上一次的图片删除

        // imgCon  放置所有图片的容器
        // dotList 放置小圆点列表
        // bnList  放置左右按钮的数组
        // imgList  放置所有图片的数组
        // pos是确定当前是第几个图片
        // direction 图片运行的方向
        // imgSrcList 存储轮播图图片地址的数组
        var imgCon,ul,preDot;
        var pos=0,
            x=0,
            bool=false,
            autoBool=false,
            dotList=[],
            imgList=[],
            bnList=[],
            time=300,
            imgSrcList=["./img/a.png","./img/b.png","./img/c.png","./img/d.png","./img/e.png"]
            direction="";
        const WIDTH=1500;
        const HEIGHT=500;
        const SPEED=40;
        const LEFT=Symbol();
        const RIGHT=Symbol();

        init();
        /* 
            init  初始化函数
           1、 创建轮播图的外层容器
           2、创建轮播图图片容器
           3、创建按钮列表
           4、创建小圆点列表
           5、将轮播图容器放在body中
           6、切换小圆点,因为当前是第0张,所以就会让第0个小圆点变红
           7、将小圆点容器水平居中
           8、设置时间间隔,每16毫秒执行animation函数一次,因为一秒是1000毫秒
           一秒中执行60次,就是60帧频,每次花费的时间是16.6666毫秒
           9、给外层的轮播图增加事件侦听,一个鼠标进入,一个是鼠标离开
         */
        function init(){
            var carousel=ce("div",{
                width:WIDTH+"px",
                height:HEIGHT+"px",
                position:"relative",
                margin:"auto",
                overflow:"hidden"
            });
            createImgCon(carousel);
            createButton(carousel);
            createDotList(carousel)
            document.body.appendChild(carousel);
            changeDot();
            ul.style.left=(WIDTH-ul.offsetWidth)/2+"px";
            setInterval(animation,16);
            carousel.addEventListener("mouseenter",mouseHandler);
            carousel.addEventListener("mouseleave",mouseHandler);
        }

        /* 
            轮播图进入和离开的事件函数
            1、如果进入轮播图,设置自动轮播的开关是false,就不会自动轮播
                并且重新将计时设为300
            2、如果离开轮播图,设置自动轮播开关是true,就会自动轮播了
        
        
         */
        function mouseHandler(e){
            if(e.type==="mouseenter"){
                autoBool=false;
                time=300;
            }else if(e.type==="mouseleave"){
                autoBool=true;
            }
        }

        /* 
            创建轮播图容器和图片
            参数 
               parent  父容器,  元素类型  将创建好的容器和图片放在这个父容器内
            1、创建图片容器,宽度是2张图片宽度
            2、根据所有轮播图地址数组创建所有图片,并且放在数组imgList中
            3、将第0张图片放在创建图片容器imgCon中
            4、将图片容器放在轮播图容器中
         */
        function createImgCon(parent){
            imgCon=ce("div",{
                position:"absolute",
                width:2*WIDTH+"px",
                height:HEIGHT+"px",
                left:0
            });
            for(var i=0;i<imgSrcList.length;i++){
                var img=ce("img",{
                    width:WIDTH+"px",
                    height:HEIGHT+"px"
                });
                img.src=imgSrcList[i];
                imgList.push(img);
            }
            imgCon.appendChild(imgList[0]);
            parent.appendChild(imgCon);
        }

        /*
             创建左右按钮
            参数 
               parent  父容器,  元素类型  将创建好的按钮放在这个父容器内
            1、创建按钮地址数组
            2、循环这个地址数组,创建所有图片,并且放置对应的位置
            3、设置图片的地址
            4、将按钮图片放在轮播图容器中
            5、给左右按钮增加点击事件执行函数bnClickHandler
          */
        function createButton(parent){
            var arr=["left","right"];
            for(var i=0;i<arr.length;i++){
                var img=ce("img",{
                    position:"absolute",
                    // (外容器高度-当前图片高度)/2 垂直居中
                    top:(HEIGHT-60)/2+"px",
                    // 如果是第0张图片,左边按钮,让他居左50像素,否则是none
                    left:i===0 ? "50px" : "none",
                      // 如果是第1张图片,右边按钮,让他居右50像素,否则是none
                    right:i===1 ? "50px" : "none"
                });
                img.src=`./img/${arr[i]}.png`;
                parent.appendChild(img);
                bnList.push(img);
                img.addEventListener("click",bnClickHandler);
            }
        }


        /* 
        
              创建小圆点
            参数 
               parent  父容器,  元素类型  将创建好的小圆点放在这个父容器内
             1、创建ul,设置样式
             2、根据图片地址的数组,循环若干次,有多少图片就循环多少次创建小圆点
             3、将每一个小圆点存在数组dotList中
             4、将小圆点放在ul中
             5、给ul增加点击事件,事件是点击小圆点,事件委托
         */
        function createDotList(parent){
             ul=ce("ul",{
                listStyle:"none",
                margin:0,
                padding:0,
                position:"absolute",
                bottom:"50px"
            });
            for(var i=0;i<imgSrcList.length;i++){
                var dot=ce("li",{
                    width:"28px",
                    height:"28px",
                    borderRadius:"50%",
                    border:"2px solid #FF0000",
                    float:"left",
                    marginLeft:i===0 ? "0px" : "15px"
                });
                dotList.push(dot);
                ul.appendChild(dot);
            }
            // dotList=Array.from(ul.children);
            parent.appendChild(ul);
            ul.addEventListener("click",dotClickHandler);
        }

        /* 
            点击左右按钮事件函数
            e   点击事件  MouseEvent
            e.target 是被点击的按钮图片
            如果bool是true,也就是当前轮播图正在播放时,点击按钮跳出,不继续执行
            1、判断被点击图片的地址里面是否包含有left.png字符串,
              如果有,就是点击左侧按钮,反之是右按钮
            2、如果点击了左侧按钮,当前图片下标-1,如果小于0,
                就让他为当前图片地址数量-1,也就是最大应该有图片下标
               并且设置方向是向右运动
            3、如果点击了右侧按钮,当前图片下标+1,如果大于前图片地址数量-1,
                就让他为0,回到最开始第0张图片
               并且设置方向是向左运动
         */
        function bnClickHandler(e){
            if(bool) return;
            if(e.target.src.includes("left.png")){
                pos--;
                if(pos<0) pos=imgSrcList.length-1;
                direction=RIGHT;
            }else{
                pos++;
                if(pos>imgSrcList.length-1) pos=0;
                direction=LEFT;
            }
            createNextImg();
        }

        /* 
            小圆点点击事件函数
            e   鼠标事件对象  MouseEvent
             e.target 是鼠标点击的目标
             因为使用时事件委托,因此判断点击目标是不是li,如果不是就跳出
               如果bool是true,也就是当前轮播图正在播放时,点击按钮跳出,不继续执行
             1、判断点击目标是否是li,不是跳出
             2、获取当前点击的小圆点是数组中第几个
             3、如果当前的点击小圆点的下标和当前展示图片的下标相同时,跳出不处理
             4、如果大于当前展示图片的下标,方向设为向左运动,反之向右
             5、将当前点击的下标设为当前应展现图片的下标
        
         */
        function dotClickHandler(e){
            if(bool) return;
            // if(e.target.nodeName!=="LI") return;
            if(e.target.constructor!==HTMLLIElement) return;
            var index=dotList.indexOf(e.target);
            if(index===pos) return;
            direction=index>pos ? LEFT : RIGHT;
            pos=index;
            createNextImg();
        }


        /* 
            创建下一张需要显示图片
            当点击左右按钮和当点击小圆点时,触发该函数
            1、如果方向向左运动,给图片容器尾部添加新的图片
            2、如果方向向右运动,给图片容器的最头部添加新图片,
            但是这时候原图被挤到后面,我们将这个容器向左挪动一个宽度位置
            3、设置完成后,设置bool是true,这时候就打开了动画的播放开关
            动画就可以完成播放了
            4、切换当前小圆点
        
         */
        function createNextImg(){
            // console.log(direction,pos,imgList[pos]);
            if(direction===LEFT){
                imgCon.appendChild(imgList[pos]);
                x=0;
            }else if(direction===RIGHT){
                imgCon.insertBefore(imgList[pos],imgCon.firstElementChild);
                imgCon.style.left=-WIDTH+"px";
                x=-WIDTH;
            }
            bool=true;
            changeDot();
        }

        /* 
            切换小圆点
            preDot是对上一次小圆点的引用变量
            刚开始第一次时,没有这个引用,因此不执行,并且设置第一次设置了第0个小圆点
            更改了第0个小圆点的背景色
            第二次进来时,上次小圆点的引用时第0个小圆点,所以就将上次小圆点修改背景透明
            将本次小圆点设置给这个引用,并且修改背景色
            这样再次进入时就可以修改原来的,设置新的
         */
        function changeDot(){
            if(preDot){
                preDot.style.backgroundColor="rgba(255,0,0,0)";
            }
            preDot=dotList[pos];
            preDot.style.backgroundColor="rgba(255,0,0,0.5)";
        }

        /* 
            创建元素
            参数:
               type   创建元素的类型  字符串
               style  创建元素的样式  对象  使用对象方式给出所有该元素的样式
              1、根据类型创建元素
              2、将给入的样式设置给元素的行内样式
              3、返回创建好的元素 
        
         */
        function ce(type,style){
            var elem=document.createElement(type);
            // ES6的方法   将后面的对象中的属性复制到前面对象中
            Object.assign(elem.style,style);
            return elem;
        }

        /* 
            每16毫秒执行该函数一次
            1、执行imgConMove这个函数,这是让图片移动方法
            2、执行自动轮播
        
         */
        function animation(){
            imgConMove();
            autoPlay();
        }

        /* 
            每16毫秒让图片移动一次
            开始的时候就一直运行,因为有一个bool值判断,如果是false时,一直就不能进入
            如果可以进入
            1、如果方向向左
               不断让变量x递减,每16毫秒减40像素,设置图片容器位置,图片容器就可以移动了
               当图片容器的第一张图完全移动到最左侧以后,也就是x小于等于负的图片宽度
               设置bool是false,16毫秒后进入时直接跳出,并且删除掉移到最左侧的图片,
               这时候后面的图片就会补充到最前面,因此我们设置将这x为0,让整个容器向后
               挪回初始位置
            2、如果方向向右
            x不断增加40像素
            如果x大于0,表示左侧的图片已经移到中间位置,原图片移到了右侧
            这时候停止运动,bool设为false,x设为初始的0,删除右侧的图片

         */
        function imgConMove(){
            if(!bool) return;
            if(direction===LEFT){
                x-=SPEED;
                if(x<=-WIDTH){
                    imgCon.firstElementChild.remove();
                    x=0;
                    bool=false;
                }
                imgCon.style.left=x+"px";
              
            }else if(direction===RIGHT){
                x+=SPEED;
                if(x>=0){
                    bool=false;
                    x=0;
                    imgCon.lastElementChild.remove();
                }
                imgCon.style.left=x+"px";
            }
        }

        /* 
            自动轮播
            1、如果自动轮播开关是false时,跳出
            2、time不断减少
            3、如果time大于0就不继续执行,跳出
            4、time值等于0,设置time初始为300
            5、创建一个点击事件对象
            6、向右侧按钮抛发这个点击事件
        
         */
        function autoPlay(){
            if(!autoBool) return;
            time--;
            if(time>0)return;
            time=300;
            var evt=new MouseEvent("click");
            bnList[1].dispatchEvent(evt);
        }
    </script>
</body>
</html>

 

posted @ 2020-04-21 22:39  cruor  阅读(161)  评论(0编辑  收藏  举报