Commit b7bcf014 by zhaochengxiang

模型字段拖动自动滚动

parent 49e332c5
/*------------------------------------------------*/
/* LIBRARIES
/*------------------------------------------------*/
import throttle from "lodash/throttle";
/*------------------------------------------------*/
/* CONSTANTS
/*------------------------------------------------*/
const OFFSET = 1; // This is the top/bottom offset you use to start scrolling in the div.
const PX_DIFF = 1;
/*------------------------------------------------*/
/* GLOBAL VARIABLES
/*------------------------------------------------*/
let scrollIncrement = 0;
let isScrolling = false;
let sidebarElement = null;
let scrollHeightSidebar = 0;
let clientRectBottom = 0;
let clientRectTop = 0;
/*------------------------------------------------*/
/* METHODS
/*------------------------------------------------*/
/**
* Scroll up in the sidebar.
*/
const goUp = () => {
scrollIncrement -= PX_DIFF;
sidebarElement.scrollTop = scrollIncrement;
if (isScrolling && scrollIncrement >= 0) {
window.requestAnimationFrame(goUp);
}
};
/**
* Scroll down in the sidebar.
*/
const goDown = () => {
scrollIncrement += PX_DIFF;
sidebarElement.scrollTop = scrollIncrement;
if (isScrolling && scrollIncrement <= scrollHeightSidebar) {
window.requestAnimationFrame(goDown);
}
};
const onDragOver = (event) => {
const isMouseOnTop =
scrollIncrement >= 0 &&
event.clientY > clientRectTop &&
event.clientY < clientRectTop + OFFSET;
const isMouseOnBottom =
scrollIncrement <= scrollHeightSidebar &&
event.clientY > clientRectBottom - OFFSET &&
event.clientY <= clientRectBottom;
if (!isScrolling && (isMouseOnTop || isMouseOnBottom)) {
isScrolling = true;
scrollIncrement = sidebarElement.scrollTop;
if (isMouseOnTop) {
window.requestAnimationFrame(goUp);
} else {
window.requestAnimationFrame(goDown);
}
} else if (!isMouseOnTop && !isMouseOnBottom) {
isScrolling = false;
}
};
/**
* The "throttle" method prevents executing the same function SO MANY times.
*/
const throttleOnDragOver = throttle(onDragOver, 150);
const addEventListenerForSidebar = (elementId) => {
// In Chrome the scrolling works.
if (navigator.userAgent.indexOf("Chrome") === -1) {
sidebarElement = document.getElementById(elementId);
scrollHeightSidebar = sidebarElement.scrollHeight;
const clientRect = sidebarElement.getBoundingClientRect();
clientRectTop = clientRect.top;
clientRectBottom = clientRect.bottom;
sidebarElement.addEventListener("dragover", throttleOnDragOver);
}
};
const removeEventListenerForSidebar = () => {
isScrolling = false;
if (sidebarElement) {
sidebarElement.removeEventListener("dragover", throttleOnDragOver);
}
};
/*------------------------------------------------*/
/* EXPORTS
/*------------------------------------------------*/
export default {
addEventListenerForSidebar,
removeEventListenerForSidebar
};
...@@ -5,6 +5,7 @@ import { DndProvider, useDrag, useDrop } from 'react-dnd'; ...@@ -5,6 +5,7 @@ import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend'; import { HTML5Backend } from 'react-dnd-html5-backend';
import update from 'immutability-helper'; import update from 'immutability-helper';
import Helper from './Help';
import './ImportActionIndex.less'; import './ImportActionIndex.less';
import { showMessage, highlightSearchContentByTerms } from '../../../../util'; import { showMessage, highlightSearchContentByTerms } from '../../../../util';
...@@ -239,7 +240,13 @@ const DragableBodyRow = ({ index, moveRow, className, style, ...restProps }) => ...@@ -239,7 +240,13 @@ const DragableBodyRow = ({ index, moveRow, className, style, ...restProps }) =>
const [, drag] = useDrag( const [, drag] = useDrag(
() => ({ () => ({
type, type,
item: { index }, item: () => {
Helper.addEventListenerForSidebar("containerId");
return { index };
},
end: (_, __) => {
Helper.removeEventListenerForSidebar();
},
collect: monitor => ({ collect: monitor => ({
isDragging: monitor.isDragging(), isDragging: monitor.isDragging(),
}), }),
...@@ -603,18 +610,36 @@ const ImportActionIndex = (props) => { ...@@ -603,18 +610,36 @@ const ImportActionIndex = (props) => {
return hasValidateReports ? includeValidateColumn : columns; return hasValidateReports ? includeValidateColumn : columns;
} }
//解决拖动自动滚动问题
//https://codesandbox.io/s/react-dnd-example-12-s3nnf
let pendingUpdateFn = undefined;
let requestedFrame = undefined;
const drawFrame = () => {
const newData = update(data, pendingUpdateFn);
onChange && onChange(newData);
pendingUpdateFn = undefined;
requestedFrame = undefined;
};
const scheduleUpdate = (updateFn) => {
pendingUpdateFn = updateFn;
if (!requestedFrame) {
requestedFrame = requestAnimationFrame(drawFrame);
}
}
const moveRow = useCallback( const moveRow = useCallback(
(dragIndex, hoverIndex) => { (dragIndex, hoverIndex) => {
const dragRow = data[dragIndex]; const dragRow = data[dragIndex];
const newData = update(data, { scheduleUpdate({
$splice: [ $splice: [
[dragIndex, 1], [dragIndex, 1],
[hoverIndex, 0, dragRow], [hoverIndex, 0, dragRow],
], ],
}); });
onChange && onChange(newData);
}, },
//eslint-disable-next-line react-hooks/exhaustive-deps //eslint-disable-next-line react-hooks/exhaustive-deps
[data], [data],
...@@ -653,7 +678,7 @@ const ImportActionIndex = (props) => { ...@@ -653,7 +678,7 @@ const ImportActionIndex = (props) => {
editable && <Button className='ml-3' type="primary" onClick={onAddClick} disabled={ editingKey!==null || keyword!=='' } >新增索引</Button> editable && <Button className='ml-3' type="primary" onClick={onAddClick} disabled={ editingKey!==null || keyword!=='' } >新增索引</Button>
} }
</div> </div>
<div className='content'> <div id="containerId">
<DndProvider backend={HTML5Backend} > <DndProvider backend={HTML5Backend} >
<Form form={form} component={false} onValuesChange={onValuesChange}> <Form form={form} component={false} onValuesChange={onValuesChange}>
<Table <Table
......
.model-import-action-index { .model-import-action-index {
.content { .yy-table {
max-height: 200px !important; max-height: 200px !important;
overflow: auto !important; overflow: auto !important;
} }
......
...@@ -7,7 +7,7 @@ import update from 'immutability-helper'; ...@@ -7,7 +7,7 @@ import update from 'immutability-helper';
import { generateUUID, highlightSearchContentByTerms, showMessage } from '../../../../util'; import { generateUUID, highlightSearchContentByTerms, showMessage } from '../../../../util';
import { dispatchLatest } from '../../../../model'; import { dispatchLatest } from '../../../../model';
import Helper from './Help';
import './ImportActionTable.less'; import './ImportActionTable.less';
const { Option } = Select; const { Option } = Select;
...@@ -202,7 +202,13 @@ const DragableBodyRow = ({ index, moveRow, className, style, ...restProps }) => ...@@ -202,7 +202,13 @@ const DragableBodyRow = ({ index, moveRow, className, style, ...restProps }) =>
const [, drag] = useDrag( const [, drag] = useDrag(
() => ({ () => ({
type, type,
item: { index }, item: () => {
Helper.addEventListenerForSidebar("containerId");
return { index };
},
end: (_, __) => {
Helper.removeEventListenerForSidebar();
},
collect: monitor => ({ collect: monitor => ({
isDragging: monitor.isDragging(), isDragging: monitor.isDragging(),
}), }),
...@@ -694,18 +700,36 @@ const ImportActionTable = (props) => { ...@@ -694,18 +700,36 @@ const ImportActionTable = (props) => {
return hasValidateReports ? includeValidateColumn : columns; return hasValidateReports ? includeValidateColumn : columns;
} }
//解决拖动自动滚动问题
//https://codesandbox.io/s/react-dnd-example-12-s3nnf
let pendingUpdateFn = undefined;
let requestedFrame = undefined;
const drawFrame = () => {
const newData = update(data, pendingUpdateFn);
onChangeRef.current && onChangeRef.current(newData);
pendingUpdateFn = undefined;
requestedFrame = undefined;
};
const scheduleUpdate = (updateFn) => {
pendingUpdateFn = updateFn;
if (!requestedFrame) {
requestedFrame = requestAnimationFrame(drawFrame);
}
}
const moveRow = useCallback( const moveRow = useCallback(
(dragIndex, hoverIndex) => { (dragIndex, hoverIndex) => {
const dragRow = data[dragIndex]; const dragRow = data[dragIndex];
const newData = update(data, { scheduleUpdate({
$splice: [ $splice: [
[dragIndex, 1], [dragIndex, 1],
[hoverIndex, 0, dragRow], [hoverIndex, 0, dragRow],
], ],
}); });
onChangeRef.current && onChangeRef.current(newData);
}, },
//eslint-disable-next-line react-hooks/exhaustive-deps //eslint-disable-next-line react-hooks/exhaustive-deps
[data], [data],
...@@ -744,7 +768,7 @@ const ImportActionTable = (props) => { ...@@ -744,7 +768,7 @@ const ImportActionTable = (props) => {
editable && <Button className='ml-3' type="primary" onClick={onAddClick} disabled={ editingKey!=='' || keyword!=='' } >新增字段</Button> editable && <Button className='ml-3' type="primary" onClick={onAddClick} disabled={ editingKey!=='' || keyword!=='' } >新增字段</Button>
} }
</div> </div>
<div className='content'> <div id="containerId">
<DndProvider backend={HTML5Backend} > <DndProvider backend={HTML5Backend} >
<Form form={form} component={false} onValuesChange={onValuesChange}> <Form form={form} component={false} onValuesChange={onValuesChange}>
<Table <Table
......
.model-import-action-table { .model-import-action-table {
.content { .yy-table {
max-height: 400px !important; max-height: 400px !important;
overflow: auto !important; overflow: auto !important;
} }
......
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