拖动框 + 收回展开

433 阅读4分钟

image-20190824183015363.png

1. 点击事件绑定在要点击拖动的元素上

<div
  class="area"
  @mousedown.stop="mouseDown"> // 阻止冒泡
</div>
  • 鼠标按下
    • 获取当前的 window.clientY ,并存储在数组里(这里我是用长度为2的数组,记录鼠标移动前后的坐标)
    • 给一个开关,保证是从点击当前元素开始

2. 移动和抬起事件绑定在了最外面的 App 上面

let appDocument = document.getElementById('app')
appDocument.addEventListener('mouseup', function (e) {
  // throttle 防抖节流函数   mouseUp 鼠标抬起事件
  throttle(that.mouseUp(e), 200, that, true)
})
appDocument.addEventListener('mousemove', function (e) {
  // mouseMove 鼠标移动事件
  throttle(that.mouseMove(e), 200, that, true)
})
  • ######鼠标移动

    • e = window.event || e(因为我的鼠标移动在多个元素之间,所以我选择了绑定了 window 全局的事件)

    • 保存 e.clientY (同样的因为 offectY 是根据当前元素的位置计算的值,因为在多个元素间移动,所以选用针对视窗定位的 clientY ;也可以直接用不存进变量,因为之前不了解 重绘 的触发条件,保险起见选择了保存复用)

    • 将当前鼠标位置存进定义的储存位置的数组里(如果只有按下时的值,直接push,如果已经存在arr[0],arr[1] 则前移再push

    • 是否触发样式重设:鼠标按下的开关 & 鼠标位置是否超过一定范围

    • 是: 用位置数组的两个值相减,计算出鼠标位置的变化,触发对应事件并且传入差值

      • 模块

      • this.actionEle = document.getElementsByClassName('fanFan')[0]
        mouseChange (mouseChange) {
          // 当前高度是动态的
          this.currentTop = parseInt(this.actionEle.style.top || 0)
          let moveTop = this.currentTop - mouseChange
          // 虽然限制了鼠标位置的范围,但是为了防止各种骚操作最后再限制一下要设置的Top值的范围
          moveTop = moveTop > 384 ? 384 : (moveTop < -253 ? -253 : moveTop)
          this.actionEle.style.top = moveTop + 'px'
        }
        
  • 鼠标抬起
    • 关掉鼠标按下的开关

3. 当我们写好了拖动框之后可能会还想要一个点击收回的效果

.warpper {
    position: relative;
    min-height: calc(100vh - 240px);
    .main {
      position: absolute;
      overflow: hidden;
      display:flex;
      // 主轴方向
      flex-direction: columns;
      // flex-grow(项目的放大比例,默认为0,即如果存在剩余空间,也不放大。) 
      // flex-shrink(项目的缩小比例,默认为1,即如果空间不足,该项目将缩小) 
      // flex-basis(项目的缩小比例,默认为1,即如果空间不足,该项目将缩小项目占据的主轴空间)
      flex: 1 1 0%;
      // 这是一个遮罩  
    	background-color: rgba(0, 0, 0, 0) !important;
      // 这是一个框格背景的实现
      width: 100%;
      height: 100%;
      background-size: 50px 50px;
    	background-image: linear-gradient(0deg, transparent 24%, rgba(0, 0, 0, 0.05) 25%, 			    rgba(0, 0, 0, 0.05) 26%, transparent 27%, transparent 74%, rgba(0, 0, 0, 0.05) 75%, 				rgba(0, 0, 0, 0.05) 76%, transparent 77%, transparent), linear-gradient(90deg, 							transparent 24%, rgba(0, 0, 0, 0.05) 25%, rgba(0, 0, 0, 0.05) 26%, transparent 27%, 				transparent 74%, rgba(0, 0, 0, 0.05) 75%, rgba(0, 0, 0, 0.05) 76%, transparent 77%, 				transparent);
      // 这是拖动框上面的主面板
      .middle {
        flex: 0 0 auto;
        position: relative;
        height: 300px;
      }
      
     
      // 点击添加这个class 展开这个拖动的块
      .open_tabs {
        min-height: calc(100vh - 420px);
        position: relative;
      }
      // 点击添加这个class 收回这个拖动的块
      .close_tabs {
        height: 35px;
        position: absolute;
        bottom: 0;
        top: auto !important;
      }
      // 这是要拖动的块
      .down {
        flex: 1 1 0%;
        background: white;
      } 
  	}
  }
  • 这时要注意,不要再去修改该块的top值
    • 原因一: 修改之后可能会导致无法拖动
    • 原因二:当你回收的时候在css里并不能知道该块现在的高度(之所以选择css做这个事情,是因为如果想要加上一些动画效果会方便很多)
  • 那怎么做呢
    • 我是去改变要收起元素的高度来解决的,具体 scss 代码在上面

4. 防抖和节流

//	这个是之前在网上搜的代码,找不见原链接了,如原作者介意,联系delete
/**
 * 防抖节流
 * @param {*} action 回调
 * @param {*} delay 等待的时间
 * @param {*} context this指针
 * @param {Boolean} iselapsed 是否等待上一次
 * @returns {Function}
 */
// eslint-disable-next-line no-unused-vars
function throttle (action, delay, context, iselapsed) {
  let timeout = null
  let lastRun = 0
  return function () {
    if (timeout) {
      if (iselapsed) {
        return
      } else {
        clearTimeout(timeout)
        timeout = null
      }
    }
    let elapsed = Date.now() - lastRun
    let args = arguments
    if (iselapsed && elapsed >= delay) {
      runCallback()
    } else {
      timeout = setTimeout(runCallback, delay)
    }
    /**
     * 执行回调
     */
    function runCallback () {
      lastRun = Date.now()
      timeout = false
      action.apply(context, args)
    }
  }
}

export { throttle }

5. 回流的发生条件

  • add/delete DOM
  • 元素的大小、位置、内容发生改变
  • offset属性
  • 页面样式style发生变化
  • 浏览器窗口变化
  • 固定定位
  • 待补充......