vlambda博客
学习文章列表

react中原生js实现左右拖动和上下拖动

昨天晚上杭州的雨可真大啊

淌水回家路~漫~漫~~   

jsx:

import React, { Component } from 'react';import _ from 'underscore';import styles from './index.css';
// 可调整宽高的Divexport default class ResizeDiv extends Component { state = { isHResize: false, isVResize: false, hNum: 100, vNum: 500, hNumLimit: 30, vNumLimit: 30,  }; resizeOffsetInfo = { clientTop: 0, clientLeft: 0,  };  leftHeight = 0;  containerWidth = 0;  componentDidMount() { this.initResizeInfo(); const throttled = _.throttle(() => { this.initResizeInfo(); }, 200);
window.onresize = throttled; } componentWillUnmount() { window.onresize = null; }
/** * 初始化resize信息 */ initResizeInfo = () => { const hEle = document.getElementById('h_resize_container'); this.resizeOffsetInfo = this.getEleOffset(hEle); this.leftHeight = hEle.offsetHeight; this.containerWidth = document.getElementById('v_resize_container').offsetWidth; };
/** * 获取元素的偏移信息 */ getEleOffset(ele) { var clientTop = ele.offsetTop; var clientLeft = ele.offsetLeft; let current = ele.offsetParent; while (current !== null) { clientTop += current.offsetTop; clientLeft += current.offsetLeft; current = current.offsetParent; } return { clientTop, clientLeft, height: ele.offsetHeight, width: ele.offsetWidth, }; }
/** * 开始拖动水平调整块 */ hResizeDown = () => { this.setState({ isHResize: true, }); };
/** * 拖动水平调整块 */ hResizeOver = e => { const { isHResize, hNum, hNumLimit } = this.state; if (isHResize && hNum >= hNumLimit && this.resizeOffsetInfo.height - hNum >= hNumLimit) { let newValue = this.resizeOffsetInfo.clientTop + this.resizeOffsetInfo.height - e.clientY; if (newValue < hNumLimit) { newValue = hNumLimit; } if (newValue > this.resizeOffsetInfo.height - hNumLimit) { newValue = this.resizeOffsetInfo.height - hNumLimit; } this.setState({ hNum: newValue, }); } };
/** * 开始拖动垂直调整块 */ vResizeDown = () => { this.setState({ isVResize: true, }); };
/** * 拖动垂直调整块 */ vResizeOver = e => { const { isVResize, vNum, vNumLimit } = this.state; if (isVResize && vNum >= vNumLimit && this.containerWidth - vNum >= vNumLimit) { let newValue = e.clientX - this.resizeOffsetInfo.clientLeft; if (newValue < vNumLimit) { newValue = vNumLimit; } if (newValue > this.containerWidth - vNumLimit) { newValue = this.containerWidth - vNumLimit; } this.setState({ vNum: newValue, }); } };
/** * 只要鼠标松开或者离开区域,那么就停止resize */ stopResize = () => { this.setState({ isHResize: false, isVResize: false, }); };
render() { const hCursor = this.state.isHResize ? 'row-resize' : 'default'; const hColor = this.state.isHResize ? '#ddd' : '#fff'; const vCursor = this.state.isVResize ? 'col-resize' : 'default'; const vColor = this.state.isVResize ? '#ddd' : '#fff';
return ( <div className={styles['container']} onMouseUp={this.stopResize} onMouseLeave={this.stopResize} > <div id="v_resize_container" className={styles['content']} onMouseMove={this.vResizeOver}> <div id="h_resize_container" style={{ width: this.state.vNum, cursor: vCursor }} className={styles['left']} onMouseMove={this.hResizeOver} > <div style={{ bottom: this.state.hNum, cursor: hCursor }} className={styles['left-top']} > 一一一一一一一 </div> <div style={{ bottom: this.state.hNum, backgroundColor: hColor }} draggable={false} onMouseDown={this.hResizeDown} className={styles['h-resize']} /> <div style={{ height: this.state.hNum + 4, cursor: hCursor }} className={styles['left-bottom']} > 二二二二二二二二二 </div> </div> <div style={{ left: this.state.vNum, backgroundColor: vColor }} draggable={false} onMouseDown={this.vResizeDown} className={styles['v-resize']} /> <div style={{ marginLeft: this.state.vNum + 4, cursor: vCursor }} className={styles['right']} > 三三三三三三三三 </div> </div> </div> ); }}

css:

.container{ margin: 30px; overflow: hidden; position: absolute; top: 0; left: 0; bottom: 0; right: 0; }  .content{ position: absolute; top: 0; left: 0; bottom: 0; right: 0; min-height: 300px; }  .left{ width: 500px; height: 100%; float: left; position: relative; }  .left-top{ position: absolute; top: 0; bottom: 104px; width: 100%; background-color: lightblue; }  .h-resize{ height: 4px; width: 100%; background: #fff; position: absolute; bottom: 100px; z-index: 1; cursor: row-resize; user-select: none; }  .left-bottom{ position: absolute; bottom: 0; width: 100%; height: 100px; background-color: lightgreen; }  .v-resize{ height: 100%; width: 4px; position: absolute; background: #fff; left: 500px; z-index: 2; cursor: col-resize; user-select: none; }  .right{ margin-left: 504px; background-color: lightsalmon; height: 100%; }