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发生变化
- 浏览器窗口变化
- 固定定位
- 待补充......