UNPKG

@visactor/vtable

Version:

canvas table width high performance

179 lines (167 loc) 8.7 kB
import { isArray, isValid } from "@visactor/vutils"; import { Group } from "../scenegraph/graphic/group"; import { updateCell } from "../scenegraph/group-creater/cell-helper"; import { createRect } from "./../vrender"; import { Factory } from "../core/factory"; import { getTargetCell } from "../event/util"; export class ListTreeStickCellPlugin { constructor(table) { this.titleRows = [], this.showedTitleRows = [], this.rowNow = -1, this.skipStartRow = -1, this.skipEndRow = -1, this.table = table, this.table.on("scroll", (e => { "vertical" === e.scrollDirection && this.updateGroupTitle(); })), this.table.on("tree_hierarchy_state_change", (e => { this.updateGroupTitle(); })), this.table.on("resize_column", (e => { this.updateGroupTitle(); })); } updateGroupTitle() { 0 === this.table.scrollTop ? (this.titleRows = [], this.showedTitleRows = []) : -1 !== this.skipStartRow && -1 !== this.skipEndRow && this.skipStartRow !== this.table.scenegraph.proxy.bodyTopRow - 1 ? (this.table.scenegraph.proxy.screenTopRow <= this.skipStartRow || this.table.scenegraph.proxy.screenTopRow >= this.skipEndRow) && (this.skipStartRow = -1, this.skipEndRow = -1, this.updateGroupTitleInfo()) : (this.skipStartRow = -1, this.skipEndRow = -1, this.updateGroupTitleInfo()), this.updateScenegraph(); } updateGroupTitleInfo() { this.rowNow = this.table.scenegraph.proxy.screenTopRow + this.titleRows.length; const recordIndex = this.table.getRecordIndexByCell(0, this.rowNow), nextRecordIndex = this.table.getRecordIndexByCell(0, this.rowNow + 1); this.getTitleRowsByRecordIndex(recordIndex, nextRecordIndex); } getTitleRowsByRecordIndex(recordIndex, nextRecordIndex) { const titleRecords = []; isArray(recordIndex) || (recordIndex = [ recordIndex ]), isArray(nextRecordIndex) || (nextRecordIndex = [ nextRecordIndex ]); for (let i = 0; i < recordIndex.length; i++) { const index = recordIndex.slice(0, i + 1), record = this.table.dataSource.getRaw(index); titleRecords.push(record); } const titleRows = [], isTitle = nextRecordIndex.length === recordIndex.length + 1; let titleIndex = recordIndex.slice(0, isTitle ? recordIndex.length : recordIndex.length - 1); const currentIndexedData = this.table.dataSource.currentIndexedData; for (let i = this.rowNow - this.table.columnHeaderLevelCount; i >= 0; i--) { const currentIndex = currentIndexedData[i]; if (isArray(currentIndex) && titleIndex.length === currentIndex.length) { let isMatch = !0; for (let j = 0; j < currentIndex.length; j++) if (currentIndex[j] !== titleIndex[j]) { isMatch = !1; break; } isMatch && (titleRows.push(i + this.table.columnHeaderLevelCount), titleIndex = titleIndex.slice(0, titleIndex.length - 1)); } else if (currentIndex === recordIndex[0]) { titleRows.push(i + this.table.columnHeaderLevelCount); break; } } this.titleRows = titleRows.reverse(); } updateScenegraph() { const {table: table} = this, {shadowGroup: shadowGroup, shadowGroupFrozen: shadowGroupFrozen} = prepareShadowRoot(table); this.showedTitleRows.length = 0; let skip = 0; for (let col = 0; col < table.colCount; col++) { let colGroup; col < table.frozenColCount ? (colGroup = new Group({ x: table.getColsWidth(0, col - 1), y: table.getFrozenRowsHeight() }), shadowGroupFrozen.add(colGroup)) : (colGroup = new Group({ x: table.getColsWidth(table.frozenColCount, col - 1), y: table.getFrozenRowsHeight() }), shadowGroup.add(colGroup)), colGroup.col = col; for (let i = 0; i < this.titleRows.length; i++) { const row = this.titleRows[i]; if (isSkipRow(row, this.rowNow, table.scenegraph.proxy.screenTopRow, this.titleRows)) { 0 === col && skip++; continue; } 0 === col && this.showedTitleRows.push(row); const cell = table.scenegraph.getCell(col, row); if ("cell" === cell.role) { const newCell = cloneGraphic(cell); newCell.setAttributes({ y: 40 * i }), colGroup.add(newCell); } else { const newCell = updateCell(col, row, table, !0, !0); newCell.setAttributes({ y: 40 * i }), colGroup.add(newCell); } } } skip > 0 && -1 === this.skipStartRow && -1 === this.skipEndRow && (this.skipStartRow = table.scenegraph.proxy.screenTopRow - 1, this.skipEndRow = table.scenegraph.proxy.screenTopRow + 1); } } function isSkipRow(row, topRow, screenTopRow, titleRows) { if (row === topRow && row !== screenTopRow + titleRows.length - 1) return !0; return row === screenTopRow + titleRows.indexOf(row) + 1 && row < topRow; } function cloneGraphic(graphic) { const newGraphic = graphic.clone(); if (newGraphic.role = graphic.role, newGraphic.col = graphic.col, newGraphic.row = graphic.row, newGraphic.mergeStartCol = graphic.mergeStartCol, newGraphic.mergeStartRow = graphic.mergeStartRow, newGraphic.mergeEndCol = graphic.mergeEndCol, newGraphic.mergeEndRow = graphic.mergeEndRow, newGraphic.contentWidth = graphic.contentWidth, newGraphic.contentHeight = graphic.contentHeight, "cell" === newGraphic.role) { const hackRect = createRect({ x: 0, y: 0, width: newGraphic.attribute.width, height: newGraphic.attribute.height }); newGraphic.add(hackRect); } if ("group" === graphic.type) { const newGroup = newGraphic; graphic.forEachChildren((child => { const newChild = cloneGraphic(child); newGroup.add(newChild); })); } return newGraphic; } function prepareShadowRoot(table) { const colHeaderGroup = table.scenegraph.colHeaderGroup, cornerHeaderGroup = table.scenegraph.cornerHeaderGroup; if (!colHeaderGroup.border) { const hackBorder = createRect({ x: 0, y: 0, width: 0, height: 0, cursor: "pointer" }); colHeaderGroup.add(hackBorder), colHeaderGroup.border = hackBorder, hackBorder.attachShadow(hackBorder.shadowRoot), hackBorder.name = "border-rect", hackBorder.addEventListener("click", (e => { const titleRows = table.listTreeStickCellPlugin.titleRows, {shadowTarget: shadowTarget} = e.pickParams, cellGroup = getTargetCell(shadowTarget), {col: col, row: row} = cellGroup; scrollToRow(row - titleRows.indexOf(row), table); })); } if (!cornerHeaderGroup.border) { const hackBorder = createRect({ x: 0, y: 0, width: 0, height: 0, cursor: "pointer" }); cornerHeaderGroup.add(hackBorder), cornerHeaderGroup.border = hackBorder, hackBorder.attachShadow(hackBorder.shadowRoot), hackBorder.name = "border-rect", hackBorder.addEventListener("click", (e => { const titleRows = table.listTreeStickCellPlugin.titleRows, {shadowTarget: shadowTarget} = e.pickParams, cellGroup = getTargetCell(shadowTarget), {col: col, row: row} = cellGroup; scrollToRow(row - titleRows.indexOf(row), table); })); } const shadowGroup = colHeaderGroup.border.shadowRoot, shadowGroupFrozen = cornerHeaderGroup.border.shadowRoot; return shadowGroup.removeAllChild(), shadowGroupFrozen.removeAllChild(), { shadowGroup: shadowGroup, shadowGroupFrozen: shadowGroupFrozen }; } function scrollToRow(row, table) { const drawRange = table.getDrawRange(); if (isValid(row) && row >= table.frozenRowCount) { const frozenHeight = table.getFrozenRowsHeight(), top = table.getRowsHeight(0, row - 1); table.scrollTop = Math.min(top - frozenHeight, table.getAllRowsHeight() - drawRange.height) - 1; } table.scenegraph.updateNextFrame(); } export const registerListTreeStickCellPlugin = () => { Factory.registerComponent("listTreeStickCellPlugin", ListTreeStickCellPlugin); }; //# sourceMappingURL=list-tree-stick-cell.js.map