javascript实现弹出层效果
弹出层和弹窗相似但是并不相同;弹窗和弹出层都是由用户触发的显示提示信息的弹出面板;但是弹窗只是显示一些信息,没有太多的复杂的交互事件;而弹层类似一个整个页面,可以实现页面的所有功能;
现在前端弹层使用的很频繁,如支付宝支付弹层等…所以掌握弹层是一个很重要的技能。如果只是简单的隐藏和切换,当然就不必说,我要说的html+animate+es6实现弹层;
html弹层结构:
ThisisHeader 上弹层 右弹层 下弹层 左弹层
css代码:
@mixinslide-top{ 0%{ -webkit-transform:translate3d(0,-400%,0); -moz-transform:translate3d(0,-400%,0); -ms-transform:translate3d(0,-400%,0); -o-transform:translate3d(0,-400%,0); transform:translate3d(0,-400%,0); } 100%{ -webkit-transform:translate3d(0,0,0); -moz-transform:translate3d(0,0,0); -ms-transform:translate3d(0,0,0); -o-transform:translate3d(0,0,0); transform:translate3d(0,0,0); } } @keyframesslideTop{ @includeslide-top; } @-webkit-keyframesslideTop{ @includeslide-top; } @mixinslide-top-hide{ 0%{ -webkit-transform:translate3d(0,0,0); -moz-transform:translate3d(0,0,0); -ms-transform:translate3d(0,0,0); -o-transform:translate3d(0,0,0); transform:translate3d(0,0,0); } 100%{ -webkit-transform:translate3d(0,-400%,0); -moz-transform:translate3d(0,-400%,0); -ms-transform:translate3d(0,-400%,0); -o-transform:translate3d(0,-400%,0); transform:translate3d(0,-400%,0); } } @keyframesslideTopHide{ @includeslide-top-hide; } @-webkit-keyframesslideTopHide{ @includeslide-top-hide; } @mixinslide-right{ 0%{ -webkit-transform:translate3d(400%,0,0); -moz-transform:translate3d(400%,0,0); -ms-transform:translate3d(400%,0,0); -o-transform:translate3d(400%,0,0); transform:translate3d(400%,0,0); } 100%{ -webkit-transform:translate3d(0,0,0); -moz-transform:translate3d(0,0,0); -ms-transform:translate3d(0,0,0); -o-transform:translate3d(0,0,0); transform:translate3d(0,0,0); } } @keyframesslideRight{ @includeslide-right; } @-webkit-keyframesslideRight{ @includeslide-right; } @mixinslide-right-hide{ 0%{ -webkit-transform:translate3d(0,0,0); -moz-transform:translate3d(0,0,0); -ms-transform:translate3d(0,0,0); -o-transform:translate3d(0,0,0); transform:translate3d(0,0,0); } 100%{ -webkit-transform:translate3d(400%,0,0); -moz-transform:translate3d(400%,0,0); -ms-transform:translate3d(400%,0,0); -o-transform:translate3d(400%,0,0); transform:translate3d(400%,0,0); } } @keyframesslideRightHide{ @includeslide-right-hide; } @-webkit-keyframesslideRightHide{ @includeslide-right-hide; } @mixinslide-bottom{ 0%{ -webkit-transform:translate3d(0,400%,0); -moz-transform:translate3d(0,400%,0); -ms-transform:translate3d(0,400%,0); -o-transform:translate3d(0,400%,0); transform:translate3d(0,400%,0); } 100%{ -webkit-transform:translate3d(0,0,0); -moz-transform:translate3d(0,0,0); -ms-transform:translate3d(0,0,0); -o-transform:translate3d(0,0,0); transform:translate3d(0,0,0); } } @keyframesslideBottom{ @includeslide-bottom; } @-webkit-keyframesslideBottom{ @includeslide-bottom; } @mixinslide-bottom-hide{ 0%{ -webkit-transform:translate3d(0,0,0); -moz-transform:translate3d(0,0,0); -ms-transform:translate3d(0,0,0); -o-transform:translate3d(0,0,0); transform:translate3d(0,0,0); } 100%{ -webkit-transform:translate3d(0,400%,0); -moz-transform:translate3d(0,400%,0); -ms-transform:translate3d(0,400%,0); -o-transform:translate3d(0,400%,0); transform:translate3d(0,400%,0); } } @keyframesslideBottomHide{ @includeslide-bottom-hide; } @-webkit-keyframesslideBottomHide{ @includeslide-bottom-hide; } @mixinslide-left{ 0%{ -webkit-transform:translate3d(-400%,0,0); -moz-transform:translate3d(-400%,0,0); -ms-transform:translate3d(-400%,0,0); -o-transform:translate3d(-400%,0,0); transform:translate3d(-400%,0,0); } 100%{ -webkit-transform:translate3d(0,0,0); -moz-transform:translate3d(0,0,0); -ms-transform:translate3d(0,0,0); -o-transform:translate3d(0,0,0); transform:translate3d(0,0,0); } } @keyframesslideLeft{ @includeslide-left; } @-webkit-keyframesslideLeft{ @includeslide-left; } @mixinslide-left-hide{ 0%{ -webkit-transform:translate3d(0,0,0); -moz-transform:translate3d(0,0,0); -ms-transform:translate3d(0,0,0); -o-transform:translate3d(0,0,0); transform:translate3d(0,0,0); } 100%{ -webkit-transform:translate3d(-400%,0,0); -moz-transform:translate3d(-400%,0,0); -ms-transform:translate3d(-400%,0,0); -o-transform:translate3d(-400%,0,0); transform:translate3d(-400%,0,0); } } @keyframesslideLeftHide{ @includeslide-left-hide; } @-webkit-keyframesslideLeftHide{ @includeslide-left-hide; } @mixinpopup-hide{ 0%{ z-index:99999; opacity:1; } 100%{ z-index:-1; opacity:0; } } @keyframespopupHide{ @includepopup-hide; } @-webkit-keyframespopupHide{ @includepopup-hide; } .popup{ position:fixed; top:0; left:0; width:100%; height:100%; z-index:-1; opacity:0; .popup-bg{ position:absolute; top:0; left:0; background:rgba(0,0,0,0.5); width:100%; height:100%; z-index:1; } .popup-wrapper{ position:relative; width:70%; height:70%; margin:auto; background:#fff; border-radius:5%; z-index:100; } &.hidden{ display:none; } &.show{ z-index:99999; opacity:1; &.top{ .popup-wrapper{ -webkit-animation:slideTop0.6slinearforwards; -moz-animation:slideTop0.6slinearforwards; -ms-animation:slideTop0.6slinearforwards; -o-animation:slideTop0.6slinearforwards; animation:slideTop0.6slinearforwards; } } &.right{ .popup-wrapper{ -webkit-animation:slideRight0.6slinearforwards; -moz-animation:slideRight0.6slinearforwards; -ms-animation:slideRight0.6slinearforwards; -o-animation:slideRight0.6slinearforwards; animation:slideRight0.6slinearforwards; } } &.bottom{ .popup-wrapper{ -webkit-animation:slideBottom0.6slinearforwards; -moz-animation:slideBottom0.6slinearforwards; -ms-animation:slideBottom0.6slinearforwards; -o-animation:slideBottom0.6slinearforwards; animation:slideBottom0.6slinearforwards; } } &.left{ .popup-wrapper{ -webkit-animation:slideLeft0.6slinearforwards; -moz-animation:slideLeft0.6slinearforwards; -ms-animation:slideLeft0.6slinearforwards; -o-animation:slideLeft0.6slinearforwards; animation:slideLeft0.6slinearforwards; } } } &.hide{ -webkit-animation:popupHide0.7slinearforwards; -moz-animation:popupHide0.7slinearforwards; -ms-animation:popupHide0.7slinearforwards; -o-animation:popupHide0.7slinearforwards; animation:popupHide0.7slinearforwards; &.top{ .popup-wrapper{ -webkit-animation:slideTopHide0.6slinearforwards; -moz-animation:slideTopHide0.6slinearforwards; -ms-animation:slideTopHide0.6slinearforwards; -o-animation:slideTopHide0.6slinearforwards; animation:slideTopHide0.6slinearforwards; } } &.right{ .popup-wrapper{ -webkit-animation:slideRightHide0.6slinearforwards; -moz-animation:slideRightHide0.6slinearforwards; -ms-animation:slideRightHide0.6slinearforwards; -o-animation:slideRightHide0.6slinearforwards; animation:slideRightHide0.6slinearforwards; } } &.bottom{ .popup-wrapper{ -webkit-animation:slideBottomHide0.6slinearforwards; -moz-animation:slideBottomHide0.6slinearforwards; -ms-animation:slideBottomHide0.6slinearforwards; -o-animation:slideBottomHide0.6slinearforwards; animation:slideBottomHide0.6slinearforwards; } } &.left{ .popup-wrapper{ -webkit-animation:slideLeftHide0.6slinearforwards; -moz-animation:slideLeftHide0.6slinearforwards; -ms-animation:slideLeftHide0.6slinearforwards; -o-animation:slideLeftHide0.6slinearforwards; animation:slideLeftHide0.6slinearforwards; } } } } html, body, .main{ width:100%; height:100%; overflow:hidden; } .head, .body, .foot{ width:100%; } .head, .foot{ height:15%; } .body{ height:70%; } .gray-theme{ background:#333; color:#fff; } .btn-list{ width:40%; min-width:270px; height:38px; .btn-box{ width:22%; height:100%; padding-right:4%; &:last-child{ padding-right:0; } } } .btn{ line-height:1em; width:100%; height:100%; border-radius:10%; font-size:16px; background:green; color:#ff0; text-align:center; vertical-align:middle; cursor:pointer; }
js代码:
classPopupComponent{ constructor(){ this.btnGroupEl=document.getElementsByClassName("btn-group")[0]; this.popupEl=document.getElementsByClassName("popup")[0]; this.popupBGEl=this.popupEl.querySelector(".popup-bg"); this.popupTitleEl=this.popupEl.querySelector(".popup-wrapper.title"); this.popupBodyEl=this.popupEl.querySelector(".popup-wrapper.body"); this.cancelBtnEl=this.popupEl.querySelector(".popup-wrapper.btn.cancel"); this.confirmBtnEl=this.popupEl.querySelector(".popup-wrapper.btn.confirm"); this.popupElClasslist=this.popupEl.classList; this.LEGVALS=["top","right","bottom","left"]; this.detaultPosition=""; this.position=""; this.SHOWCLASSNAME="show"; this.HIDECLASSNAME="hide"; this.HIDDENCLASSNAME="hidden"; } /** *给弹窗的标题和主体添加内容 *@paramObjectcontentObj传递的对象 */ setContentForPopup(contentObj={'title':'title','body':'body'}){ try{ if(!TB.isObject(contentObj)){ thrownewError("TheparamofsetContentForPopupfunctionerror!"); } letvalue; for(letpropincontentObj){ if(!contentObj.hasOwnProperty(prop)){ continue; } if(prop==='title'){ value=contentObj[prop]; this.popupTitleEl.innerText=value; } if(prop==='body'){ value=contentObj[prop]; this.popupBodyEl.innerText=value; } } }catch(e){ console.log("Popupelementisnotexist!"); console.error(e); } } /** *删除弹窗的类名 *@returnvoid */ deletePopupPreviousClassName(){ if(this.HIDDENCLASSNAME&&KB.checkType.isString(this.HIDDENCLASSNAME)){ this.popupElClasslist.remove(this.HIDDENCLASSNAME); } if(this.detaultPosition&&KB.checkType.isString(this.detaultPosition)){ this.popupElClasslist.remove(this.detaultPosition); } this.detaultPosition=this.position; } /** *弹窗隐藏 *@returnvoid */ popupHide(){ if(this.popupElClasslist.contains(this.SHOWCLASSNAME)){ this.popupElClasslist.remove(this.SHOWCLASSNAME); this.popupElClasslist.add(this.HIDECLASSNAME); } } /** *弹窗显示 *@returnvoid */ popupShow(){ this.deletePopupPreviousClassName(); if(this.popupElClasslist.contains(this.HIDECLASSNAME)){ this.popupElClasslist.remove(this.HIDECLASSNAME); this.popupElClasslist.add(this.SHOWCLASSNAME); this.popupElClasslist.add(this.position); } this.setContentForPopup({ 'title':this.position+'title', 'body':this.position+'body', }); } /** *按钮容器的点击事件 *@paramObjecte点击的事件event *@returnvoid */ btnGroupClickEvent(e){ letbtnEl=e.target||e.srcElement; if(!TB.isElement(btnEl)){ thrownewError("Getbtnelementerror!"); } this.position=btnEl.getAttribute("data-position"); if(!TB.isString(this.position)||(this.LEGVALS.indexOf(this.position)<0)){ thrownewError("Cannotgetpositionvaluefrombtnelement!"); } this.popupShow(); } /** *给DOM元素添加点击事件 *@paramObjectelem添加点击事件的dom元素 *@paramFunctionfn触发事件调用的回调函数 */ addClickEventFormElem(elem,fn){ TB.addHandler.call(this,elem,'click',fn,false); } /** *初始化函数 *@returnvoid */ init(){ this.addClickEventFormElem(this.btnGroupEl,this.btnGroupClickEvent); this.addClickEventFormElem(this.cancelBtnEl,this.popupHide); this.addClickEventFormElem(this.confirmBtnEl,this.popupHide); } } letpopupComponent=newPopupComponent(); popupComponent.init();
TB.addHandler:
/* *给DOM元素添加事件 *@paramvoid *@returncallbackfunction回调函数 **/ functionaddHandler(elem,type,callback,useCapture){ varcheckType=checkArgumentType(), _document=document, _callback=checkType.isFunction(callback)?callback:function(){}, _self=this; if(!checkType.isElement(elem)||!checkType.isString(type)){ return; } if(_document.addEventListener){ addHandler=function(elem,type,callback,useCapture){ elem.addEventListener(type,function(e){ _callback.call(_self,e); },useCapture||false); } }elseif(_document.attachEvent){ addHandler=function(elem,type,callback,useCapture){ elem.attachEvent("on"+type,function(e){ _callback.apply(_self,[e]); }); } }else{ addHandler=function(elem,type,callback,useCapture){ elem["on"+type]=function(e){ _callback.call(_self,e); }; } } addHandler(elem,type,callback,useCapture); }
首先说一下弹窗的DOM结构:
在外层一般是绝对定位,并使用flex布局使得内容居中;它的直接子元素一般有两个,黑色背景层和内容容器;如图所示:
样式的动画相信前端的同学一般都知道怎么做;但是有一点要注意,不要试图使用display来实现动画;
我使用的解决的办法是首先
动画的显示隐藏使用的z-index和opacity;但是这样存在开始时,弹窗会缓缓隐藏,那么我们可以用一个类表示display:none;点击显示弹层时,移除该类即可;
对于js没什么好说的,无非是操作类名;但是有一点要注意事件注册和this的指向;
注意我的addHandler函数,该函数只会判断一次浏览器的环境,不需要反复的判断浏览器的环境;
在btnGroupClickEvent函数中this是指向PopupComponent类,而不是事件的event;所以addHandler函数中首先保存this的指向,然后使用call或者apply改变this的指向
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。