ES6轮播图插件自制

插件描述

  • 一行代码在你想要的位置生成一个轮播图

插件使用说明

  • import插件
  • 在html页面中书写一个容器(即调用插件时的形参1parent),给这个容器书写css样式,包括宽度和位置等
  • 使用语句Carousel.createCarousel(parent,arr)生成轮播图.其中形参1是用来承载轮播图的容器,可以输入选择符字符串也可以输入节点;形参2是轮播图图片的src数组。
<script type="module">
    import Carousel from "url"
    Carousel.createCarousel(parent,arr)
</script>

插件编写思路

1.采用静态函数编写接口static createCarousel(parent,arr)

2.分析轮播图组成元素,需要一个轮播图容器(carousel_wrapper),一个可以装下两张图片的图片容器(img_wrapper),两个btn,跟图片个数相等的选项卡圆点;

3.将功能拆解:

  • 图片预加载
  • 创建轮播图元素
  • 左右按钮的点击事件
  • 添加需要参与下次轮播的图片进入img_wrapper
  • 选项卡圆点的mouseover事件
  • 更改选项卡圆点的样式
  • 自动轮播

插件编写心得

  • 函数式编程不仅仅是把代码写在一个个函数中被包裹,得注意每个函数尽可能单独完成一个唯一的功能,这样,元素的事件中就可以灵活的调用函数。
  • 标志变量的使用非常重要。可以使用其作为开关,在程序中设置手动切换轮播图的开关,设置自动轮播的暂停与继续;也可以使用其作为逻辑分叉的判断条件

插件实现细节(部分)

if(typeof parent === "string") Carousel.parent=document.querySelector(parent);

  • 参1可输入元素节点或元素节点的选择符字符串

Carousel.loadImg(Carousel.arr,Carousel.imgLoadedHandler)

  • 将形参2传入的图片src数组进行图片的预加载

Carousel.WIDTH = parseFloat(Carousel.list[0].width)

  • 将第一张图片的宽高设置为carousel_wrapper的宽高

Carousel.createNextImg()

  • 动态向img_wrapper中添加图片实现无缝轮播

height:${Carousel.HEIGHT}px

  • 将形参1元素的高度动态设置为图片高度,解决高度塌陷问题

插件将carousel_wrapper设置了居中,即传入的形参1元素的水平中间,使得小像素显示屏也能显示大像素图片

注意事项

  • \color{orange}{选项卡圆点和左右按钮,插件都自带,插件会给形参1元素动态设置高度为形参2src数组第一个src代表的图片的高度}
  • 形参1parent代表的元素不需要任何的innerHTML,如果写了也会被插件清空
  • 为了增强插件的稳定性,插件给形参1(parent)设置部分属性,如下
    Object.assign(Carousel.parent.style,{
              position:"relative",
              height:`${Carousel.HEIGHT}px`,
              zIndex:99999,
              overflowX:"hidden"
          });
    
  • 左右按钮和选项卡圆点是固定尺寸的,适合较大的轮播图,如果图片较小可以手动修改其尺寸

插件源代码

export default class Carousel{
    static prev;
    static pos = 0;
    static dots=[];
    static time = 300;
    static auto_play = true;
    static isMoving = false;
    static direction;
    static speed = 20;
    static parent;
    static list=[];
    static carousel_wrapper;
    static WIDTH ;
    static HEIGHT;
    static go_left_btn;
    static go_right_btn;
    static img_wrapper;
    static btn_list;
    static screen_width;
    static screen_height;
    static arr;
    
    //接口,导出插件生成的轮播图,用参数parent接受
    static createCarousel(parent,arr){
        Carousel.arr = arr;
        Carousel.screen_width = window.innerWidth;
        Carousel.screen_height = window.innerHeight;
        Carousel.parent = parent;
        if(typeof parent === "string") Carousel.parent=document.querySelector(parent);
        Carousel.parent.innerHTML=""
        Carousel.loadImg(Carousel.arr,Carousel.imgLoadedHandler);
    }
    //图片预加载
    static imgLoadedHandler(list){
        for(let i = 0;i < list.length;i++){
            Carousel.list.push(list[i]);
        }
        Carousel.WIDTH = parseFloat(Carousel.list[0].width);
        Carousel.HEIGHT = parseFloat(Carousel.list[0].height);
        Object.assign(Carousel.parent.style,{
            position:"relative",
            height:`${Carousel.HEIGHT}px`,
            zIndex:99999,
            overflowX:"hidden"
        });
        Carousel.carousel_wrapper = Carousel.createCarouselWrapper();
        Carousel.createImgWrapper(Carousel.carousel_wrapper);
        Carousel.carousel_wrapper.addEventListener("mouseover",Carousel.mouseHandler);
        Carousel.carousel_wrapper.addEventListener("mouseout",Carousel.mouseHandler);
        Carousel.createBtn(Carousel.carousel_wrapper);
        Carousel.createDots(Carousel.carousel_wrapper);
        Carousel.go_left_btn.addEventListener("click",Carousel.clickHandler);
        Carousel.go_right_btn.addEventListener("click",Carousel.clickHandler);
        Carousel.autoPlay();
        Carousel.img_wrapper.appendChild(Carousel.list[0]);
        Carousel.parent.appendChild(Carousel.carousel_wrapper);
    }
    //创建轮播图外围容器
    static createCarouselWrapper(){
        let carousel_wrapper = Carousel.ce("div",{
            width: `${Carousel.WIDTH}px`,
            height:`${Carousel.HEIGHT}px`,
            position:"absolute",
            left:"50%",
            marginLeft:`${-Carousel.WIDTH*0.5}px`,
            overflowX:"hidden"
        });
        return carousel_wrapper;
    }
    //创建一个可以容纳两张图片的盒子
    static createImgWrapper(parent,arr){
        Carousel.arr = arr;
        Carousel.img_wrapper = Carousel.ce("div",{
            width: `${Carousel.WIDTH*2}px`,
            height:`${Carousel.HEIGHT}px`,
            position:"absolute",
            left:0
        },parent)
    }
    //创建两个按钮
    static createBtn(parent){
        Carousel.go_left_btn = new Image();
        Carousel.go_left_btn.src="https://p2.lefile.cn/product/adminweb/2018/11/11/2a7f8349-14f0-42e1-afe8-7ae8afd54e1e.png";
        Carousel.go_right_btn = new Image();
        Carousel.go_right_btn.src="https://p2.lefile.cn/product/adminweb/2018/11/11/cae7b801-0fe6-4691-ba99-239ba9d11576.png";
        Object.assign(Carousel.go_left_btn.style,{
            position:"absolute",
            left:`${Carousel.WIDTH*0.5-Carousel.screen_width*0.5}px`,
            marginLeft:`100px`,
            top:`${Carousel.HEIGHT*0.5}px`,
            marginTop:`${-Carousel.go_right_btn.height*0.5}px`
        })
        Object.assign(Carousel.go_right_btn.style,{
            position:"absolute",
            left:`${Carousel.WIDTH*0.5-Carousel.screen_width*0.5+Carousel.screen_width}px`,
            marginLeft:`-100px`,
            top:`${Carousel.HEIGHT*0.5}px`,
            marginTop:`${-Carousel.go_right_btn.height*0.5}px`
        })
        parent.appendChild(Carousel.go_left_btn)
        parent.appendChild(Carousel.go_right_btn)
    }
    //创建圆点选项卡
    static createDots(parent){
        Carousel.dots = Carousel.ce("div",{
            zIndex:66,
            background:"red",
            height:"30px",
            width:"100%",
            position:"absolute",
            textAlign:"center",
            bottom:"40px"
        },parent);
        Carousel.list.forEach((item,index)=>{
                let span = Carousel.ce("span",{
                    display:"inline-block",
                    width:"30px",
                    height:"30px",
                    borderRadius:"50%",
                    background:"white",
                    marginRight:"5px"
                },Carousel.dots)
                span.addEventListener("mouseover",Carousel.dotMouseoverHandler);
                span.span_index =index;
        })
        Carousel.prev = Carousel.dots.firstElementChild;
        Carousel.prev.style.background = "blue";
    }
    //两个按钮的点击事件
    static clickHandler(e){
        if(Carousel.isMoving)return;
        if(e.target === Carousel.go_right_btn)
            {
                Carousel.direction = "left";
                Carousel.pos++;
                if(Carousel.pos===Carousel.list.length)Carousel.pos=0;
            }
        else if(e.target === Carousel.go_left_btn){
            Carousel.direction = "right";
            Carousel.pos--;
            if(Carousel.pos===-1)Carousel.pos=Carousel.list.length-1;
        }
        Carousel.createNextImg();
        Carousel.animation();
        Carousel.changeDot();
    }
    //从存储图片元素的数组之中调出轮播需要的一张图片,并将img_wrapper位置初始化
    static createNextImg(){
        if(Carousel.direction === "left"){
            Carousel.img_wrapper.appendChild(Carousel.list[Carousel.pos]);
        }else if(Carousel.direction === "right"){
            Carousel.img_wrapper.insertBefore(Carousel.list[Carousel.pos],Carousel.img_wrapper.firstChild);
            Carousel.img_wrapper.style.left=`${-Carousel.WIDTH}px`;
        }
    }
    //图片移动动画
    static animation(){
        Carousel.isMoving = true;
        if(Carousel.direction === "right"){
            Carousel.img_wrapper.style.left = parseFloat(Carousel.img_wrapper.style.left)+Carousel.speed + "px";
            if(parseFloat(Carousel.img_wrapper.style.left)<=0) 
            {
            window.requestAnimationFrame(Carousel.animation);
            }
            else{
                window.cancelAnimationFrame(Carousel.animation)
                Carousel.img_wrapper.lastChild.remove();
                Carousel.img_wrapper.style.left = 0;
                Carousel.dot_index--;
                Carousel.isMoving = false;
                return;
            }
        }
        else if(Carousel.direction === "left"){
            Carousel.img_wrapper.style.left = parseFloat(Carousel.img_wrapper.style.left)-Carousel.speed + "px";
            if(parseFloat(Carousel.img_wrapper.style.left)>=-(Carousel.WIDTH)) 
            {
            window.requestAnimationFrame(Carousel.animation);
            }
            else{
                window.cancelAnimationFrame(Carousel.animation)
                Carousel.img_wrapper.firstChild.remove();
                Carousel.dot_index++;
                Carousel.img_wrapper.style.left = 0;
                Carousel.isMoving = false;
                return;
            }
        }
    }
    //自动轮播
    static autoPlay(){
        if(Carousel.auto_play){
            Carousel.time--;
        if(Carousel.time<=0){
                Carousel.time=300;
                let evt = new Event("click");
                Carousel.go_right_btn.dispatchEvent(evt);
            }
        }
        window.requestAnimationFrame(Carousel.autoPlay)
    };
    //实现鼠标移入轮播图区域停止自动轮播,移出继续自动轮播
    static mouseHandler(e){
        if(e.type==="mouseover"){
            Carousel.time=300;
            Carousel.auto_play = false;
        }
        else if(e.type==="mouseout"){
            Carousel.auto_play = true;
        }
    }
    //选项卡中圆点的mouseover
    static dotMouseoverHandler(e){
        if(Carousel.isMoving)return;
        if(e.target.constructor !== HTMLSpanElement)return;
        if(Carousel.pos<e.target.span_index){ 
            Carousel.direction = "left";
        }
        else if(Carousel.pos>e.target.span_index)
        {
            Carousel.direction = "right";
        }
        else return;
        Carousel.pos = e.target.span_index;
        Carousel.changeDot();
        Carousel.createNextImg();
        Carousel.animation(); 
    }
    //实现选项卡变化
    static changeDot(){
        if(Carousel.prev)Carousel.prev.style.background = "white";
        Carousel.prev = Carousel.dots.children[Carousel.pos];
        Carousel.prev.style.background = "blue";
    }
    //创建元素
    static ce(type,style,parent){
        let elem=document.createElement(type);
        if(style){
            Object.assign(elem.style,style);
        }
        if(parent){
            if(typeof parent==="string")parent=document.querySelector(parent);
            parent.appendChild(elem);
        }
        return elem;
    }
    //图片预加载
    static loadImg(arr,callBack){
        let img=new Image();
        img.src=arr.shift();
        img.arr=arr;
        img.list=[];
        img.callBack=callBack;
        img.addEventListener("load",this.loadHandler);
    }
    static loadHandler(e){
        let img=e.currentTarget;
        img.list.push(img.cloneNode(false));
        if(img.arr.length===0){
            img.callBack(img.list);
            return;
        }
        img.src=img.arr.shift();
    }
}

   
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342