Commit d6a4da56 authored by coderTomato's avatar coderTomato

sql编辑页面实现拖动调整宽度

parent ced1f7e2
.root {
position: relative;
display: flex;
//margin: 24px auto;
.left {
height: 100%;
position: relative;
.handler {
position: absolute;
right: 0;
bottom: 0;
width: auto;
height: 100%;
user-select: none;
color: #fff;
text-align: center;
cursor: ew-resize;
display: flex;
flex-direction: column;
justify-content: center;
}
}
.right {
height: 100%;
}
}
import React, { useRef, useState } from 'react';
import useDraggable from '../../hooks/useDraggable';
import styles from './DraggleLayout.less';
function DraggleLayout({
children, // 两列布局
min = 0, // 左侧最小宽度
max = Infinity, // 左侧最大宽度
containerWidth = 0, // 容器宽度
containerHeight = 0, // 容器高度
initLeftWidth = 0, // 初始左侧容器宽度
handler = null, // 拖拽器
onWidthChange = width => width, // 左侧容器高度变化
}) {
const ref = useRef(null);
const [position, setPosition] = useState({ x: initLeftWidth, y: 0 });
const [props] = useDraggable(
ref,
{
onMouseMove: ({ x, y }) => {
let _x = x;
if (_x < min) _x = min;
if (_x > max) _x = max;
if (onWidthChange) onWidthChange(_x);
setPosition({ x: _x, y });
},
},
{ overbound: false },
);
const _handler = handler ? (
React.cloneElement(handler, {
...handler.props,
style: {
...handler.props.style,
pointerEvents: 'none',
},
})
) : (
<span style={{ fontSize: 18, pointerEvents: 'none' }}></span>
);
return (
<div
ref={ref}
className={styles.root}
style={{ width: containerWidth, height: containerHeight }}
>
<div className={styles.left} style={{ width: position.x }}>
{children[0]}
<div className={styles.handler} {...props}>
{_handler}
</div>
</div>
<div
className={styles.right}
style={{ width: containerWidth - position.x }}
>
{children[1]}
</div>
</div>
);
}
export default DraggleLayout;
import DraggleLayout from './DraggleLayout';
export default DraggleLayout;
import React from "react";
import {connect} from "umi";
import styles from './index.less';
import {} from "@ant-design/icons";
import StudioMenu from "./StudioMenu";
import {Row, Col, Card, Form,BackTop} from "antd";
import StudioTabs from "./StudioTabs";
......@@ -16,6 +14,7 @@ import {
showClusterConfiguration, showSessionCluster, showJars
} from "@/components/Studio/StudioEvent/DDL";
import {loadSettings} from "@/pages/Settings/function";
import DraggleLayout from "@/components/DraggleLayout";
type StudioProps = {
rightClickMenu:StateType['rightClickMenu'];
......@@ -45,15 +44,68 @@ const Studio: React.FC<StudioProps> = (props) => {
};
return (
// <div onClick={onClick} style={{'margin':'-24px'}}>
// <StudioMenu form={form}/>
// <Card bordered={false} className={styles.card} size="small" id="studio_card">
// <Row>
// <Col span={4} className={styles["vertical-tabs"]}>
// <StudioLeftTool/>
// </Col>
// <Col span={16}>
// <StudioTabs/>
// </Col>
// <Col span={4} className={styles["vertical-tabs"]}>
// <StudioRightTool form={form}/>
// </Col>
// </Row>
// <Row>
// <Col span={24}>
// <StudioConsole/>
// </Col>
// </Row>
// </Card>
// <BackTop />
// </div>
<div onClick={onClick} style={{'margin':'-24px'}}>
<StudioMenu form={form}/>
<Card bordered={false} className={styles.card} size="small" id="studio_card">
<Row>
<Col span={4} className={styles["vertical-tabs"]}>
<StudioLeftTool/>
</Col>
<Col span={16}>
<StudioTabs/>
<Col>
<DraggleLayout
containerWidth={1100}
containerHeight={1220}
min={50}
max={600}
initLeftWidth={200}
handler={
<div
style={{
width: 4,
height: '100%',
background: 'rgb(77, 81, 100)',
}}
/>
}
>
<StudioLeftTool span={4} className={styles["vertical-tabs"]} style={{
backgroundColor: `rgb(36, 205, 208)`,
color: `#fff`,
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}/>
<StudioTabs
style={{
backgroundColor: `rgb(116, 140, 253)`,
color: `#fff`,
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
/>
</DraggleLayout>
</Col>
<Col span={4} className={styles["vertical-tabs"]}>
<StudioRightTool form={form}/>
......
import { useRef } from 'react';
import { off, on } from '../utils/dom';
import useMount from './useMount'
/**
* @hook useDraggable
* @desc 使得DOM变得可拖拽
* @at 2020/09/22
* @by lmh
* */
// 拖拽的初始位置
const initPosition = { x: 0, y: 0 };
// 默认的配置,默认允许拖拽元素溢出容器
const defaultOptions = { overbound: true };
// 当前触发mouseDown的元素,由于mouseUp 绑定在window
// eventCallback 会触发到其他使用 useDraggable 的元素
let currentTarget = null;
const useDraggable = (
container, // 容器,可以是ref.current|dom| 拖拽元素的父元素(默认)
{ onMouseDown, onMouseUp, onMouseMove }, // callback
{ overbound } = defaultOptions, // 是否支持拖拽溢出容器,默认是允许,
) => {
const isDragging = useRef(null);
const ref = useRef(null);
useMount(() => {
const mouseMove = e => {
if (ref.current === currentTarget) {
if (isDragging.current) {
if (onMouseMove) {
// ref.current | dom | 拖拽元素的父元素
const roots =
container?.current ?? container ?? ref.current.parentNode;
let x = e.clientX - initPosition.x;
let y = e.clientY - initPosition.y;
// 是否允许 拖拽位置脱离边界
if (!overbound) {
if (x < 0) x = 0;
if (y < 0) y = 0;
const { clientWidth: pWidth, clientHeight: pHeight } = roots;
const {
clientWidth: cWidth,
clientHeight: cHeight,
} = ref.current;
if (x + cWidth > pWidth) x = pWidth - cWidth;
if (y + cHeight > pHeight) y = pHeight - cHeight;
}
onMouseMove({ x, y });
}
}
}
};
const mouseUp = e => {
if (ref.current === currentTarget) {
isDragging.current = false;
if (onMouseUp) onMouseUp(e);
}
};
on(window, 'mousemove', mouseMove);
on(window, 'mouseup', mouseUp);
return () => {
off(window, 'mousemove', mouseMove);
off(window, 'mouseup', mouseUp);
};
});
const props = {
ref,
onMouseDown: e => {
isDragging.current = true;
const target = e.target || e.srcElement;
// 缓存此次触发事件的元素
currentTarget = target;
// offsetLeft 返回与最近定位的元素(或者body)的左边缘距离
// clientX 鼠标事件点击的x轴位置
initPosition.x = e.clientX - target.offsetLeft;
initPosition.y = e.clientY - target.offsetTop;
if (onMouseDown) onMouseDown(e);
},
};
return [props, isDragging];
};
export default useDraggable;
import { useEffect } from 'react';
/**
* @hook useMount
* @desc ComponentDidMount likes
* */
const useMount = callback => {
useEffect(callback, []);
};
export default useMount;
......@@ -69,6 +69,7 @@ const DataBaseTableList: React.FC<{}> = (props: any) => {
renderItem={(row) => {
return (
<Card
style={{width: 300}}
hoverable={true}
bodyStyle={cardBodyStyle}
......
export function addClassName(el, className) {
if (el.classList) {
el.classList.add(className);
} else {
if (!el.className.match(new RegExp(`(?:^|\\s)${className}(?!\\S)`))) {
el.className += ` ${className}`;
}
}
}
export function getEventPosition(container = document.body, event) {
const rect = container.getBoundingClientRect();
const position = {
x: event.clientX - rect.left,
y: event.clientY - rect.top,
};
return position;
}
export function removeClassName(el, className) {
if (el.classList) {
el.classList.remove(className);
} else {
el.className = el.className.replace(
new RegExp(`(?:^|\\s)${className}(?!\\S)`, 'g'),
'',
);
}
}
export function clearClassName(el) {
el.className = '';
}
export const on = (target, event, ...args) =>
target.addEventListener(event, ...args);
export const off = (target, event, ...args) =>
target.removeEventListener(event, ...args);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment