了解拖拽之前先了解两个api
element.setCapture
和 element.releaseCapture
setCapture: 在处理一个 mousedown 事件过程中调用这个方法来把全部的鼠标事件重新定向到这个元素,直到鼠标按钮被释放或者 document.releaseCapture() 被调用。 releaseCapture: 如果该 document 中的一个元素之上当前启用了鼠标捕获,则释放鼠标捕获
核心逻辑
import React, { Component } from 'react';
import './index.scss';
import { Card, Icon, Input, Layout } from 'antd';
const { Sider, Content } = Layout;
let dragBtn, dragDom, dragCollDom;
export default class SelectDept extends Component {
componentDidMount() {
this.setSiderWidth();
}
// 设置侧边栏宽度
setSiderWidth = () => {
dragBtn = document.getElementById('drag-tip');
dragDom = document.getElementById('drag-area');
dragCollDom = document.getElementById('collapse_sider');
var siderWidth = Number(window.localStorage.getItem(this.props.SiderWidthDivide));
if (siderWidth == 0) {
this.setMaxValue(256);
} else {
if (siderWidth < 256) {
this.setMinValue(32);
} else {
this.setMaxValue(siderWidth);
}
};
}
isIE = () => navigator.userAgent.toLowerCase().indexOf('trident') > -1 ? true : false;
MouseDown = (e) => {
// 鼠标的X轴坐标
let clientX = e.clientX;
// 拖动块距离屏幕左侧的偏移量
let offsetLeft = dragBtn.offsetLeft;
// 鼠标移动
document.onmousemove = (e) => {
let curDist = offsetLeft + (e.clientX - clientX), // 拖动块的移动距离
maxDist = 700; // 拖动块的最大移动距离
// 边界值处理
if (curDist < 243) {
// 设置值(保证拖动块一直在拖动盒子的相对位置)
curDist < 32 && (curDist = 32);
this.setMinValue(curDist);
return false
}
curDist > maxDist && (curDist = maxDist);
this.setMaxValue(curDist);
return false;
};
// 鼠标松开
document.onmouseup = (e) => {
let curDist = offsetLeft + (e.clientX - clientX); // 拖动块的移动距离
if (curDist < 243) {
this.setMinValue(32);
}
document.onmousemove = null;
document.onmouseup = null;
// 释放鼠标
dragBtn.releaseCapture && dragBtn.releaseCapture();
};
// 捕获鼠标
dragBtn.setCapture && dragBtn.setCapture();
return false;
};
setMinValue = (curDist) => {
window.localStorage.setItem(this.props.SiderWidthDivide, '32');
if (this.isIE()) {
dragBtn.style.cssText = `left:${curDist}px;`;
dragCollDom.style.cssText = `flex:0 0 ${curDist}px;width:${curDist}px`;
dragDom.style.cssText = 'flex:0 0 0px;width:0px';
} else {
dragBtn.style.left = dragCollDom.style.width = curDist + 'px';
dragCollDom.style.flex = `0 0 ${curDist}px`;
dragDom.style.flex = '0 0 0px';
dragDom.style.width = '0px';
}
}
setMaxValue = (curDist) => {
window.localStorage.setItem(this.props.SiderWidthDivide, curDist);
// 设置值(保证拖动块一直在拖动盒子的相对位置)
if (this.isIE()) {
dragBtn.style.cssText = `left:${curDist}px;`;
dragDom.style.cssText = `flex:0 0 ${curDist}px;width:${curDist}px`;
dragCollDom.style.cssText = 'flex:0 0 0px;width:0px';
} else {
dragBtn.style.left = dragDom.style.width = curDist + 'px';
dragDom.style.flex = `0 0 ${curDist}px`;
dragCollDom.style.flex = '0 0 0px';
dragCollDom.style.width = '0px';
}
}
render() {
const { nodeClick, children, urlMatch,moreAction } = this.props;
return (
<Layout id="drag-content" >
<div id="collapse_sider" style={{ width: 0 }} >
<div id="collapse_sider_box">
<div className="base">左<br />侧<br />菜<br />单</div>
<Icon className="collapse_icon"
type="iconfont iconzhankai2"
onClick={() => this.setMaxValue(256)}
/>
</div>
</div>
<Sider id="drag-area" className="sider" >
<div className="whiteBox">
树状组件
</div>
</Sider>
<div id="drag-tip" onMouseDown={this.MouseDown}>
<Icon className="drag_icon" type="iconfont icontuozhuai" />
</div>
<Layout style={{ paddingLeft: 24, overflowY: 'auto' }}>
<Content>
<Card bordered={false}>
{children}
</Card>
</Content>
</Layout>
</Layout>
);
}
}
样式
@import "src/scss/variables";
#drag-content {
position: relative;
height: calc(100vh - 180px);
background: none;
.ant-layout {
background: none;
}
/*鼠标移入显示可拖动样式*/
#drag-tip {
top: 0;
width: 24px;
left: 256px;
height: 100%;
position: absolute;
background-color: transparent;
z-index: 1000;
transition: all 0s;
.drag_icon {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%);
font-size: 13px;
color: rgba(216, 216, 216, 1);
}
&:hover {
cursor: col-resize;
}
}
.sider {
box-shadow: none;
max-width: initial !important;
min-width: initial !important;
transition: all 0s;
background: rgba(238, 240, 243, 1);
.ant-layout-sider-children {
overflow: hidden;
}
}
#collapse_sider {
background: rgba(238, 240, 243, 1);
#collapse_sider_box {
position: relative;
height: 100%;
overflow: hidden;
}
.base {
position: absolute;
width: 100%;
top: 50%;
transform: translateY(-50%);
text-align: center;
}
.collapse_icon {
position: absolute;
width: 100%;
bottom: 10px;
text-align: center;
font-size: 12px;
color: #577ac7;
cursor: pointer;
}
}
.whiteBox {
width: 100%;
height: 100%;
padding: 0px 8px;
background-color: #eef0f3;
transition: width 0.3s;
overflow: hidden;
}
}