Skip to content
Go back

react宽度可拖拽组件

Updated:  at  11:44 AM

了解拖拽之前先了解两个api

element.setCaptureelement.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;
    }
}


Previous Post
Astro 优雅的起飞!
Next Post
React源码学习