目录
一. 需求简介
- 如下图所示,点击右侧一排按钮之后,会有对应的弹框,从 1 处滑出
- 为什么要单独写这个呢?
二. 从 2 处划出的原理
- 如果点击按钮之后,从 2 处弹出,实现起来会格外简单:
- 在最开始时,将弹框定位在屏幕外侧(注:此设计稿为 1920*1080),也就是定位在 right: -1920px,右侧屏幕的外面
- 点击按钮后,将弹框定位修改为 right: 1920px,也就是定位在屏幕左侧开始的地方
- 最后给弹框本身加个 过渡 效果:transition: all 1s ease;
- 此时,点击侧边栏按钮,弹框就会从右侧屏幕外(2处)滑入左侧屏幕,观看体验较差
三. 从 1 处划出的原理
- 如果点击按钮之后,从 1 处弹出,实现起来会较为复杂:
- 思考一下,如何确保弹框从 1处 出现之前,是隐藏的状态呢?
- 如果沿用 1.1 中的方法,将弹框定位在 1处 右边,那么 1处 右边这部分,是无法隐藏的
- 不要考虑使用 display: none/block; 控制显隐,因为 transition: all 1s ease; 和它是冲突的,display: none/block; 这种控制显隐的方法,会导致过渡效果失效
我的解决方案:- 在弹框外侧,加 <div class="home-model-outer"> 进行包裹,我称之为 容器A
- 容器A,最开始会被定位在屏幕的左侧,也就是弹框最终会出现的位置
- 容器A,最开始的宽高会被设置为0,防止阻挡下层页面的点击事件
- 弹框此时作为 容器A 的子元素,会被定位在 1处 外侧,即 1处 - 2处 之间有弹框
- 容器A,会被设置溢出隐藏,这样超过 容器A 的子元素弹框,就会不为人所见
- 当点击按钮之后,修改 容器A 的宽高(改成和弹框一样的大小),此时,容器A覆盖于页面最上方,其面的内容将无法进行交互
- 随着 容器A 宽高的修改,弹框将被完整的显现,宽高是一瞬间修改的,弹框的动画是有时间延迟的,因此弹框的动画效果被完整的保留
<div class="home-model-outer"> <div class="home-model-box" data-modalIndex="0"></div> <div class="home-model-box" data-modalIndex="1"></div> <div class="home-model-box" data-modalIndex="2"></div> ... </div>
四. 完整示例
4.1 html 结构
<!-- 右侧按钮列表 --> <ul> <li> <a class="model-handle" href="#" data-modalHandleIndex="0"> 右侧边栏按钮0</a> </li> <li> <a class="model-handle" href="#" data-modalHandleIndex="1"> 右侧边栏按钮1</a> </li> <li> <a class="model-handle" href="#" data-modalHandleIndex="2"> 右侧边栏按钮2</a> </li> </ul> <!-- 弹框显隐容器 --> <div class="home-model-outer"> <!-- 弹框动画容器 --> <div class="home-model-box" data-modalIndex="0"> <!-- 弹框内嵌的 iframe --> <iframe id="main-content-iframe" name="main" frameBorder="0" class="right-link-iframe" scrolling="auto" src="${ctx}/common/homeDialog/administrativeOffice.html"> </iframe> </div> <div class="home-model-box" data-modalIndex="1">...</div> <div class="home-model-box" data-modalIndex="2">...</div> </div>
- 上部分代码主要是结构,分为:右侧按钮列表 及 弹框显隐容器
- 右侧按钮列表中,通过自定义属性 data-modalHandleIndex="0" 与对应的弹框关联
- 弹框显隐容器内,包含了全部的弹框,每个弹框通过自定义属性 data-modalIndex="0" 对应右侧按钮
- 每个弹框内部嵌入 iframe,对应各自弹框的内容
4.2 css 原来的样式
/* 弹框外层容器 */ .home-model-outer { position: absolute; top: 0; left: -1436px; width: 0; height: 0; overflow: hidden; } /* 弹框动画容器(弹框本身) */ .home-model-box { position: absolute; top: 0; left: 1436px; width: 1436px; height: 800px; z-index: 10; transition: all 1s ease; } /* iframe 样式 */ .right-link-iframe { width:100%; height:100%; border: none; overflow-x: hidden; overflow-y:auto; }
- 弹框外层容器:是相对于右侧按钮列表定位的,宽高被设置为0,溢出隐藏,偏左的距离就是弹框最终出现后的宽度
- 弹框动画容器(弹框本身):是相对于弹框外层容器定位的,定位距离是弹框本身的宽度,加上动画效果
4.3 右侧链接的点击事件
- 给 右侧按钮 的 a标签 绑定事件,点击 a标签 时,当前被点击的按钮添加激活样式,兄弟按钮移除激活样式
- 通过 $(this.attr("xxx") 获取 a标签的自定义属性,及当前 a标签 对应的 弹框编号
/* 右侧链接点击事件 */ $('.model-handle').click(function () { $(this).parent('li').addClass('active').siblings().removeClass('active'); /* 获取被点击的链接编号 */ modalIndex = $(this).attr("data-modalHandleIndex"); /* 判断打开/关闭对应的弹框 */ eachMyModal(modalIndex); });
4.4 打开 / 关闭相应弹框的方法
- 该方法需要接收参数:从 a链接 自定义属性中获取的,对应的弹框编号:
- function eachMyModal(modalIndex) { ... }
- 遍历弹框动画容器(弹框本身),获取各个弹框的自身编号:
- var modleIndexNowEle = $(this).attr('data-modalIndex');
- 获取当前遍历到的弹框的左边距:
- var left = $(this).css('left');
- 进行逻辑判断1 —— 此方法接受的链接编号 = 当前弹框编号,且弹框当前是隐藏状态,就显示弹框,并让父元素充满容器
if (modleIndexNowEle === modalIndex && left === '1436px') { console.log('点击划出',left); /* 显示弹框 */ $(this).css('left', '0px').siblings().css('left', '1436px'); /* 父元素充满容器 */ $('.home-model-outer').css({ 'width': '1436px', 'height': '800px', });
- 进行逻辑判断2 —— 此方法接受的链接编号 = 当前弹框编号,且弹框当前是显示状态,就隐藏弹框,并让父元素宽高为0,防止下层的点击事件出现问题
else if (modleIndexNowEle === modalIndex && left === '0px') { console.log('点击隐藏',left); /* 隐藏弹框 */ $(this).css('left', '1436px'); $('.model-handle').parent('li').removeClass('active'); $('.home-model-outer').css({ 'width': '0', 'height': '0', }); }
4.5 逻辑代码合并
/* 当前点击的右侧链接编号 */ var modalIndex; /* 右侧链接点击事件 */ $('.model-handle').click(function () { $(this).parent('li').addClass('active').siblings().removeClass('active'); /* 获取被点击的链接编号 */ modalIndex = $(this).attr("data-modalHandleIndex"); /* 判断打开/关闭对应的弹框 */ eachMyModal(modalIndex); }); /* 判断打开/关闭当前弹框 */ function eachMyModal(modalIndex) { $('.home-model-box').each(function(index) { /* 获取弹框编号 */ var modleIndexNowEle = $(this).attr('data-modalIndex'); /* 获取弹框宽度 */ var width = $(this).css('width'); /* 获取弹框展示状态 */ var display = $(this).css('display'); /* 获取弹框居左状态 */ var left = $(this).css('left'); /* 获取弹框层级 */ var zIndex = $(this).css('zIndex'); /* 链接编号 = 当前弹框编号,弹框当前是隐藏状态,就显示弹框,并让父元素充满容器 */ if (modleIndexNowEle === modalIndex && left === '1436px') { console.log('点击划出',left); /* 显示弹框 */ $(this).css('left', '0px').siblings().css('left', '1436px'); /* 父元素充满容器 */ $('.home-model-outer').css({ 'width': '1436px', 'height': '800px', }); /* 链接编号 = 当前弹框编号,弹框当前是显示状态,就隐藏弹框,并让父元素宽高为0,防止影响点击事件 */ } else if (modleIndexNowEle === modalIndex && left === '0px') { console.log('点击隐藏',left); /* 隐藏弹框 */ $(this).css('left', '1436px'); $(this).css('boxShadow', 'none'); $('.model-handle').parent('li').removeClass('active'); $('.home-model-outer').css({ 'width': '0', 'height': '0', }); } else {} }); }
实现点击侧边栏,从侧边栏处开始(而不是屏幕外侧),滑动出现弹框的效果
最新推荐文章于 2023-10-31 23:12:46 发布
本文详细阐述了如何避免直接从屏幕边缘弹出弹框导致的体验问题,通过嵌套容器和CSS动画,实现了从已知位置平滑过渡的效果。通过实例展示了HTML结构、CSS样式调整和JavaScript逻辑,以实现实时响应的弹框切换。
摘要由CSDN通过智能技术生成