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 相关文章推荐
JavaScript 匿名函数(anonymous function)与闭包(closure)
Oct 04 Javascript
javascript中使用正则计算中文长度的例子
Apr 29 Javascript
jQuery中:last选择器用法实例
Dec 30 Javascript
Javascript对象Clone实例分析
Jun 09 Javascript
学习javascript面向对象 理解javascript对象
Jan 04 Javascript
基于JavaScript实现TAB标签效果
Jan 12 Javascript
JS创建事件的三种方法(实例代码)
May 12 Javascript
详解Vue学习笔记进阶篇之列表过渡及其他
Jul 17 Javascript
jQuery plugin animsition使用小结
Sep 14 jQuery
vue使用swiper实现中间大两边小的轮播图效果
Nov 24 Javascript
如何通过vscode运行调试javascript代码
Jul 24 Javascript
15个值得收藏的JavaScript函数
Sep 15 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 empty()与isset()区别的详细介绍
2013/06/17 PHP
部署PHP项目应该注意的几点事项分享
2013/12/20 PHP
thinkphp备份数据库的方法分享
2015/01/04 PHP
php实现递归与无限分类的方法
2015/02/16 PHP
理解PHP中的Session及对Session有效期的控制
2016/01/08 PHP
php中json_encode不兼容JSON_UNESCAPED_UNICODE的解决方案
2016/05/31 PHP
让你的网站可编辑的实现js代码
2009/10/19 Javascript
jQuery前端框架easyui使用Dialog时bug处理
2014/12/05 Javascript
EasyUI中datagrid在ie下reload失败解决方案
2015/03/09 Javascript
JQuery使用$.ajax和checkbox实现下次不在通知功能
2015/04/16 Javascript
JS实现自动固定顶部的悬浮菜单栏效果
2015/09/16 Javascript
ES6中的数组扩展方法
2016/08/26 Javascript
JS移动端/H5同时选择多张图片上传并使用canvas压缩图片
2017/06/20 Javascript
自定义类似于jQuery UI Selectable 的Vue指令v-selectable
2017/08/23 jQuery
微信小程序实现折叠面板
2018/01/31 Javascript
Vue单页及多页应用全局配置404页面实践记录
2018/05/22 Javascript
ant-design-vue 实现表格内部字段验证功能
2019/12/16 Javascript
在vue中使用回调函数,this调用无效的解决
2020/08/11 Javascript
python利用hook技术破解https的实例代码
2013/03/25 Python
python实现跨文件全局变量的方法
2014/07/07 Python
python多维数组切片方法
2018/04/13 Python
Python登录注册验证功能实现
2018/06/18 Python
python的pip安装以及使用教程
2018/09/18 Python
python微元法计算函数曲线长度的方法
2018/11/08 Python
详解Python多线程下的list
2020/07/03 Python
css3和jquery实现的可折叠导航菜单适合放在手机网页的导航菜单
2014/09/02 HTML / CSS
利用html5 file api读取本地文件示例(如图片、PDF等)
2018/03/07 HTML / CSS
Sneaker Studio乌克兰:购买运动鞋
2018/03/26 全球购物
用友笔试题目
2016/10/25 面试题
会计专业自荐信范文
2013/12/02 职场文书
教师职位说明书
2014/07/29 职场文书
红领巾心向党演讲稿
2014/09/10 职场文书
2015年会计个人工作总结
2015/04/02 职场文书
长江七号观后感
2015/06/11 职场文书
环保建议书作文300字
2015/09/14 职场文书
《文化苦旅》读后感:阅读,让人诗意地栖居在大地上
2019/12/24 职场文书