e-virt-table
Version:
A powerful data table based on canvas. You can use it as data grid、Microsoft Excel or Google sheets. It supports virtual scroll、cell edit etc.
766 lines • 30.2 kB
JavaScript
import { getMaxRow, calCrossSpan, toLeaf, sortFixed, throttle, filterHiddenColumns } from './util';
import CellHeader from './CellHeader';
import { TreeUtil } from './TreeUtil';
export default class Header {
constructor(ctx) {
Object.defineProperty(this, "ctx", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
}); // 上下文
Object.defineProperty(this, "x", {
enumerable: true,
configurable: true,
writable: true,
value: 0
}); // x坐标
Object.defineProperty(this, "y", {
enumerable: true,
configurable: true,
writable: true,
value: 0
}); // y坐标
Object.defineProperty(this, "width", {
enumerable: true,
configurable: true,
writable: true,
value: 0
}); // 宽度
Object.defineProperty(this, "height", {
enumerable: true,
configurable: true,
writable: true,
value: 0
}); // 高度
Object.defineProperty(this, "resizeTarget", {
enumerable: true,
configurable: true,
writable: true,
value: null
}); //调整表头
Object.defineProperty(this, "dragTarget", {
enumerable: true,
configurable: true,
writable: true,
value: null
}); //拖拽表头
Object.defineProperty(this, "dragingCell", {
enumerable: true,
configurable: true,
writable: true,
value: undefined
}); //拖拽表头进入的格子
Object.defineProperty(this, "dragCellDiff", {
enumerable: true,
configurable: true,
writable: true,
value: 0
}); //拖拽表头
Object.defineProperty(this, "resizeNum", {
enumerable: true,
configurable: true,
writable: true,
value: 0
}); // 调整列的数量
Object.defineProperty(this, "isResizing", {
enumerable: true,
configurable: true,
writable: true,
value: false
}); // 是否移动中
Object.defineProperty(this, "clientX", {
enumerable: true,
configurable: true,
writable: true,
value: 0
}); // 鼠标按下时的x轴位置
Object.defineProperty(this, "resizeDiff", {
enumerable: true,
configurable: true,
writable: true,
value: 0
}); // 是否移动中
Object.defineProperty(this, "columnIndex", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "isMouseDown", {
enumerable: true,
configurable: true,
writable: true,
value: false
}); // 是否按下
Object.defineProperty(this, "columns", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "visibleColumns", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "visibleLeafColumns", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "visibleHeight", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "visibleWidth", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "allCellHeaders", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "leafCellHeaders", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "renderLeafCellHeaders", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "fixedLeftCellHeaders", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "centerCellHeaders", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "fixedRightCellHeaders", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "renderCenterCellHeaders", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "renderFixedCellHeaders", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
this.ctx = ctx;
// 监听表头重置,窗口变化
this.ctx.on('resetHeader', throttle(() => {
this.init();
this.ctx.clearSelector();
this.ctx.emit('draw');
}, 100));
this.init();
// 初始化调整列大小ENABLE_RESIZE_COLUMN
this.initResizeColumn();
this.initDragColumn();
}
init(isBuffer = false) {
const { config: { HEADER_HEIGHT, SCROLLER_TRACK_SIZE }, } = this.ctx;
// 防止resizeAllColumn递归
if (!isBuffer) {
const columns = this.ctx.database.getColumns();
this.columns = columns;
}
this.allCellHeaders = [];
this.leafCellHeaders = [];
this.fixedLeftCellHeaders = [];
this.fixedRightCellHeaders = [];
this.centerCellHeaders = [];
this.visibleColumns = filterHiddenColumns(this.columns);
const maxHeaderRow = getMaxRow(this.visibleColumns);
const leafColumns = toLeaf(this.visibleColumns);
this.height = HEADER_HEIGHT * maxHeaderRow;
this.visibleHeight = this.height;
this.width = leafColumns.reduce((sum, _item) => {
const width = _item.width || 100;
const { maxWidth, minWidth } = _item;
if (maxWidth && width > maxWidth) {
return sum + maxWidth;
}
if (minWidth && width < minWidth) {
return sum + minWidth;
}
return sum + width;
}, 0);
this.columnIndex = 0;
this.resizeNum = 0; // 可调整调整列数量
const spanColumns = sortFixed(calCrossSpan(this.visibleColumns, maxHeaderRow));
this.render(spanColumns, 0);
this.ctx.database.updateColIndexKeyMap(this.leafCellHeaders);
const containerElement = this.ctx.containerElement.getBoundingClientRect();
// 如果有可调整列,宽度等于容器宽度
if (this.resizeNum > 0) {
this.ctx.stageWidth = Math.floor(containerElement.width);
}
else {
this.ctx.stageWidth = Math.min(Math.floor(this.width + SCROLLER_TRACK_SIZE), Math.floor(containerElement.width));
}
this.ctx.stageElement.style.width = this.ctx.stageWidth + 'px';
this.visibleWidth = this.ctx.stageWidth - SCROLLER_TRACK_SIZE;
// 如果表头宽度小于可视宽度,平均分配
const overWidth = this.visibleWidth - this.width;
if (this.resizeNum && overWidth > 0) {
const diff = Math.floor((overWidth / this.resizeNum) * 100) / 100;
this.resizeAllColumn(diff);
}
const leafLeftCellHeaders = this.fixedLeftCellHeaders.filter((item) => !item.hasChildren);
this.ctx.fixedLeftWidth = leafLeftCellHeaders.reduce((sum, _item) => sum + _item.width, 0);
const leafRightCellHeaders = this.fixedRightCellHeaders.filter((item) => !item.hasChildren);
this.ctx.fixedRightWidth = leafRightCellHeaders.reduce((sum, _item) => sum + _item.width, SCROLLER_TRACK_SIZE);
// 更新最大列索引
this.ctx.maxColIndex = this.leafCellHeaders.length - 1;
this.ctx.header.x = this.x;
this.ctx.header.y = this.y;
this.ctx.header.width = this.width;
this.ctx.header.height = this.height;
this.ctx.header.allCellHeaders = this.allCellHeaders;
this.ctx.header.visibleWidth = this.visibleWidth;
this.ctx.header.visibleHeight = this.visibleHeight;
}
// 调整表头的宽度
initResizeColumn() {
this.ctx.on('mousedown', (e) => {
if (!this.ctx.config.ENABLE_RESIZE_COLUMN) {
return;
}
if (!this.ctx.isTarget(e)) {
return;
}
this.clientX = e.clientX;
if (this.resizeTarget) {
this.isResizing = true;
this.ctx.columnResizing = true;
}
else {
this.isResizing = false;
}
this.isMouseDown = true;
});
this.ctx.on('mouseup', () => {
if (!this.ctx.config.ENABLE_RESIZE_COLUMN) {
return;
}
this.isMouseDown = false;
// 清空
if (this.resizeDiff !== 0 && this.resizeTarget) {
// 调整宽度
this.resizeColumn(this.resizeTarget, this.resizeDiff);
}
this.resizeTarget = null;
this.isResizing = false;
this.isMouseDown = false;
this.ctx.columnResizing = false;
this.clientX = 0;
this.resizeDiff = 0;
});
this.ctx.on('mousemove', (e) => {
if (!this.ctx.config.ENABLE_RESIZE_COLUMN) {
return;
}
// 编辑中不触发mousemove
if (this.ctx.editing)
return;
const { stageWidth, config: { RESIZE_COLUMN_MIN_WIDTH }, } = this.ctx;
// 鼠标移动
if (this.isResizing && this.resizeTarget) {
const resizeTargetWidth = this.resizeTarget.width;
const resizeTargetMinWidth = this.resizeTarget.minWidth;
const resizeTargetMaxWidth = this.resizeTarget.maxWidth;
let diff = e.clientX - this.clientX;
if (diff + resizeTargetWidth < RESIZE_COLUMN_MIN_WIDTH) {
diff = -(resizeTargetWidth - RESIZE_COLUMN_MIN_WIDTH);
}
if (resizeTargetMinWidth && diff + resizeTargetWidth < resizeTargetMinWidth) {
diff = -(resizeTargetWidth - resizeTargetMinWidth);
}
if (resizeTargetMaxWidth && diff + resizeTargetWidth > resizeTargetMaxWidth) {
diff = resizeTargetMaxWidth - resizeTargetWidth;
}
this.resizeDiff = diff;
this.ctx.emit('draw');
}
else {
this.resizeTarget = null;
// 按下时不改变样式,有可能是多选表头
if (this.isMouseDown) {
return;
}
// 鼠标在表头上,边界处理
if (e.offsetX < 0 || e.offsetX > this.visibleWidth) {
if (this.ctx.stageElement.style.cursor === 'col-resize') {
this.ctx.stageElement.style.cursor = 'default';
}
return;
}
// 恢复默认样式
if (this.ctx.stageElement.style.cursor === 'col-resize') {
this.ctx.stageElement.style.cursor = 'default';
}
// 渲染的表头
const renderAllCellHeaders = [...this.renderFixedCellHeaders, ...this.renderCenterCellHeaders];
for (const col of renderAllCellHeaders) {
const { offsetX, offsetY } = this.ctx.getOffset(e);
const x = offsetX;
const y = offsetY;
const drawX = col.getDrawX();
const drawY = col.getDrawY();
if (x > drawX + col.width - 5 &&
x < drawX + col.width + 4 &&
x < stageWidth - 4 && // 视窗中最后一列不允许调整宽
y > drawY) {
const colIndex = col.colIndex + col.colspan - 1;
const resizeTarget = this.leafCellHeaders.find((item) => item.colIndex === colIndex);
if (!resizeTarget) {
return;
}
// 中间部分到固定位置
if (!resizeTarget.fixed && this.ctx.stageWidth - this.ctx.fixedRightWidth < drawX + col.width) {
return;
}
// 在表头内
if (this.ctx.isTarget(e) && offsetY <= this.height) {
this.ctx.stageElement.style.cursor = 'col-resize';
this.resizeTarget = resizeTarget;
}
}
}
}
});
}
initDragColumn() {
this.ctx.on('cellHeaderMousedown', (cellHeader) => {
if (!this.ctx.config.ENABLE_DRAG_COLUMN) {
return;
}
if (cellHeader.column.dragDisabled) {
return;
}
if (this.dragTarget === cellHeader) {
this.ctx.dragHeaderIng = true;
this.dragCellDiff = this.ctx.mouseX - cellHeader.drawX;
this.ctx.stageElement.style.cursor = 'grabbing';
}
else {
this.dragTarget = cellHeader;
this.ctx.dragHeaderIng = false;
}
});
this.ctx.on('cellMousedown', () => {
if (!this.ctx.config.ENABLE_DRAG_COLUMN) {
return;
}
this.dragTarget = null;
this.ctx.dragHeaderIng = false;
});
this.ctx.on('mouseup', () => {
if (!this.ctx.config.ENABLE_DRAG_COLUMN) {
return;
}
if (this.dragingCell && this.dragTarget) {
// 需要移动
const genSortObj = (columns, obj = {}) => {
columns.forEach((item, index) => {
if (item.children) {
genSortObj(item.children, obj);
}
obj[item.key] = index;
});
return obj;
};
const columns = this.ctx.database.getColumns();
const sortColumns = calCrossSpan(columns, getMaxRow(columns));
const tree = new TreeUtil(sortColumns, {
key: 'key', // 节点唯一标识字段(对应我们之前的field)
childrenKey: 'children', // 子节点数组字段
});
const position = this.dragTarget.colIndex > this.dragingCell.colIndex ? 'before' : 'after';
tree.treeMove(this.dragTarget.column, this.dragingCell.column, position);
const columnsTree = tree.getTree();
const sortData = genSortObj(columnsTree);
this.ctx.database.setCustomHeader({ sortData });
this.init();
const data = {
source: this.dragTarget,
target: this.dragingCell,
columns: sortColumns,
};
this.ctx.emit('columnDragChange', data);
}
if (this.ctx.dragHeaderIng && this.dragTarget) {
this.ctx.dragHeaderIng = false;
this.dragTarget = null;
this.dragingCell = undefined;
this.dragCellDiff = 0;
this.ctx.clearSelector();
this.ctx.focusCellHeader = undefined;
this.ctx.stageElement.style.cursor = 'default';
this.ctx.emit('draw');
}
});
this.ctx.on('mousemove', (e) => {
if (!this.ctx.config.ENABLE_DRAG_COLUMN) {
return;
}
if (!this.ctx.dragHeaderIng || !this.dragTarget) {
return;
}
if (!this.dragTarget.fixed) {
this.ctx.startAdjustPosition(e);
}
this.ctx.emit('draw');
});
this.ctx.on('cellHoverChange', (cell) => {
if (!this.ctx.config.ENABLE_DRAG_COLUMN) {
return;
}
if (cell.column.dragDisabled) {
return;
}
this.dragingCell = this.getDragCellHeader(cell.colIndex);
});
this.ctx.on('cellHeaderHoverChange', (cellHeader) => {
if (!this.ctx.config.ENABLE_DRAG_COLUMN) {
return;
}
if (cellHeader.column.dragDisabled) {
return;
}
this.dragingCell = this.getDragCellHeader(cellHeader.colIndex);
});
}
getDragCellHeader(colIndex) {
if (!this.dragTarget || !this.ctx.dragHeaderIng) {
return;
}
// 同级别
const { column: { parentKey }, key, level, fixed, } = this.dragTarget;
const dragCellHeader = this.allCellHeaders.find((item) => item.key !== key &&
item.fixed === fixed &&
item.column.level === level &&
item.column.parentKey === parentKey &&
item.colIndex <= colIndex &&
item.colIndex + item.colspan - 1 >= colIndex);
if (this.ctx.dragHeaderIng) {
const cursor = dragCellHeader ? 'grabbing' : 'not-allowed';
// 禁用拖拽
this.ctx.stageElement.style.cursor = cursor;
}
return dragCellHeader;
}
resizeColumn(cell, diff) {
const setWidth = (columns) => {
columns.forEach((column) => {
if (column.children && column.children.length > 0) {
setWidth(column.children);
}
if (column.key === cell.key) {
const width = column.width || 100;
column.width = width + diff;
}
});
};
setWidth(this.columns);
let overDiff = 0;
// 如果表头宽度小于可视宽度,平均分配
if (this.width < this.visibleWidth) {
const overWidth = this.visibleWidth - this.width;
overDiff = Math.floor((overWidth / this.resizeNum) * 100) / 100;
this.resizeAllColumn(overDiff);
}
const width = cell.width + diff + overDiff;
this.ctx.emit('resizeColumnChange', {
colIndex: cell.colIndex,
key: cell.key,
oldWidth: cell.width,
width: width,
column: cell.column,
columns: this.columns,
});
this.ctx.database.setCustomHeaderResizableData(cell.key, width);
this.init(true);
this.ctx.emit('draw');
}
resizeAllColumn(fellWidth) {
if (fellWidth === 0)
return;
const widthMap = new Map();
// 存需要更改的宽度
let isResize = true;
for (const col of this.allCellHeaders) {
if (col.widthFillDisable) {
// 不允许调整宽度
widthMap.set(col.key, col.width);
}
else {
const width = col.width + fellWidth * col.colspan;
widthMap.set(col.key, width);
if (width < this.ctx.config.RESIZE_COLUMN_MIN_WIDTH) {
isResize = false;
}
}
}
// 如果有小于RESIZE_COLUMN_MIN_WIDTH的列,不允许调整
if (!isResize) {
return;
}
// 递归更改宽度
const uptateWidth = (columns) => {
columns.forEach((column) => {
if (widthMap.has(column.key)) {
column.width = widthMap.get(column.key);
}
if (column.children && column.children.length > 0) {
uptateWidth(column.children);
}
});
};
uptateWidth(this.columns);
this.init(true);
this.ctx.emit("draw");
}
getCustomHeader() {
const columns = this.ctx.database.getColumns();
const customHeader = this.ctx.database.getCustomHeader();
const { sortData = {} } = customHeader;
if (Object.keys(sortData).length === 0) {
return {
columns,
customHeader,
};
}
const _sortColumns = calCrossSpan(columns, getMaxRow(columns));
return {
columns: _sortColumns,
customHeader,
};
}
render(arr, originX) {
const len = arr.length;
let everyOffsetX = originX;
const { HEADER_HEIGHT = 0 } = this.ctx.config;
for (let i = 0; i < len; i++) {
const item = arr[i];
const height = HEADER_HEIGHT * (item.rowspan || 0);
const y = HEADER_HEIGHT * (item.level || 0);
let { minWidth, maxWidth } = item;
let width = item.width || 100; // 读取映射宽度
if (minWidth && width < minWidth) {
width = minWidth;
}
if (maxWidth && width > maxWidth) {
width = maxWidth;
}
if (item.children) {
// 父级表头的宽度是叶子节点表头的宽度总和
const _arr = toLeaf(item.children);
width = _arr.reduce((sum, _item) => sum + (_item?.width || 100), 0);
}
const cellHeader = new CellHeader(this.ctx, this.columnIndex, everyOffsetX, y, width, height, item);
// 设置表头
this.ctx.database.setHeader(item.key, cellHeader);
this.allCellHeaders.push(cellHeader);
if (!item.children) {
this.leafCellHeaders.push(cellHeader);
if (!cellHeader.column.widthFillDisable) {
this.resizeNum++;
}
}
if (item.fixed === 'left') {
this.fixedLeftCellHeaders.push(cellHeader);
}
else if (item.fixed === 'right') {
this.fixedRightCellHeaders.push(cellHeader);
}
else {
this.centerCellHeaders.push(cellHeader);
}
!item.children && this.columnIndex++;
item.children && this.render(item.children, everyOffsetX);
everyOffsetX += width;
}
}
drawTipLine() {
if (this.isResizing && this.resizeTarget) {
const { stageHeight, config: { RESIZE_COLUMN_LINE_COLOR, RESIZE_COLUMN_TEXT_COLOR, RESIZE_COLUMN_TEXT_BG_COLOR, ENABLE_RESIZE_COLUMN_TEXT, }, } = this.ctx;
const resizeTargetDrawX = this.resizeTarget.getDrawX();
const resizeTargetWidth = this.resizeTarget.width;
const x = resizeTargetDrawX + resizeTargetWidth + this.resizeDiff - 0.5;
const poins = [x - 0.5, 0, x - 0.5, stageHeight];
this.ctx.paint.drawLine(poins, {
borderColor: RESIZE_COLUMN_LINE_COLOR,
});
if (ENABLE_RESIZE_COLUMN_TEXT) {
const newWidth = Math.floor(resizeTargetWidth + this.resizeDiff);
const text = `${newWidth}px`;
const rw = 45;
const rh = 24;
this.ctx.paint.drawRect(x + rw / 2, this.ctx.mouseY - rh / 2, rw, rh, {
fillColor: RESIZE_COLUMN_TEXT_BG_COLOR,
borderWidth: 0,
borderColor: 'transparent',
});
this.ctx.paint.drawText(text, x + rw / 2, this.ctx.mouseY - rh / 2, rw, rh + 2, {
padding: 0,
color: RESIZE_COLUMN_TEXT_COLOR,
align: 'center',
verticalAlign: 'middle',
});
}
}
}
drawDragTip() {
if (this.dragTarget && this.ctx.dragHeaderIng) {
const { DRAG_TIP_BG_COLOR, DRAG_TIP_LINE_COLOR } = this.ctx.config;
const rw = this.dragTarget.width;
// 提示背景
this.ctx.paint.drawRect(this.ctx.mouseX - this.dragCellDiff, this.visibleHeight, rw, this.ctx.body.visibleHeight, {
fillColor: DRAG_TIP_BG_COLOR,
borderWidth: 0,
borderColor: 'transparent',
});
if (this.dragingCell) {
const { drawX, drawY, visibleWidth, colIndex } = this.dragingCell;
// 向坐移动
let x = drawX;
let y = drawY;
if (colIndex > this.dragTarget.colIndex) {
// 向右移动
x = drawX + visibleWidth;
}
// 边界处理
if (colIndex === 0) {
x = x + 1;
}
// 边界处理
if (colIndex === this.ctx.maxColIndex) {
x = x - 1;
}
const poins = [x, y, x, this.ctx.stageHeight];
// 倒三角形
const trianglePoins = [x - 4, y, x + 4, y, x, y + 6, x - 4, y];
this.ctx.paint.drawLine(trianglePoins, {
borderColor: DRAG_TIP_LINE_COLOR,
borderWidth: 1.2,
fillColor: DRAG_TIP_LINE_COLOR,
});
this.ctx.paint.drawLine(poins, {
borderColor: DRAG_TIP_LINE_COLOR,
borderWidth: 1.2,
});
}
}
}
drawFixedShadow() {
const { fixedLeftWidth, fixedRightWidth, scrollX, header, stageWidth, config: { HEADER_BG_COLOR, SCROLLER_TRACK_SIZE }, } = this.ctx;
if (scrollX > 0 && fixedLeftWidth !== 0) {
this.ctx.paint.drawShadow(this.x, this.y, fixedLeftWidth, this.height, {
fillColor: HEADER_BG_COLOR,
side: 'right',
shadowWidth: 4,
colorStart: 'rgba(0,0,0,0.1)',
colorEnd: 'rgba(0,0,0,0)',
});
}
// 右边阴影
if (scrollX < Math.floor(header.width - stageWidth - 1) && fixedRightWidth !== SCROLLER_TRACK_SIZE) {
const x = header.width - (this.x + this.width) + stageWidth - fixedRightWidth;
this.ctx.paint.drawShadow(x, this.y, fixedRightWidth, this.height, {
fillColor: HEADER_BG_COLOR,
side: 'left',
shadowWidth: 4,
colorStart: 'rgba(0,0,0,0)',
colorEnd: 'rgba(0,0,0,0.1)',
});
}
}
update() {
const renderLeafCellHeaders = [];
const renderCenterCellHeaders = [];
const renderFixedCellHeaders = [];
// 中心的最后一个ColIndex
if (this.centerCellHeaders.length) {
const lastCenterCell = this.centerCellHeaders[this.centerCellHeaders.length - 1];
this.ctx.lastCenterColIndex = lastCenterCell.colIndex;
}
this.centerCellHeaders.forEach((item) => {
if (item.isHorizontalVisible() && item.isVerticalVisible()) {
renderCenterCellHeaders.push(item);
if (!item.hasChildren) {
renderLeafCellHeaders.push(item);
}
}
});
this.fixedLeftCellHeaders.forEach((item) => {
renderFixedCellHeaders.push(item);
if (!item.hasChildren) {
renderLeafCellHeaders.push(item);
}
});
this.fixedRightCellHeaders.forEach((item) => {
renderFixedCellHeaders.push(item);
if (!item.hasChildren) {
renderLeafCellHeaders.push(item);
}
});
this.renderCenterCellHeaders = renderCenterCellHeaders;
this.renderFixedCellHeaders = renderFixedCellHeaders;
this.renderLeafCellHeaders = renderLeafCellHeaders.sort((a, b) => a.x - b.x);
this.visibleLeafColumns = this.renderLeafCellHeaders.map((item) => item.column);
this.ctx.header.visibleLeafColumns = this.visibleLeafColumns;
this.ctx.header.leafCellHeaders = this.leafCellHeaders;
this.ctx.header.renderLeafCellHeaders = this.renderLeafCellHeaders;
this.ctx.header.renderCellHeaders = this.renderFixedCellHeaders.concat(this.renderCenterCellHeaders);
}
drawBottomLine() {
const { stageWidth, config: { BORDER_COLOR }, } = this.ctx;
const poins = [0, this.height, stageWidth, this.height];
this.ctx.paint.drawLine(poins, {
borderColor: BORDER_COLOR,
borderWidth: 1,
});
}
draw() {
this.renderCenterCellHeaders.forEach((item) => {
item.update();
item.draw();
});
this.drawFixedShadow();
this.renderFixedCellHeaders.forEach((item) => {
item.update();
item.draw();
});
this.drawBottomLine();
this.drawTipLine();
this.drawDragTip();
}
}
//# sourceMappingURL=Header.js.map