问题描述:JS分栏效果问题:发现鼠标拖动分割线向上拖拽,然后鼠标弹起后正常;鼠标拖动分割线向下,然后鼠标弹起后,发现还可以继续拖拽分割线,这是不正常的。经过分析发现是以为鼠标弹起的时候坐落在了iframe上导致鼠标弹起事件失效。
效果图:
问题代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
/* 拖拽相关样式 */
.box {
width: 100%;
height: 100%;
margin: 1% 0px;
overflow: hidden;
box-shadow: -1px 9px 10px 3px rgba(0, 0, 0, 0.11);
}
/*底部div样式*/
.bottom {
position: absolute;
bottom: 0;
height: 200px;
width: 100%;
background: #fff;
}
/*拖拽区div样式*/
.resize {
position: absolute;
bottom: 203px;
height: 3px;
width: 100%;
color: #fff;
background-color: #ccc;
border-radius: 5px;
cursor: row-resize;
}
/*拖拽区鼠标悬停样式*/
.resize:hover {
color: #999;
}
</style>
<script>
/*
遇到的问题:最初写的时候,发现鼠标拖动分割线经过左右两边的iframe的时候就不灵了。
*/
window.onload = function () {
var resize = document.getElementsByClassName('resize')[0];
var bottom = document.getElementsByClassName('bottom')[0];
var box = document.getElementsByClassName('box')[0];
// 鼠标按下事件
resize.onmousedown = function (e) {
//颜色改变提醒
resize.style.background = '#818181';
var startY = e.clientY;
resize.bottom = bottom.offsetHeight;
function moveHandle (e) {
var endY = e.clientY;
var moveLen = resize.bottom + (startY - endY);
resize.style.bottom = Math.max(0, moveLen) + 'px'; // 设置底部区域的高度
console.log('resize.bottom: ' + resize.style.bottom, moveLen)
bottom.style.height = moveLen + 'px';
}
// 鼠标拖动事件
document.onmousemove = moveHandle
// 鼠标松开事件
resize.onmouseup = document.onmouseup = function (evt) {
//颜色恢复
resize.style.background = '#d6d6d6';
document.onmousemove = null;
document.onmouseup = null;
resize.releaseCapture && resize.releaseCapture(); //当你不在需要继续获得鼠标消息就要应该调用ReleaseCapture()释放掉
};
resize.setCapture && resize.setCapture(); //该函数在属于当前线程的指定窗口里设置鼠标捕获
return false;
};
}
</script>
</head>
<body>
<div class="box" ref="box">
<div class="bottom">
<!--底部div内容-->
<iframe src="http://www.baidu.com" width="100%" height="100%" style="margin-top: 10px; border: none;"></iframe>
</div>
<div class="resize" title="收缩底边栏"></div>
</div>
</body>
</html>
解决方案:这个问题给出的解决方案是,当鼠标按下去准备拖动分割线的时候,出现一个半透明的遮盖层,这个遮盖层的z-index比较高,那么鼠标在移动的时候其实是在这个遮盖层之上移动,这样就会触发mousemove。
最终代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
html, body { height: 100%; width: 100%; }
/* 拖拽相关样式 */
.box {
width: 100%;
height: 100%;
overflow: hidden;
box-shadow: -1px 9px 10px 3px rgba(0, 0, 0, 0.11);
}
/*底部div样式*/
.bottom {
position: absolute;
bottom: 0;
height: 200px;
width: 100%;
background: #fff;
}
/*拖拽区div样式*/
.resize {
position: absolute;
bottom: 200px;
height: 8px;
width: 100%;
color: #fff;
background-color: #eaeaea;
border-radius: 5px;
cursor: row-resize;
}
/*拖拽区鼠标悬停样式*/
.resize:hover {
color: #eaeaea;
}
.mask {
position: absolute;
/* height: 8px; */
width: 100%;
left: 0;
top: -7px;
z-index: 999;
color: red;
text-align: center;
}
.resize:hover .mask {
color: blue;
}
</style>
<script>
/*
遇到的问题:最初写的时候,发现鼠标拖动分割线经过左右两边的iframe的时候就不灵了。
这个问题给出的解决方案是:当鼠标按下去准备拖动分割线的时候,出现一个半透明的遮盖层,这个遮盖层的z-index比较高,那么鼠标在移动的时候其实是在这个遮盖层之上移动,这样就会触发mousemove。
*/
function throttle(func, wait, options) {
var timeout, context, args, result;
var previous = 0;
if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : new Date().getTime();
timeout = null;
func.apply(context, args);
if (!timeout) context = args = null;
};
var throttled = function() {
var now = new Date().getTime();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
};
throttled.cancel = function() {
clearTimeout(timeout);
previous = 0;
timeout = null;
}
return throttled;
}
window.onload = function () {
var resize = document.getElementsByClassName('resize')[0];
var mask = document.getElementsByClassName('mask')[0];
var bottom = document.getElementsByClassName('bottom')[0];
var box = document.getElementsByClassName('box')[0];
resize.onmousedown = function (e) {
var startY = e.clientY;
mask.style.height = '300px';
mask.style.background = 'transparent';
console.log('bottom.offsetHeight: ' + bottom.offsetHeight)
resize.bottom = bottom.offsetHeight;
function moveHandle (e) {
var endY = e.clientY;
var clientHeight = document.documentElement.clientHeight || document.body.clientHeight
var moveLen = resize.bottom + (startY - endY);
if (moveLen > clientHeight) {
moveLen = clientHeight
}
if (moveLen < 10) {
moveLen = 0
}
resize.style.bottom = moveLen + 'px';
bottom.style.height = moveLen + 'px';
}
document.onmousemove = throttle(moveHandle, 10)
resize.onmouseup = document.onmouseup = function (evt) {
mask.style.height = '8px';
document.onmousemove = null;
document.onmouseup = null;
resize.releaseCapture && resize.releaseCapture(); //当你不在需要继续获得鼠标消息就要应该调用ReleaseCapture()释放掉
};
resize.setCapture && resize.setCapture(); //该函数在属于当前线程的指定窗口里设置鼠标捕获
return false;
};
}
</script>
</head>
<body>
<div class="box" ref="box">
<div class="bottom">
<!--底部div内容-->
<iframe src="http://www.baidu.com" width="100%" height="100%" style="margin-top: 10px; border: none;"></iframe>
</div>
<div class="resize" title="收缩底边栏"><div class="mask">一</div></div>
</div>
</body>
</html>
阿里云解决方案: