实现点击侧边栏,从侧边栏处开始(而不是屏幕外侧),滑动出现弹框的效果

目录

一. 需求简介

二. 从 2 处划出的原理

三. 从 1 处划出的原理

四. 完整示例

4.1 html 结构

4.2 css 原来的样式

4.3 右侧链接的点击事件 

4.4 打开 / 关闭相应弹框的方法

4.5 逻辑代码合并


一. 需求简介

  • 如下图所示,点击右侧一排按钮之后,会有对应的弹框,从 处滑出
  • 为什么要单独写这个呢?

二. 从 2 处划出的原理

  • 如果点击按钮之后,从 2 处弹出,实现起来会格外简单:
  1. 在最开始时,将弹框定位在屏幕外侧(注:此设计稿为 1920*1080),也就是定位在 right: -1920px,右侧屏幕的外面
  2. 点击按钮后,将弹框定位修改为 right: 1920px,也就是定位在屏幕左侧开始的地方
  3. 最后给弹框本身加个 过渡 效果: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 {}
    });
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lyrelion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值