diff --git a/common/changes/@visactor/vtable/3582-feature-fillHandle-function_2025-03-19-10-33.json b/common/changes/@visactor/vtable/3582-feature-fillHandle-function_2025-03-19-10-33.json new file mode 100644 index 000000000..c35b79994 --- /dev/null +++ b/common/changes/@visactor/vtable/3582-feature-fillHandle-function_2025-03-19-10-33.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "refactor: fillHandle function #3582\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file diff --git a/packages/vtable/examples/interactive/fill-handle.ts b/packages/vtable/examples/interactive/fill-handle.ts index 634f2293b..9e5831864 100644 --- a/packages/vtable/examples/interactive/fill-handle.ts +++ b/packages/vtable/examples/interactive/fill-handle.ts @@ -82,7 +82,27 @@ export function createTable() { columns, widthMode: 'standard', excelOptions: { - fillHandle: true + fillHandle: args => { + const { selectRanges, table } = args; + if (selectRanges.length === 1) { + const { start, end } = selectRanges[0]; + console.log('fillHandle', start, end); + const minCol = Math.min(start.col, end.col); + const maxCol = Math.max(start.col, end.col); + const minRow = Math.min(start.row, end.row); + const maxRow = Math.max(start.row, end.row); + //判断start到end 所有单元格有没有不能编辑的 + for (let col = minCol; col <= maxCol; col++) { + for (let row = minRow; row <= maxRow; row++) { + if (row === 2 && col === 2) { + return false; + } + } + } + return true; + } + return false; + } } }; const tableInstance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); diff --git a/packages/vtable/src/event/event.ts b/packages/vtable/src/event/event.ts index fc88d0718..c91755215 100644 --- a/packages/vtable/src/event/event.ts +++ b/packages/vtable/src/event/event.ts @@ -587,9 +587,17 @@ export class EventManager { } return false; } - checkCellFillhandle(eventArgsSet: SceneEvent, update?: boolean): boolean { - if (this.table.options.excelOptions?.fillHandle) { + let isFillHandle = false; + if (typeof this.table.options.excelOptions?.fillHandle === 'function') { + isFillHandle = this.table.options.excelOptions.fillHandle({ + selectRanges: this.table.stateManager.select.ranges, + table: this.table + }); + } else { + isFillHandle = this.table.options.excelOptions?.fillHandle; + } + if (isFillHandle) { const { eventArgs } = eventArgsSet; if (eventArgs) { if (this.table.stateManager.select?.ranges?.length) { @@ -601,11 +609,31 @@ export class EventManager { this.table.stateManager.select.ranges[this.table.stateManager.select.ranges.length - 1].start.row, this.table.stateManager.select.ranges[this.table.stateManager.select.ranges.length - 1].end.row ); - - const lastCellBound = this.table.scenegraph.highPerformanceGetCell(lastCol, lastRow).globalAABBBounds; - // 计算鼠标与fillhandle矩形中心之间的距离 + const startCol = Math.min( + this.table.stateManager.select.ranges[this.table.stateManager.select.ranges.length - 1].start.col, + this.table.stateManager.select.ranges[this.table.stateManager.select.ranges.length - 1].end.col + ); + const startRow = Math.min( + this.table.stateManager.select.ranges[this.table.stateManager.select.ranges.length - 1].start.row, + this.table.stateManager.select.ranges[this.table.stateManager.select.ranges.length - 1].end.row + ); + // 计算鼠标与fillhandle矩形中心之间的距离 distanceX 和 distanceY + // 考虑最后一行和最后一列的特殊情况 + let lastCellBound; + if (lastCol < this.table.colCount - 1) { + lastCellBound = this.table.scenegraph.highPerformanceGetCell(lastCol, lastRow).globalAABBBounds; + } else { + lastCellBound = this.table.scenegraph.highPerformanceGetCell(startCol - 1, lastRow).globalAABBBounds; + } const distanceX = Math.abs(eventArgsSet.abstractPos.x - lastCellBound.x2); + + if (lastRow < this.table.rowCount - 1) { + lastCellBound = this.table.scenegraph.highPerformanceGetCell(lastCol, lastRow).globalAABBBounds; + } else { + lastCellBound = this.table.scenegraph.highPerformanceGetCell(lastCol, startRow - 1).globalAABBBounds; + } const distanceY = Math.abs(eventArgsSet.abstractPos.y - lastCellBound.y2); + const squareSize = 6 * 3; // 判断鼠标是否落在fillhandle矩形内 if ( diff --git a/packages/vtable/src/scenegraph/select/update-select-border.ts b/packages/vtable/src/scenegraph/select/update-select-border.ts index 5fdd89cd6..42282cd20 100644 --- a/packages/vtable/src/scenegraph/select/update-select-border.ts +++ b/packages/vtable/src/scenegraph/select/update-select-border.ts @@ -94,10 +94,6 @@ function updateComponent( computeRectCellRangeStartCol, computeRectCellRangeStartRow ).globalAABBBounds; - const lastCellBound = scene.highPerformanceGetCell( - computeRectCellRangeEndCol, - computeRectCellRangeEndRow - ).globalAABBBounds; selectComp.rect.setAttributes({ x: firstCellBound.x1 - scene.tableGroup.attribute.x, //坐标xy在下面的逻辑中会做适当调整 @@ -107,12 +103,50 @@ function updateComponent( visible: true }); if (selectComp.fillhandle) { + const fillHandle = scene.table.options.excelOptions?.fillHandle; + let visible = true; + if (typeof fillHandle === 'function') { + visible = fillHandle({ selectRanges: scene.table.stateManager.select.ranges, table: scene.table }); + } + //#region 计算填充柄小方块的位置 + + let lastCellBound; + //当选择区域没有到到最后一列时 + if (computeRectCellRangeEndCol < table.colCount - 1) { + lastCellBound = scene.highPerformanceGetCell( + computeRectCellRangeEndCol, + computeRectCellRangeEndRow + ).globalAABBBounds; + } else { + // 最后一列 + lastCellBound = scene.highPerformanceGetCell( + computeRectCellRangeStartCol - 1, + computeRectCellRangeEndRow + ).globalAABBBounds; + } + const handlerX = lastCellBound.x2 - scene.tableGroup.attribute.x - 3; + //当选择区域没有到到最后一行时 + if (computeRectCellRangeEndRow < table.rowCount - 1) { + lastCellBound = scene.highPerformanceGetCell( + computeRectCellRangeEndCol, + computeRectCellRangeEndRow + ).globalAABBBounds; + } else { + // 最后一行 + lastCellBound = scene.highPerformanceGetCell( + computeRectCellRangeEndCol, + computeRectCellRangeStartRow - 1 + ).globalAABBBounds; + } + const handlerY = lastCellBound.y2 - scene.tableGroup.attribute.y - 3; + //#endregion + selectComp.fillhandle?.setAttributes({ - x: lastCellBound.x2 - scene.tableGroup.attribute.x - 3, // 调整小方块位置 - y: lastCellBound.y2 - scene.tableGroup.attribute.y - 3, // 调整小方块位置 + x: handlerX, // 调整小方块位置 + y: handlerY, // 调整小方块位置 width: 6, height: 6, - visible: true + visible }); } diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index 61ea79d17..7add525bc 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -327,7 +327,7 @@ export interface BaseTableConstructorOptions { /** 快捷键功能设置 */ keyboardOptions?: TableKeyboardOptions; excelOptions?: { - fillHandle?: boolean; + fillHandle?: boolean | ((args: { selectRanges: CellRange[]; table: BaseTableAPI }) => boolean); }; /** 事件触发相关设置 */ eventOptions?: TableEventOptions;