javascript实现弹出层效果


Posted in Javascript onDecember 10, 2019

弹出层和弹窗相似但是并不相同;弹窗和弹出层都是由用户触发的显示提示信息的弹出面板;但是弹窗只是显示一些信息,没有太多的复杂的交互事件;而弹层类似一个整个页面,可以实现页面的所有功能;

现在前端弹层使用的很频繁,如支付宝支付弹层等…所以掌握弹层是一个很重要的技能。如果只是简单的隐藏和切换,当然就不必说,我要说的html+animate+es6实现弹层;

javascript实现弹出层效果

javascript实现弹出层效果

javascript实现弹出层效果

javascript实现弹出层效果

html弹层结构:

<main class="main">
 <header class="head flex-center gray-theme">This is Header</header>
 <section class="body flex-center">
  <ul class="btn-list flex-center btn-group">
  <li class="btn-box"><span class="btn inline-flex-center" data-position="top">上弹层</span></li>
  <li class="btn-box"><span class="btn inline-flex-center" data-position="right">右弹层</span></li>
  <li class="btn-box"><span class="btn inline-flex-center" data-position="bottom">下弹层</span></li>
  <li class="btn-box"><span class="btn inline-flex-center" data-position="left">左弹层</span></li>
  </ul>
 </section>
 <footer class="foot flex-center gray-theme">This is Footer</footer>
 <!-- popup -->
 <section class="popup flex-center hide hidden">
  <section class="popup-bg"></section>
  <section class="popup-wrapper">
  <header class="title head flex-center"></header>
  <section class="container body flex-center"></section>
  <footer class="btn-wrapper foot flex-center">
   <ul class="btn-list flex-center">
   <li class="btn-box"><span class="btn cancel inline-flex-center">取消</span></li>
   <li class="btn-box"><span class="btn confirm inline-flex-center">确认</span></li>
   </ul>
  </footer>
  </section>
 </section>
</main>

css代码:

@mixin slide-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);
 }
}

@keyframes slideTop{
 @include slide-top;
}

@-webkit-keyframes slideTop{
 @include slide-top;
}

@mixin slide-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);
 }
}

@keyframes slideTopHide{
 @include slide-top-hide;
}

@-webkit-keyframes slideTopHide{
 @include slide-top-hide;
}

@mixin slide-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);
 }
}

@keyframes slideRight{
 @include slide-right;
}

@-webkit-keyframes slideRight{
 @include slide-right;
}

@mixin slide-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);
 }
}

@keyframes slideRightHide{
 @include slide-right-hide;
}

@-webkit-keyframes slideRightHide{
 @include slide-right-hide;
}

@mixin slide-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);
 }
}

@keyframes slideBottom{
 @include slide-bottom;
}

@-webkit-keyframes slideBottom{
 @include slide-bottom;
}

@mixin slide-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);
 }
}

@keyframes slideBottomHide{
 @include slide-bottom-hide;
}

@-webkit-keyframes slideBottomHide{
 @include slide-bottom-hide;
}

@mixin slide-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);
 }
}

@keyframes slideLeft{
 @include slide-left;
}

@-webkit-keyframes slideLeft{
 @include slide-left;
}

@mixin slide-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);
 }
}

@keyframes slideLeftHide{
 @include slide-left-hide;
}

@-webkit-keyframes slideLeftHide{
 @include slide-left-hide;
}

@mixin popup-hide{
 0%{
 z-index: 99999;
 opacity: 1;
 }
 100%{
 z-index: -1;
 opacity: 0;
 }
}

@keyframes popupHide{
 @include popup-hide;
}

@-webkit-keyframes popupHide{
 @include popup-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: slideTop 0.6s linear forwards;
  -moz-animation: slideTop 0.6s linear forwards;
  -ms-animation: slideTop 0.6s linear forwards;
  -o-animation: slideTop 0.6s linear forwards;
  animation: slideTop 0.6s linear forwards;
  }
 }
 &.right{
  .popup-wrapper{
  -webkit-animation: slideRight 0.6s linear forwards;
  -moz-animation: slideRight 0.6s linear forwards;
  -ms-animation: slideRight 0.6s linear forwards;
  -o-animation: slideRight 0.6s linear forwards;
  animation: slideRight 0.6s linear forwards;
  }
 }
 &.bottom{
  .popup-wrapper{
  -webkit-animation: slideBottom 0.6s linear forwards;
  -moz-animation: slideBottom 0.6s linear forwards;
  -ms-animation: slideBottom 0.6s linear forwards;
  -o-animation: slideBottom 0.6s linear forwards;
  animation: slideBottom 0.6s linear forwards;
  }
 }
 &.left{
  .popup-wrapper{
  -webkit-animation: slideLeft 0.6s linear forwards;
  -moz-animation: slideLeft 0.6s linear forwards;
  -ms-animation: slideLeft 0.6s linear forwards;
  -o-animation: slideLeft 0.6s linear forwards;
  animation: slideLeft 0.6s linear forwards;
  }
 }
 }
 &.hide{
 -webkit-animation: popupHide 0.7s linear forwards;
 -moz-animation: popupHide 0.7s linear forwards;
 -ms-animation: popupHide 0.7s linear forwards;
 -o-animation: popupHide 0.7s linear forwards;
 animation: popupHide 0.7s linear forwards;
 &.top{
  .popup-wrapper{
  -webkit-animation: slideTopHide 0.6s linear forwards;
  -moz-animation: slideTopHide 0.6s linear forwards;
  -ms-animation: slideTopHide 0.6s linear forwards;
  -o-animation: slideTopHide 0.6s linear forwards;
  animation: slideTopHide 0.6s linear forwards;
  }
 }
 &.right{
  .popup-wrapper{
  -webkit-animation: slideRightHide 0.6s linear forwards;
  -moz-animation: slideRightHide 0.6s linear forwards;
  -ms-animation: slideRightHide 0.6s linear forwards;
  -o-animation: slideRightHide 0.6s linear forwards;
  animation: slideRightHide 0.6s linear forwards;
  }
 }
 &.bottom{
  .popup-wrapper{
  -webkit-animation: slideBottomHide 0.6s linear forwards;
  -moz-animation: slideBottomHide 0.6s linear forwards;
  -ms-animation: slideBottomHide 0.6s linear forwards;
  -o-animation: slideBottomHide 0.6s linear forwards;
  animation: slideBottomHide 0.6s linear forwards;
  }
 }
 &.left{
  .popup-wrapper{
  -webkit-animation: slideLeftHide 0.6s linear forwards;
  -moz-animation: slideLeftHide 0.6s linear forwards;
  -ms-animation: slideLeftHide 0.6s linear forwards;
  -o-animation: slideLeftHide 0.6s linear forwards;
  animation: slideLeftHide 0.6s linear forwards;
  }
 }
 }

}

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代码:

class PopupComponent {
 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";
 }

 /**
  * 给弹窗的标题和主体添加内容
  * @param Object contentObj 传递的对象
  */
 setContentForPopup(contentObj = {'title':'title', 'body': 'body'}) {
  try{
  if (!TB.isObject(contentObj)) {
   throw new Error("The param of setContentForPopup function error!");
  }
  let value;
  for (let prop in contentObj) {
   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("Popup element is not exist!");
  console.error(e);
  }
 }

 /**
  * 删除弹窗的类名
  * @return void
  */
 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;
 }

 /**
  * 弹窗隐藏
  * @return void
  */
 popupHide() {
  if (this.popupElClasslist.contains(this.SHOWCLASSNAME)) {
  this.popupElClasslist.remove(this.SHOWCLASSNAME);
  this.popupElClasslist.add(this.HIDECLASSNAME);
  }
 }

 /**
  * 弹窗显示
  * @return void
  */
 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',
  });
 }

 /**
  * 按钮容器的点击事件
  * @param Object e 点击的事件event
  * @return void
  */
 btnGroupClickEvent(e) {
  let btnEl = e.target || e.srcElement;
  if (!TB.isElement(btnEl)) {
  throw new Error("Get btn element error!");
  }
  this.position = btnEl.getAttribute("data-position");
  if (!TB.isString(this.position) || (this.LEGVALS.indexOf(this.position) < 0)) {
  throw new Error("Can not get position value from btn element!");
  }
  this.popupShow();

 }

 /**
  * 给DOM元素添加点击事件
  * @param Object elem 添加点击事件的dom元素 
  * @param Function fn  触发事件调用的回调函数
  */
 addClickEventFormElem(elem, fn) {
  TB.addHandler.call(this, elem, 'click', fn, false);
 }

 /**
  * 初始化函数
  * @return void
  */
 init() {
  this.addClickEventFormElem(this.btnGroupEl, this.btnGroupClickEvent);
  this.addClickEventFormElem(this.cancelBtnEl, this.popupHide);
  this.addClickEventFormElem(this.confirmBtnEl, this.popupHide);
 }
 }

 let popupComponent = new PopupComponent();
 popupComponent.init();

TB.addHandler:

/*
* 给DOM元素添加事件
* @param void
* @return callback function 回调函数
* */
function addHandler(elem, type, callback, useCapture) {
 var checkType = 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); 
 }
 } else if (_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布局使得内容居中;它的直接子元素一般有两个,黑色背景层和内容容器;如图所示:

javascript实现弹出层效果

样式的动画相信前端的同学一般都知道怎么做;但是有一点要注意,不要试图使用display来实现动画;
我使用的解决的办法是首先

动画的显示隐藏使用的z-index和opacity;但是这样存在开始时,弹窗会缓缓隐藏,那么我们可以用一个类表示display: none;点击显示弹层时,移除该类即可;

对于js没什么好说的,无非是操作类名;但是有一点要注意事件注册和this的指向;
注意我的addHandler函数,该函数只会判断一次浏览器的环境,不需要反复的判断浏览器的环境;
在btnGroupClickEvent函数中this是指向PopupComponent类,而不是事件的event;所以addHandler函数中首先保存this的指向,然后使用call或者apply改变this的指向

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JQuery 浮动导航栏实现代码
Aug 27 Javascript
使用jQuery重置(reset)表单的方法
May 05 Javascript
node.js中的console.warn方法使用说明
Dec 09 Javascript
移动Web中图片自适应的两种JavaScript解决方法
Jun 18 Javascript
牛叉的Jquery——Jquery与DOM对象的互相转换及DOM的三种操作
Oct 29 Javascript
request请求获取参数的实现方法(post和get两种方式)
Sep 27 Javascript
angular+webpack2实战例子
May 23 Javascript
vue中axios处理http发送请求的示例(Post和get)
Oct 13 Javascript
详解从零搭建 vue2 vue-router2 webpack3 工程
Nov 22 Javascript
Javascript中parseInt的正确使用方式
Oct 17 Javascript
vue3修改link标签默认icon无效问题详解
Oct 09 Javascript
vue-socket.io跨域问题有效解决方法
Feb 11 Javascript
element表格翻页第2页从1开始编号(后端从0开始分页)
Dec 10 #Javascript
微信小程序实现注册登录功能(表单校验、错误提示)
Dec 10 #Javascript
微信小程序登陆注册功能的实现代码
Dec 10 #Javascript
vue excel上传预览和table内容下载到excel文件中
Dec 10 #Javascript
JS实现点餐自动选择框(案例分析)
Dec 10 #Javascript
原生js实现随机点餐效果
Dec 10 #Javascript
使用原生JS实现火锅点餐小程序(面向对象思想)
Dec 10 #Javascript
You might like
COM in PHP (winows only)
2006/10/09 PHP
QQ登录 PHP OAuth示例代码
2011/07/20 PHP
PHP实现克鲁斯卡尔算法实例解析
2014/08/22 PHP
PHP高级编程实例:编写守护进程
2014/09/02 PHP
Symfony数据校验方法实例分析
2015/01/26 PHP
PHP中include/require/include_once/require_once使用心得
2016/08/28 PHP
两个select之间option的互相添加操作(jquery实现)
2009/11/12 Javascript
使用jquery局部刷新(jquery.load)从数据库取出数据
2014/01/22 Javascript
Javascript基础知识(三)BOM,DOM总结
2014/09/29 Javascript
Javascript基础教程之数据类型转换
2015/01/18 Javascript
Javascript基础教程之函数对象和属性
2015/01/18 Javascript
AngularJS iframe跨域打开内容时报错误的解决办法
2015/01/26 Javascript
JavaScript+CSS实现仿天猫侧边网页菜单效果
2015/08/25 Javascript
zepto中使用swipe.js制作轮播图附swipeUp,swipeDown不起效果问题
2015/08/27 Javascript
jquery制作图片时钟特效
2020/03/30 Javascript
分享jQuery网页元素拖拽插件
2020/12/01 Javascript
BootStrap 附加导航组件
2016/07/22 Javascript
VueJs路由跳转——vue-router的使用详解
2017/01/10 Javascript
Bootstrap列表组学习使用
2017/02/09 Javascript
VUE实现一个分页组件的示例
2017/09/13 Javascript
vue登录页面cookie的使用及页面跳转代码
2019/07/10 Javascript
深入理解javascript prototype的相关知识
2019/09/19 Javascript
JavaScript中数组去重的5种方法
2020/07/04 Javascript
使用python Django做网页
2013/11/04 Python
python中字符串变二维数组的实例讲解
2018/04/03 Python
python 编写简单网页服务器的实例
2018/06/01 Python
python 实现的发送邮件模板【普通邮件、带附件、带图片邮件】
2019/07/06 Python
wxPython实现画图板
2020/08/27 Python
Python创建一个元素都为0的列表实例
2019/11/28 Python
End Clothing美国站:英国男士潮牌商城
2018/04/20 全球购物
土木工程专业推荐信
2014/02/19 职场文书
2014法制宣传日活动总结
2014/07/09 职场文书
课堂打架检讨书200字
2014/11/21 职场文书
李强感恩观后感
2015/06/17 职场文书
2019年大学毕业生个人自我鉴定范文大全
2019/03/21 职场文书
golang 实用库gotable的具体使用
2021/07/01 Golang