Commit 459f426a authored by zhangwenshuai's avatar zhangwenshuai

增加右侧拖拽

parent b60f523c
......@@ -19,23 +19,36 @@ const DragSorted = (props: any) => {
const divider: any = document.querySelector('#divider');
// 左侧固定列分割线
const leftFixedHandleWrap: any = document.querySelector('#leftFixedHandleWrap');
const rightFixedHandleWrap: any = document.querySelector('#rightFixedHandleWrap');
// 监听鼠标移动
const onMouseMove = useCallback((e) => {
const tableRect = container.getBoundingClientRect();
const detaX = columnCopyDiv.getAttribute('data-deta-x');
// 所有列
const draggableColumns = document.querySelectorAll('.draggableColumn');
const leftFixedHandleWrapRect = leftFixedHandleWrap.getBoundingClientRect();
const leftFixedHandleWrapRectX = (leftFixedHandleWrap && leftFixedHandleWrap.getBoundingClientRect().x) || 0;
const rightFixedHandleWrapRectX = (rightFixedHandleWrap && rightFixedHandleWrap.getBoundingClientRect().x) || tableRect.right;
const columnCopyDivRect = columnCopyDiv.getBoundingClientRect();
const columnCopyDivWidth = columnCopyDivRect.width;
const columnCopyDivX = columnCopyDivRect.x;
// 影子div中间点的x坐标
const columnCopyDivMid = columnCopyDivX + columnCopyDivWidth / 2;
const left = e.clientX - tableRect.x - Number(detaX);
// 影子div随鼠标移动
// 鼠标在左侧固定列与右侧固定列之间有效
if (e.clientX > leftFixedHandleWrapRectX && e.clientX < rightFixedHandleWrapRectX) {
columnCopyDiv.style.left = `${left}px`;
}
draggableColumns.forEach((dom) => {
const domRect = dom.getBoundingClientRect();
if (columnCopyDivMid > domRect.x && columnCopyDivMid < domRect.x + domRect.width) {
// 当前节点在左侧固定列与右侧固定列之间有效
if (
domRect.x > leftFixedHandleWrapRectX
&& domRect.x < rightFixedHandleWrapRectX
&& columnCopyDivMid > domRect.x
&& columnCopyDivMid < domRect.x + domRect.width
) {
// 影子div中点在投放目标中
divider.style.left = `${domRect.x - tableRect.x}px`;
// 收集投放目标的信息
......@@ -46,24 +59,20 @@ const DragSorted = (props: any) => {
}
});
const left = e.clientX - tableRect.x - Number(detaX);
// 影子div随鼠标移动
columnCopyDiv.style.left = `${left}px`;
if (typeof onScroll === 'function') {
let dir = '';
let step = 10;
// 设置鼠标超出表格左右两侧时的滚动事件
if (e.clientX > tableRect.right - 30) {
// 设置鼠标超出表格左右固定列两侧时的滚动事件
if (columnCopyDivX + columnCopyDivWidth > rightFixedHandleWrapRectX - 50) {
dir = 'right';
step = 100;
} else if (e.clientX > tableRect.right - 100) {
} else if (columnCopyDivX + columnCopyDivWidth > rightFixedHandleWrapRectX - 100) {
dir = 'right';
step = 10;
} else if (e.clientX < leftFixedHandleWrapRect.x + 100) {
step = 30;
} else if (columnCopyDivX < leftFixedHandleWrapRectX + 100) {
dir = 'left';
step = 10;
} else if (e.clientX < leftFixedHandleWrapRect.x + 30) {
step = 30;
} else if (columnCopyDivX < leftFixedHandleWrapRectX + 50) {
dir = 'left';
step = 100;
} else {
......
import React from 'react';
import { ResizableBox } from 'react-resizable';
import styles from './DragFixed.less';
const DragFixed = (props: any) => {
const {
initLeft,
initTop,
onResizeStart,
tableWidth,
showColumns,
columnWidth,
columns,
onResizeStop,
scrollbarWidth,
} = props;
// 表格
const container: any = document.querySelector('#tableContainer');
// 滑块wrap
const handleWrap: any = document.querySelector('#rightFixedHandleWrap');
// 滑块
const handle: any = document.querySelector('#rightFixedHandle');
// 分割线wrap
const dividerWrap: any = document.querySelector('#dividerWrap');
// 分割线
const divider: any = document.querySelector('#divider');
const onMouseEnterWrap = (e: any) => {
// 滑块wrap添加hovered样式
handleWrap.classList.add(styles.hovered);
// 滑块初始化位置,显示
handle.style.top = `${e.clientY}px`;
handle.style.opacity = 1;
};
const onMouseMoveWrap = (e: any) => {
// 滑块位置跟随鼠标上下移动
handle.style.top = `${e.clientY}px`;
};
const onMouseLeaveWrap = () => {
// 滑块wrap移除hovered样式
handleWrap.classList.remove(styles.hovered);
// 滑块隐藏
handle.style.opacity = 0;
};
const onResizeStartHandle = (e: any) => {
if (typeof onResizeStart === 'function') {
onResizeStart();
}
const originLeft = container.getBoundingClientRect().x || 0;
handleWrap.style.top = 0;
handleWrap.style.left = `${e.x - originLeft}px`;
};
const onResizeHandle = (e: any) => {
const containerRect: any = container.getBoundingClientRect();
let inTableRight = containerRect.right - e.x;
// left不能超过表格一半宽度
if (inTableRight > tableWidth / 2) {
inTableRight = tableWidth / 2;
}
let fixedWidth = 0;
let index = 0;
// 计算固定列宽度及索引
for (let i = showColumns.length - 1; i >= 0; i--) {
fixedWidth += showColumns[i].width || columnWidth;
if (fixedWidth > inTableRight) {
index = i;
break;
}
}
let rightHandleLeft = fixedWidth - (showColumns[index].width || columnWidth);
// if (inTableRight > fixedWidth - (showColumns[index].width || columnWidth) / 2) {
// // left位于当前列中间偏右
// rightHandleLeft = fixedWidth;
// } else {
// // left位于当前列中间偏左
// rightHandleLeft = fixedWidth - (showColumns[index].width || columnWidth);
// }
// 拖动时显示分割线
dividerWrap.style.display = 'block';
// 分割线取列的边侧位置
divider.style.left = `${containerRect.width - scrollbarWidth - rightHandleLeft}px`;
// 拖动线取鼠标位置
handleWrap.style.left = `${containerRect.width - scrollbarWidth - inTableRight}px`;
// 滑动过程中滑块始终显示
// 滑块wrap添加hovered样式
handleWrap.classList.add(styles.hovered);
// 滑块初始化位置,显示
handle.style.opacity = 1;
};
const onResizeStopHandle = () => {
// 当前固定列宽度为分割线的left
const fixedWidth: string = divider.style.left;
// 样式转数值
const fixedWidthNum: string = fixedWidth.slice(0, -2);
// 分隔线wrap隐藏
dividerWrap.style.display = 'none';
// 滑块wrap移除hovered样式
handleWrap.classList.remove(styles.hovered);
handleWrap.style.top = `${initTop}px`;
handleWrap.style.left = fixedWidth;
// 滑块隐藏
handle.style.opacity = 0;
let leftFixedWidth = 0;
const fixedCol: any = {};
// 计算获取固定列
for (let i = showColumns.length - 1; i >= 0; i--) {
leftFixedWidth += showColumns[i].width || columnWidth;
if (leftFixedWidth <= tableWidth + scrollbarWidth - Number(fixedWidthNum)) {
fixedCol[showColumns[i].columnName] = 1;
} else {
break;
}
}
const newColumns: any = [];
// 为固定列增加fixed属性
columns.map((item: any) => {
if (fixedCol[item.columnName] === 1) {
item.fixed = 'right';
} else {
if (item.fixed === 'right') {
item.fixed = '';
}
}
newColumns.push(item);
});
if (typeof onResizeStop === 'function') {
onResizeStop({ columns: newColumns });
}
};
return (
<div
id="rightFixedHandleWrap"
className={styles.leftFixedHandleWrap}
style={{
left: `${initLeft}px`,
top: `${initTop}px`,
}}
onMouseEnter={onMouseEnterWrap}
onMouseMove={onMouseMoveWrap}
onMouseLeave={onMouseLeaveWrap}
>
<ResizableBox
handle={
<span
id="rightFixedHandle"
className={styles.leftFixedHandle}
onClick={(e) => {
e.stopPropagation();
}}
/>
}
onResizeStart={onResizeStartHandle}
onResize={onResizeHandle}
onResizeStop={onResizeStopHandle}
draggableOpts={{ enableUserSelectHack: false }}
/>
</div>
);
};
export default DragFixed;
......@@ -141,7 +141,7 @@
top: 0;
bottom: 0;
background: rgba(0,0,0,0.3);
z-index: 5;
//z-index: 5;
//pointer-events: none;
display: none;
cursor: grab;
......
......@@ -11,6 +11,7 @@ import { TableProps, TableState, ColumnProps, RowProps } from './interface';
import Column from './Column';
import Cell from './Cell';
import LeftDragFixed from './DragFixed';
import RightDragFixed from './RightDragFixed';
import DragSorted from './DragSorted';
import { getMergeClassName, getMergeStyle } from '../utils/utils';
import { Consumer } from './context';
......@@ -266,8 +267,7 @@ export default class AirTable extends Component<TableProps, TableState> {
// 拖拽自定义固定列前置动作
onResizeStartLeftDragFixed = () => {
// 拖动开始,将表格滚动回最左端
if (this.grid3 && this.grid4) {
this.grid3.scrollToPosition({ scrollLeft: 0 });
if (this.grid4) {
this.grid4.scrollToPosition({ scrollLeft: 0 });
}
};
......@@ -283,24 +283,33 @@ export default class AirTable extends Component<TableProps, TableState> {
},
);
};
// 拖拽自定义固定列前置动作
onResizeStartRightDragFixed = () => {
// 拖动开始,将表格滚动回最右端
const { columns } = this.state;
const showColumns = this.memoizeColumns(columns);
if (this.grid4) {
this.grid4.scrollToCell({ columnIndex: showColumns.length - 1 });
}
};
onScrollHor = (direction: string, step: number) => {
// 拖动超过视图范围,将表格左右滚动
if (this.grid4) {
if (direction === 'right') {
if (this.grid4.state.scrollLeft >= this.grid4.getTotalColumnsWidth() - this.state.tableWidth - 100) {
console.log('已经到最右侧了')
console.log('已经到最右侧了');
return;
}
this.grid4.scrollToPosition({ scrollLeft: this.grid4.state.scrollLeft + step });
} else {
if (this.grid4.state.scrollLeft <= 0) {
console.log('已经到最左侧了')
console.log('已经到最左侧了');
return;
}
this.grid4.scrollToPosition({ scrollLeft: this.grid4.state.scrollLeft - step });
}
}
}
};
// 渲染表头
renderHeaderCell = (
{ showColumns, position }: { showColumns: ColumnProps[]; position?: string },
......@@ -320,7 +329,15 @@ export default class AirTable extends Component<TableProps, TableState> {
orderNo,
} = showColumns[columnIndex];
return (
<DragSorted columnName={columnName} orderNo={orderNo} onDropFinish={onDragSorted} onScroll={this.onScrollHor} className={styles.headerCell} key={key} style={style}>
<DragSorted
columnName={columnName}
orderNo={orderNo}
onDropFinish={onDragSorted}
onScroll={this.onScrollHor}
className={styles.headerCell}
key={key}
style={style}
>
<ResizableBox
width={style.width}
handle={
......@@ -458,7 +475,6 @@ export default class AirTable extends Component<TableProps, TableState> {
const scrollbarWidth = scrollbarSize() || 0;
const showColumns = this.memoizeColumns(columns);
const leftColumns = this.memoizeLeftColumns(columns);
const rightColumns = this.memoizeRightColumns(columns);
// 有隐藏列时,修正数据与列头不匹配问题
......@@ -486,7 +502,6 @@ export default class AirTable extends Component<TableProps, TableState> {
<ScrollSync>
{({ onScroll, scrollLeft, scrollTop }: any) => {
return (
<div
className={
this.props.onScroll
......@@ -506,9 +521,7 @@ export default class AirTable extends Component<TableProps, TableState> {
className={styles.leftSideContainer}
style={{
width: `${leftWidth}px`,
height: `${totalHeight -
scrollbarWidth +
headerHeight}px`,
height: `${totalHeight - scrollbarWidth + headerHeight}px`,
}}
>
{
......@@ -599,8 +612,7 @@ export default class AirTable extends Component<TableProps, TableState> {
// 中部表头
<div
style={{
backgroundColor:
'rgba(246, 246, 246, 1)',
backgroundColor: 'rgba(246, 246, 246, 1)',
height: headerHeight,
width,
}}
......@@ -610,28 +622,20 @@ export default class AirTable extends Component<TableProps, TableState> {
this.grid3 = dom;
}}
className={styles.headerGrid}
overscanColumnCount={
overscanColumnCount
}
columnWidth={this.getColumnWidth.bind(
this,
{
columns: showColumns,
showColumns,
},
)}
overscanColumnCount={overscanColumnCount}
columnWidth={this.getColumnWidth.bind(this, {
columns: showColumns,
showColumns,
})}
columnCount={columnCount}
width={width}
rowHeight={headerHeight}
rowCount={1}
height={headerHeight}
scrollLeft={scrollLeft}
cellRenderer={this.renderHeaderCell.bind(
this,
{
showColumns,
},
)}
cellRenderer={this.renderHeaderCell.bind(this, {
showColumns,
})}
/>
</div>
}
......@@ -649,54 +653,39 @@ export default class AirTable extends Component<TableProps, TableState> {
this.grid4 = dom;
}}
className={styles.centerGrid}
overscanColumnCount={
overscanColumnCount
}
overscanRowCount={
overscanRowCount
}
columnWidth={this.getColumnWidth.bind(
this,
{
columns: showColumns,
showColumns,
},
)}
overscanColumnCount={overscanColumnCount}
overscanRowCount={overscanRowCount}
columnWidth={this.getColumnWidth.bind(this, {
columns: showColumns,
showColumns,
})}
columnCount={columnCount}
width={realWidth}
rowHeight={rowHeight}
rowCount={rowCount}
onScroll={(
...arg: Array<Object>
) => {
onScroll={(...arg: Array<Object>) => {
onScroll(...arg);
this.onScroll(arg[0]);
}}
scrollTop={scrollTop}
height={totalHeight}
cellRenderer={this.renderBodyCell.bind(
this,
{
showColumns,
showData,
position: 'center',
},
)}
cellRenderer={this.renderBodyCell.bind(this, {
showColumns,
showData,
position: 'center',
})}
/>
) : (
columnCount > 0 &&
!loading && (
<Empty
className={
styles.defaultEmpty
}
description={
noDataPlaceholder ||
locale.empty
}
/>
)
)}
columnCount > 0 &&
!loading && (
<Empty
className={styles.defaultEmpty}
description={
noDataPlaceholder || locale.empty
}
/>
)
)}
</div>
}
</div>
......@@ -704,14 +693,26 @@ export default class AirTable extends Component<TableProps, TableState> {
}}
</AutoSizer>
</div>
{canFixed && (
<RightDragFixed
initLeft={tableWidth - rightWidth}
initTop={headerHeight}
tableWidth={tableWidth}
showColumns={showColumns}
columnWidth={columnWidth}
columns={columns}
scrollbarWidth={scrollbarWidth}
onResizeStart={this.onResizeStartRightDragFixed}
onResizeStop={this.onResizeStopLeftDragFixed}
/>
)}
{totalWidth > tableWidth && rightCount > 0 && (
<div
className={styles.rightSideContainer}
style={{
width: `${rightWidth}px`,
height: `${totalHeight -
scrollbarWidth +
headerHeight}px`,
height: `${totalHeight - scrollbarWidth + headerHeight}px`,
right: scrollbarWidth,
}}
>
{
......@@ -785,10 +786,7 @@ export default class AirTable extends Component<TableProps, TableState> {
</div>
)}
<div className={styles.fillHandleWrapper} />
<div
className={styles.loading}
style={{ top: `${totalHeight / 2}px` }}
>
<div className={styles.loading} style={{ top: `${totalHeight / 2}px` }}>
{loading && (loadComp ? loadComp : <Spin />)}
</div>
<div
......
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