加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ES6实现图片切换特效(图片墙效果)

发布时间:2020-12-16 04:21:31 所属栏目:百科 来源:网络整理
导读:按照国际惯例先放效果图 贴代码: index.html ! DOCTYPE html html lang ="en" head meta charset ="UTF-8" title index / link rel ="stylesheet" href ="index.css" body div id ="wrap" !-- div class="img_container" ul class="img_classify" li class=

按照国际惯例先放效果图

贴代码:

index.html

<!DOCTYPE html>
<html lang="en"head>
    meta charset="UTF-8"title>index</link rel="stylesheet" href="index.css"bodydiv id="wrap">
        <!-- <div class="img_container">
            <ul class="img_classify">
                <li class="img_classify_type_btn img_classify_type_btn_active">类别1</li>
                <li class="img_classify_type_btn">类别2</li>
            </ul>
            <div class="img_pic_container">
                <figure>
                    <img src="images/1.jpg" alt="1">
                    <figcaption>title</figcaption>
                </figure>
            </div>
        </div> -->
    div 遮罩层,预览时出现大图  <div class="img_overlay">
        <div class="img_overlay_prevbtn"></div>
        <div class="img_overlay_nextbtn"></div>
        <img src="images/1.jpg" alt="1">
    </div> -->

    script src="index.js"></script="data.js">
        const img=new $Img({
            data,initType:"JavaScript,//默认显示的分类
            outWrap:#wrap所有DOM挂载点
        });
    html>

index.css

*{
    margin:0;
    padding:0;
}
body{ 
    background: #fafafa;
    background: url('images/bg.png')
}
li{
    list-style:none;
}
a{
    text-decoration: none;
}
::-webkit-scrollbar {
    display:
#wrap{  
    width: 1065px; 0 auto; 30px; rgb(255,255);
    border-radius: 2px;
    margin-top: 100px;
}
.img_container{
    font-size: 10px;
}
.img_classify_type_btn{ inline-block; .2em 1em; 1.6em;
    margin-right: 10px;
    cursor: pointer;
    border: 1px solid #e95a44;
    outline: none;
    color: #e95a44;
    transition: all .4s;
    user-select: none;/*文字不允许用户选中*/ 2px;
}
.img_classify_type_btn_active{ #fff;
}
.img_pic_container{
    position: relative;
    width: 1005px; flex;
    flex-wrap: wrap; all .6s cubic-bezier(0.77,0.175,1);动画效果*/
}
.img_pic_container figure{ 240px;
    height: 140px; absolute;
    transform: scale(0,0);
    opacity: 0;
    overflow: hidden; none;
}
 伪元素遮罩层 */
.img_pic_container figure::before { block; 100%;
    top:
    left:
    z-index: 4; rgba(58,12,5,0.5);
    content: ' '; all .3s; pointer;
}
 图片 
.img_pic_container figure img { all .3s;
}
 图片标题 
.img_pic_container figure figcaption { 50%; 7; 1.5em; translate(-50%,-50%);
    text-align: center; 悬停图片的时候标题显示 
.img_pic_container figure:hover figcaption{ 1;
}
.img_pic_container figure:hover img{ scale(1.1,1.1);
}
 悬停图片的时候遮罩显示 
.img_pic_container figure:hover::before{
.img_overlay{ fixed;
    right:
    bottom:
    background-color: rgba(0,.8);
    justify-content:
    align-items: 99;
}
.img_overlay_prevbtn,.img_overlay_nextbtn{ 50px; 2px solid white;
    line-height: white; 2rem; pointer;
}
.img_overlay_prevbtn{ 20px;
}
.img_overlay_nextbtn{
.img_overlay_prevbtn:active,.img_overlay_nextbtn:active{ rgb(241,241,.4);
}
.img_overlay_nextbtn::after{ "N";
}
.img_overlay_prevbtn::after{ "P";
}
.img_overlay img {
  transform: scale(2,2);
}

index.js

(function(window,document){

    let canChange=true;
    let curImgIndex=0;//默认显示的图片索引

    公共方法(便于之后对DOM的操作)
    const methods={
        同时添加多个子元素,对象简洁表示法
        appendChilds(parent,...child){
            child.forEach(item=>{
                parent.appendChild(item);
            })
        },选择单个元素
        $(selector,root=document){
            return root.querySelector(selector);
        },1)">选择多个元素
        $$(selector,1)"> root.querySelectorAll(selector);
        }
    };

     构造函数
    let Img=(options){
        this._init(options);初始化,对图片进行分类
        this._createElement();生成DOM
        this._bind();绑定事件
        this._show();显示到页面上
    }

    初始化
    Img.prototype._init=({data,initType,outWrap}){
        this.types=["全部"];全部分类
        this.all=[];所有图片
        this.classified={"全部":[]};分类映射
        this.curType=initType;当前显示的图片分类
        this.outWrap=methods.$(outWrap);所有DOM挂载点
        this.imgContainer=null;图片部分容器(不包括分类按钮)
        this.wrap=图片区域总容器(包括分类按钮)
        this.typeBtnEls=分类按钮数组
        this.figures=图片数组

        this._classify(data);对图片进行分类
        console.log(this.classified);//打印分类映射表

    }

    对图片进行分类
    Img.prototype._classify=(data){
        let srcs=[];存储已经生成过的图片,避免重复生成

        data.forEach(({type,title,alt,src},index)=>{
             arr.includes(a) 判断数组中是否存在某个值
             如果分类的数组中,没有当前分类,则添加当前分类
            if(!this.types.includes(type)){            
                .types.push(type);
            }

            Object.keys(obj) 返回obj中所有属性名组成的数组
            如果属性名中不存在该分类,则添加该分类
            if(!Object.keys(.classified).includes(type)){
                this.classified[type]=[];
            }

            如果该图片没有生成过
            srcs.includes(src)){
                srcs.push(src);

                生成图片
                let figure=document.createElement("figure");
                let img=document.createElement("img");
                let figcaption=document.createElement("figcaption");

                img.src=src;
                img.setAttribute("alt"title;

                methods.appendChilds(figure,img,figcaption);

                添加到图片数组中
                .all.push(figure);

                添加到分类映射中
                this.classified[type].push(this.all.length-1);

            }else{
                如果该图片已经生成过,就去srcs数组中找到对应图片
                srcs.findIndex(s1=>s1===src) 遍历src数组,找到元素的值为src的,返回其下标
                this.classified[type].push(srcs.findIndex(s1=>s1===src));

            }
        })
    }

    获取对应分类下的图片
    Img.prototype._getImgsByType=(type){
        如果分类是全部,就返回all数组
        否则就去图片映射表里,找到该分类对应的图片的索引;
        通过map遍历this.all数组,找到这些索引对应的图片
        return type==="全部"?[...this.all]:this.classified[type].map(index=>.all[index]);
    }

    生成DOM
    Img.prototype._createElement=(){
        let typesBtn=[];
        根据分类数组,生成所有分类对应的按钮元素
        for(let type of .types.values()){    
            typesBtn.push(`
                <li class="img_classify_type_btn${ type===this.curType?' img_classify_type_btn_active':''}">${ type }</li>
            `);
        }

        console.log(typesBtn);

        整体模板
        let templates=`
            <ul class="img_classify">${ typesBtn.join("") }</ul>
            <div class="img_pic_container"></div>
        `;

        let wrap=document.createElement("div");
        wrap.className="img_container";
        wrap.innerHTML=templates;

        this.imgContainer=methods.$(".img_pic_container"将分类下对应的图片数组使用扩展运算符展开,添加到图片容器中
        methods.appendChilds(this.imgContainer,...this._getImgsByType(.curType));

        取出可能会用到的元素,挂载到this上
        wrap;
        this.typeBtnEls=[...methods.$$(".img_classify_type_btn"this.figures=[...methods.$$("figure",wrap)];使用扩展运算符将取得的DOM元素转数组

        遮罩层
        let overlay=document.createElement("div");
        overlay.className="img_overlay";
        overlay.innerHTML=`
            <div class="img_overlay_prevbtn"></div>
            <div class="img_overlay_nextbtn"></div>
            <img src="" alt="">
        `;
        methods.appendChilds(.outWrap,overlay);
        this.overlay=overlay;
        this.previewImg=methods.$("img",overlay);当前要预览的图片

        this._calcPosition(this.figures);修改每张图片的定位
映射关系
    Img.prototype._diff=(curImgs,nextImgs){
        let diffArr=[];保存映射关系
         如:当前[1,2,3,6],下一批[3,9,11,14]
         则映射为[[2,0],..] 
         两组图片中国相同的图片为3,3在数组1的下标为2,3在数组2的下标为0,保存这种映射关系
        
        curImgs.forEach((src1,index1)=>遍历当前src数组,对每一个src,去下一批的src数组中找是否有相同的,有则返回该src在下一批数组中的下标
            let index2=nextImgs.findIndex(src2=>src1===src2);

            //
            if(index2!=-1){
                diffArr.push([index1,index2]);
            }
        })

         diffArr;

    }

    绑定事件
    Img.prototype._bind=(){
        解构赋值,获取到e.target
        methods.$(".img_classify",this.wrap).addEventListener("click",({target})=>if(target.nodeName!=="LI") return;如果点的不是li,则返回
            console.log(target.innerText);
            
            if(!canChange) ;
            canChange=false;

            const type=target.innerText;
            const imgs=this._getImgsByType(type);下一轮要显示的所有图片

            目前出现的图片的所有src
            let curImgs=this.figures.map(figure=>methods.$("img"点击后下一批要出现的图片的src
            let nextImgs=imgs.map(figure=>methods.$("img"this._diff(curImgs,nextImgs);得到两组图片共有的图片映射关系
            遍历该映射
            diffArr.forEach(([,index2])=>{index2是两组中相同的图片在下一组中的索引
                every() 方法使用指定函数检测数组中的所有元素:
                如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
                如果所有元素都满足条件,则返回 true。
                this.figures.every((figure,index)=>{
                    let src=methods.$("img"if(src===nextImgs[index2]){
                        splice() 方法向/从数组中添加/删除项目
                        this.figures.splice(index,1);找到相同的图片,从上一轮的图片数组中剔除
                        return ;
                    }
                    ;
                })
            })

            ._calcPosition(imgs);

            let needAppendImgs=[];切换下一轮时需要添加的元素(相同的元素不需要重复添加)
            if(diffArr.length){
                如果两轮存在相同图片,则相同的图片 不需要重复加载
                let nextIndex=diffArr.map(([,index2])=>index2);相同的图片的下标
                imgs.forEach((figure,1)">{
                    needAppendImgs.includes(index)){
                        needAppendImgs.push(figure);如果该图片不存在,则添加
                    }
                })
            }如果不存在相同图片,则所有图片需要加载
                needAppendImgs=imgs;
            }

            隐藏当前所有图片
            this.figures.forEach(figure=>{
                figure.style.transform="scale(0,0) translate(0 100%)";
                figure.style.opacity="0";
            })

            添加需要新增的图片
            methods.appendChilds(.imgContainer,...needAppendImgs);

            显示新一轮的图片            
            setTimeout(()=>{
                imgs.forEach(el=>{                    
                    el.style.transform="scale(1,1) translate(0,0)";
                    el.style.opacity="1";    
                    console.log(el);                
                })
            });

            销毁上一轮出现的所有图片
            setTimeout(()=>.imgContainer.removeChild(figure);            
                })

                imgs;

                canChange=;
            },600);在css中动画设置的结束时长就是0.6秒

            切换按钮样式
            this.typeBtnEls.forEach(btn=>(btn.className="img_classify_type_btn"));
            target.className="img_classify_type_btn img_classify_type_btn_active";
        })

        给每张图片绑定点击事件
        this.imgContainer.addEventListener("click",1)">if(target.nodeName!=="FIGURE" && target.nodeName!=="FIGCAPTION") ;
            if(target.nodeName==="FIGCAPTION"){
                target=target.parentNode;
            }

            显示预览的图片和遮罩层
            const src=methods.$("img"this.figures.findIndex(figure=>src===methods.$("img"this.previewImg.src=src;
            this.overlay.style.display="flex";
            
            setTimeout(()=>this.overlay.style.opacity="1";
            })
        })

        点击遮罩层,淡出
        this.overlay.addEventListener("click",()=>this.overlay.style.opacity="0";
            setTimeout(()=>this.overlay.style.display="none"300毫秒是css中transition设置的时间
        })

        上一张下一张按钮绑定
        methods.$(".img_overlay_prevbtn",1)">this.overlay).addEventListener("click",e=>阻止事件冒泡,导致触发点击遮罩隐藏遮罩的情况
            e.stopPropagation();
            curImgIndex=curImgIndex===0?this.figures.length-1:curImgIndex-1this.previewImg.src=methods.$("img",1)">.figures[curImgIndex]).src;
        })
        methods.$(".img_overlay_nextbtn",1)">{
            e.stopPropagation();
            curImgIndex=curImgIndex===this.figures.length-1?0:curImgIndex+1.figures[curImgIndex]).src;
        })
    }

    显示到页面上
    Img.prototype._show=(){
        methods.appendChilds(this.outWrap,1)">this.wrap);把图片总容器挂载到指定的外容器上

        演示器实现进场动画
        setTimeout(()=>让所有图片显示
            {
                figure.style.transform="scale(1,1)">;
                figure.style.opacity="1";
            })
        },0)

    }

    计算每张图片的top和left
    Img.prototype._calcPosition=(figures){
        figures.forEach((figure,1)">140是每张图片的高度,15是每张图片垂直方向的间隙
            240是每张图片的宽度,15是每张图片水平方向的间隙
            figure.style.top=parseInt(index/4)*140+parseInt(index/4)*15+"px";
            figure.style.left=parseInt(index%4)*(240+15)+"px";
            figure.style.transform="scale(0,0) translate(0,-100%)";让特效更丰富
设置图片容器高度
        var num=figures.length;图片数量
        if(num<=4){
            this.imgContainer.style.height="140px";
        }this.imgContainer.style.height=Math.ceil(num/4)*140+(Math.ceil(num/4)-1)*15+"px";
        }
        
    }

    window.$Img=Img;暴露到全局

})(window,document);

data.js(数据)

const data = [

  {
    type: 'JavaScript''ES6快速入门'
  },{
    type: 'JavaScript''Javascript实现二叉树算法''Canvas绘制时钟''./images/3.jpg''基于websocket的火拼俄罗斯''前端框架''React知识点综合运用实例''React组件''./images/5.jpg''Vue+Webpack打造todo应用''Vue.js入门基础''./images/7.jpg''使用Vue2.0实现购物车和地址选配功能''React'
  }

]

?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读