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 相关文章推荐
借用Google的Javascript API Loader来加速你的网站
Jan 28 Javascript
分别用marquee和div+js实现首尾相连循环滚动效果,仅3行代码
Sep 21 Javascript
P3P Header解决Cookie跨域的问题
Mar 12 Javascript
jQuery .attr()和.removeAttr()方法操作元素属性示例
Jul 16 Javascript
使用AngularJS实现表单向导的方法
Jun 19 Javascript
浅析如何利用angular结合translate为项目实现国际化
Dec 08 Javascript
Jquery树插件zTree实现菜单树
Jan 24 Javascript
node.js操作mysql简单实例
May 25 Javascript
vue-cli项目中怎么使用mock数据
Sep 27 Javascript
jQuery实现轮播图效果
Nov 26 jQuery
JS实现电脑虚拟键盘的操作
Jun 24 Javascript
解决Antd Table表头加Icon和气泡提示的坑
Nov 17 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
比较详细PHP生成静态页面教程
2012/01/10 PHP
PHP 读取和编写 XML
2014/11/19 PHP
关于Laravel Route重定向的一个注意点
2017/01/16 PHP
PHP三种方式实现链式操作详解
2017/01/21 PHP
PHP运用foreach神奇的转换数组(实例讲解)
2018/02/01 PHP
PHP面向对象程序设计内置标准类,普通数据类型转为对象类型示例
2019/06/12 PHP
详解no input file specified 三种解决方法
2019/11/29 PHP
JS input文本框禁用右键和复制粘贴功能的代码
2010/04/15 Javascript
javascript for循环从入门到偏门(效率优化+奇特用法)
2012/08/01 Javascript
P3P Header解决Cookie跨域的问题
2013/03/12 Javascript
js实现文章文字大小字号功能完整实例
2014/11/01 Javascript
js正则匹配出所有图片及图片地址src的方法
2015/06/08 Javascript
跟我学习javascript的异步脚本加载
2015/11/20 Javascript
在 Express 中使用模板引擎
2015/12/10 Javascript
利用CSS、JavaScript及Ajax实现图片预加载的方法
2016/11/29 Javascript
js手机号批量滚动抽奖实现代码
2020/04/17 Javascript
json字符串传到前台input的方法
2018/08/06 Javascript
详解puppeteer使用代理
2018/12/27 Javascript
nodejs分离html文件里面的js和css的方法
2019/04/09 NodeJs
微信小程序Flex布局用法深入浅出分析
2019/04/25 Javascript
使用js实现一个简单的滚动条过程解析
2019/09/10 Javascript
浅谈微信小程序列表埋点曝光指南
2019/10/15 Javascript
python基础教程之对象和类的实际运用
2014/08/29 Python
Python类的用法实例浅析
2015/05/27 Python
用Python删除本地目录下某一时间点之前创建的所有文件的实例
2017/12/14 Python
使用Python将Mysql的查询数据导出到文件的方法
2019/02/25 Python
python sitk.show()与imageJ结合使用常见的问题
2020/04/20 Python
Python3读写ini配置文件的示例
2020/11/06 Python
PHP如何设置和取得Cookie值
2015/06/30 面试题
上级检查欢迎词
2014/01/18 职场文书
岗位职责说明书
2014/05/07 职场文书
学习张丽丽心得体会
2014/09/03 职场文书
会计试用期自我评价
2014/09/19 职场文书
国情备忘录观后感
2015/06/04 职场文书
七一活动主持词
2015/06/29 职场文书
Python Pandas pandas.read_sql函数实例用法
2021/06/21 Python