@antv/s2-react
Version:
use S2 with react
164 lines • 7.55 kB
JavaScript
import { __awaiter } from "tslib";
import { FrozenGroupArea, InteractionStateName, S2Event, S2_PREFIX_CLS, } from '@antv/s2';
import { get, pick, throttle } from 'lodash';
import React, { memo, useEffect, useState } from 'react';
import { useSpreadSheetInstance } from '../../../../context/SpreadSheetContext';
import './drag-copy-mask.less';
export const DragCopyMask = memo(({ onCopyFinished }) => {
const s2 = useSpreadSheetInstance();
const [startCell, setStartCell] = useState();
const [maskPosition, setMaskPosition] = useState({ right: 0, bottom: 0 });
const [dragPoint, setDragPoint] = useState();
const isInCell = (point, cell) => {
const cellMeta = pick(cell.getMeta(), [
'x',
'y',
'width',
'height',
'fieldValue',
]);
const scrollOffset = s2.facet.getScrollOffset();
const sampleColNode = s2.facet.getColNodes()[0];
const sampleColNodeHeight = (sampleColNode === null || sampleColNode === void 0 ? void 0 : sampleColNode.height) || 0;
// 点位偏移
const pointX = point.x;
const pointY = point.y;
const scrollOffsetY = (scrollOffset === null || scrollOffset === void 0 ? void 0 : scrollOffset.scrollY) - sampleColNodeHeight;
const cellMaxX = cellMeta.x - scrollOffset.scrollX + cellMeta.width + 4;
const cellMinX = cellMeta.x - scrollOffset.scrollX;
const cellMaxY = cellMeta.y - scrollOffsetY + cellMeta.height + 4;
const cellMinY = cellMeta.y - scrollOffsetY;
return (cellMaxX >= pointX &&
cellMinX < pointX &&
cellMaxY >= pointY &&
cellMinY < pointY);
};
/** 判断当前位置是否在表格可视区域内 */
const judgePointInView = (point) => {
const rect = s2.getCanvasElement().getBoundingClientRect();
const frozenGroupAreas = s2.facet.frozenGroupAreas;
const viewMinX = rect.x;
const viewMaxX = rect.x + rect.width;
// 减去列头高度
const viewMinY = rect.y + frozenGroupAreas[FrozenGroupArea.Row].height;
const viewMaxY = rect.y + rect.height;
return (point.x <= viewMaxX &&
point.x >= viewMinX &&
point.y <= viewMaxY &&
point.y >= viewMinY);
};
const getCurrentHoverCell = (event) => {
const rect = s2.getCanvasElement().getBoundingClientRect();
const allCells = s2.facet.getDataCells();
return allCells.find((dataCell) => isInCell({ y: event.y - rect.y, x: event.x - rect.x }, dataCell));
};
const getSelectedCellRange = (startCell, endCell) => {
const startCellMeta = startCell.getMeta();
const endCellMeta = endCell === null || endCell === void 0 ? void 0 : endCell.getMeta();
const minX = Math.min(startCellMeta.colIndex, endCellMeta.colIndex);
const maxX = Math.max(startCellMeta.colIndex, endCellMeta.colIndex);
const maxY = Math.max(startCellMeta.rowIndex, endCellMeta.rowIndex);
const minY = Math.min(startCellMeta.rowIndex, endCellMeta.rowIndex);
const allCells = s2.facet.getDataCells();
return allCells.filter((item) => {
const itemMeta = item.getMeta();
return (itemMeta.rowIndex <= maxY &&
itemMeta.rowIndex >= minY &&
itemMeta.colIndex <= maxX &&
itemMeta.colIndex >= minX);
});
};
// 利用闭包记录最近一次hover位置,防止鼠标拖拽越界报错
const lastHoverPoint = { x: 0, y: 0 };
const dragMove = throttle((event) => {
if (!startCell) {
return;
}
let targetCell = getCurrentHoverCell(event);
let newX = event.x - dragPoint.x;
let newY = event.y - dragPoint.y;
// 判断鼠标是否在表格可视区域,不在的话使用最近一次hover位置
if (!judgePointInView(event)) {
targetCell = getCurrentHoverCell(lastHoverPoint);
newX = lastHoverPoint.x - dragPoint.x;
newY = lastHoverPoint.y - dragPoint.y;
}
else {
lastHoverPoint.x = event.x;
lastHoverPoint.y = event.y;
}
setMaskPosition({ right: newX, bottom: newY });
const selectedRange = getSelectedCellRange(startCell, targetCell);
// 更改选中状态
s2.interaction.changeState({
cells: selectedRange.map((v) => v.getMeta()),
stateName: InteractionStateName.PREPARE_SELECT,
force: true,
});
}, 10);
const dragMouseUp = (event) => __awaiter(void 0, void 0, void 0, function* () {
if (!startCell) {
return;
}
const targetCell = getCurrentHoverCell(event) ||
getCurrentHoverCell(lastHoverPoint);
const displayData = s2.dataSet.getDisplayDataSet();
const selectedRange = getSelectedCellRange(startCell, targetCell);
const { fieldValue } = startCell.getMeta();
const changedCells = selectedRange.map((item) => {
const { rowIndex, valueField } = item.getMeta();
if (displayData[rowIndex] &&
typeof displayData[rowIndex][valueField] !== 'undefined') {
displayData[rowIndex][valueField] = fieldValue;
}
return item;
});
// 更改选中状态
s2.interaction.changeState({
cells: changedCells.map((v) => v.getMeta()),
stateName: InteractionStateName.PREPARE_SELECT,
force: true,
});
yield s2.render(true);
setMaskPosition({ right: 0, bottom: 0 });
s2.off(S2Event.GLOBAL_MOUSE_MOVE, dragMove);
s2.off(S2Event.GLOBAL_MOUSE_UP, dragMouseUp);
setStartCell(undefined);
onCopyFinished === null || onCopyFinished === void 0 ? void 0 : onCopyFinished();
});
useEffect(() => {
if (startCell) {
s2.on(S2Event.GLOBAL_MOUSE_MOVE, dragMove);
s2.on(S2Event.GLOBAL_MOUSE_UP, dragMouseUp);
}
}, [startCell]);
const dragMouseDown = (event) => {
if (get(event, 'target.id') !== 'spreadsheet-drag-copy-point') {
return;
}
const rect = event.target.getBoundingClientRect();
const { top, left } = get(event, 'target.style', {});
const allCells = s2.facet.getDataCells();
const targetCell = allCells.find((v) => isInCell({ y: parseFloat(top), x: parseFloat(left) }, v));
setDragPoint({ x: rect.x, y: rect.y });
setStartCell(targetCell);
};
useEffect(() => {
const pointElement = document.getElementById('spreadsheet-drag-copy-point');
if (pointElement && s2) {
pointElement.addEventListener('mousedown', dragMouseDown);
}
return () => {
pointElement === null || pointElement === void 0 ? void 0 : pointElement.removeEventListener('mousedown', dragMouseDown);
};
}, [s2]);
return (React.createElement("div", { className: `${S2_PREFIX_CLS}-drag-copy-mask`, style: {
right: maskPosition.right > 0 ? maskPosition.right : 0,
bottom: maskPosition.bottom > 0 ? maskPosition.bottom : 0,
left: maskPosition.right <= 0 ? maskPosition.right : 0,
top: maskPosition.bottom <= 0 ? maskPosition.bottom : 0,
width: Math.abs(maskPosition.right),
height: Math.abs(maskPosition.bottom),
} }));
});
//# sourceMappingURL=drag-copy-mask.js.map