diff --git a/src/editor/assets/css/table/table.css b/src/editor/assets/css/table/table.css index 7ec8293..a0b281e 100644 --- a/src/editor/assets/css/table/table.css +++ b/src/editor/assets/css/table/table.css @@ -84,21 +84,21 @@ border: 1px dotted #000000; } -.ce-table-tool__line { +.ce-table-tool__border { position: absolute; z-index: 1; background: transparent; pointer-events: none; } -.ce-table-tool__rline__resize { +.ce-table-tool__border__row { position: absolute; cursor: row-resize; pointer-events: auto; } -.ce-table-tool__cline__resize { +.ce-table-tool__border__col { position: absolute; cursor: col-resize; pointer-events: auto; -} +} \ No newline at end of file diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index 1b2450d..cff8c11 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -1319,10 +1319,10 @@ export class Draw { } else { this._immediateRender() } + const positionContext = this.position.getPositionContext() // 光标重绘 if (isSetCursor) { const positionList = this.position.getPositionList() - const positionContext = this.position.getPositionContext() if (positionContext.isTable) { const { index, trIndex, tdIndex } = positionContext const elementList = this.getOriginalElementList() @@ -1344,7 +1344,7 @@ export class Draw { const oldHeaderElementList = deepClone(this.header.getElementList()) const { startIndex, endIndex } = this.range.getRange() const pageNo = this.pageNo - const oldPositionContext = deepClone(this.position.getPositionContext()) + const oldPositionContext = deepClone(positionContext) const zone = this.zone.getZone() this.historyManager.execute(function () { self.zone.setZone(zone) @@ -1358,6 +1358,10 @@ export class Draw { } // 信息变动回调 nextTick(() => { + // 表格工具重新渲染 + if (isCompute && !this.isReadonly() && positionContext.isTable) { + this.tableTool.render() + } // 页面尺寸改变 if (this.listener.pageSizeChange) { this.listener.pageSizeChange(this.pageRowList.length) diff --git a/src/editor/core/draw/particle/table/TableTool.ts b/src/editor/core/draw/particle/table/TableTool.ts index 1063b82..527d2a4 100644 --- a/src/editor/core/draw/particle/table/TableTool.ts +++ b/src/editor/core/draw/particle/table/TableTool.ts @@ -2,7 +2,6 @@ import { IElement } from '../../../..' import { EDITOR_PREFIX } from '../../../../dataset/constant/Editor' import { TableOrder } from '../../../../dataset/enum/table/TableTool' import { IEditorOption } from '../../../../interface/Editor' -import { IElementPosition } from '../../../../interface/Element' import { Position } from '../../../position/Position' import { Draw } from '../../Draw' @@ -11,13 +10,16 @@ interface IAnchorMouseDown { order: TableOrder; index: number; element: IElement; - position: IElementPosition; } export class TableTool { - private readonly translate = 18 - private minTdWidth = 20 + // 单元格最小宽度 + private readonly MIN_TD_WIDTH = 20 + // 行列工具相对表格偏移值 + private readonly ROW_COL_OFFSET = 18 + // 边框工具宽/高度 + private readonly BORDER_VALUE = 4 private draw: Draw private canvas: HTMLCanvasElement @@ -26,8 +28,8 @@ export class TableTool { private container: HTMLDivElement private toolRowContainer: HTMLDivElement | null private toolColContainer: HTMLDivElement | null + private toolBorderContainer: HTMLDivElement | null private anchorLine: HTMLDivElement | null - private toolBox: HTMLDivElement | null private mousedownX: number private mousedownY: number @@ -40,8 +42,8 @@ export class TableTool { // x、y轴 this.toolRowContainer = null this.toolColContainer = null + this.toolBorderContainer = null this.anchorLine = null - this.toolBox = null this.mousedownX = 0 this.mousedownY = 0 } @@ -49,30 +51,43 @@ export class TableTool { public dispose() { this.toolRowContainer?.remove() this.toolColContainer?.remove() - this.toolBox?.remove() + this.toolBorderContainer?.remove() + this.toolRowContainer = null + this.toolColContainer = null + this.toolBorderContainer = null } - public render(element: IElement, position: IElementPosition) { + public render() { + const { isTable, index, trIndex, tdIndex } = this.position.getPositionContext() + if (!isTable) return + + // 销毁之前工具 this.dispose() - const { trIndex, tdIndex } = this.position.getPositionContext() + + // 渲染所需数据 const { scale } = this.options - const height = this.draw.getHeight() - const pageGap = this.draw.getPageGap() + const elementList = this.draw.getOriginalElementList() + const positionList = this.position.getOriginalPositionList() + const element = elementList[index!] + const position = positionList[index!] const { colgroup, trList } = element const { coordinate: { leftTop } } = position + const height = this.draw.getHeight() + const pageGap = this.draw.getPageGap() const prePageHeight = this.draw.getPageNo() * (height + pageGap) + const tableX = leftTop[0] + const tableY = leftTop[1] + prePageHeight const td = element.trList![trIndex!].tdList[tdIndex!] const rowIndex = td.rowIndex const colIndex = td.colIndex - // 计算表格行列信息 - const rowList = trList!.map(tr => tr.height) - const colList = colgroup!.map(col => col.width) - // 渲染行 + + // 渲染行工具 + const rowHeightList = trList!.map(tr => tr.height) const rowContainer = document.createElement('div') rowContainer.classList.add(`${EDITOR_PREFIX}-table-tool__row`) - rowContainer.style.transform = `translateX(-${this.translate * scale}px)` - for (let r = 0; r < rowList.length; r++) { - const rowHeight = rowList[r] * scale + rowContainer.style.transform = `translateX(-${this.ROW_COL_OFFSET * scale}px)` + for (let r = 0; r < rowHeightList.length; r++) { + const rowHeight = rowHeightList[r] * scale const rowItem = document.createElement('div') rowItem.classList.add(`${EDITOR_PREFIX}-table-tool__row__item`) if (r === rowIndex) { @@ -84,7 +99,6 @@ export class TableTool { this._mousedown({ evt, element, - position, index: r, order: TableOrder.ROW }) @@ -93,17 +107,18 @@ export class TableTool { rowItem.style.height = `${rowHeight}px` rowContainer.append(rowItem) } - rowContainer.style.left = `${leftTop[0]}px` - rowContainer.style.top = `${leftTop[1] + prePageHeight}px` + rowContainer.style.left = `${tableX}px` + rowContainer.style.top = `${tableY}px` this.container.append(rowContainer) this.toolRowContainer = rowContainer - // 渲染列 + // 渲染列工具 + const colWidthList = colgroup!.map(col => col.width) const colContainer = document.createElement('div') colContainer.classList.add(`${EDITOR_PREFIX}-table-tool__col`) - colContainer.style.transform = `translateY(-${this.translate * scale}px)` - for (let c = 0; c < colList.length; c++) { - const colHeight = colList[c] * scale + colContainer.style.transform = `translateY(-${this.ROW_COL_OFFSET * scale}px)` + for (let c = 0; c < colWidthList.length; c++) { + const colWidth = colWidthList[c] * scale const colItem = document.createElement('div') colItem.classList.add(`${EDITOR_PREFIX}-table-tool__col__item`) if (c === colIndex) { @@ -115,83 +130,70 @@ export class TableTool { this._mousedown({ evt, element, - position, index: c, order: TableOrder.COL }) } colItem.append(colItemAnchor) - colItem.style.width = `${colHeight}px` + colItem.style.width = `${colWidth}px` colContainer.append(colItem) } - colContainer.style.left = `${leftTop[0]}px` - colContainer.style.top = `${leftTop[1] + prePageHeight}px` + colContainer.style.left = `${tableX}px` + colContainer.style.top = `${tableY}px` this.container.append(colContainer) this.toolColContainer = colContainer - if (!trList?.length) return - - // 绘制边框拖拽 - const LINE_THRESHOLD_VALUE = 3 - const tableHeight = rowList.reduce((pre, cur) => pre + cur, 0) - const tableWidth = colList.reduce((pre, cur) => pre + cur, 0) - - // 渲染工具外部容器 - const tableLineTool = document.createElement('div') - tableLineTool.classList.add(`${EDITOR_PREFIX}-table-tool__line`) - tableLineTool.style.height = tableHeight * scale + 'px' - tableLineTool.style.width = tableWidth * scale + 'px' - tableLineTool.style.left = `${leftTop[0]}px` - tableLineTool.style.top = `${leftTop[1] + prePageHeight}px` - - for (let i = 0, len = trList.length || 0; i < len; i++) { - const tr = trList[i] - for (let j = 0; j < tr.tdList.length; j++) { - const td = tr.tdList[j] - const rowLine = document.createElement('div') - rowLine.classList.add(`${EDITOR_PREFIX}-table-tool__rline__resize`) - rowLine.dataset.rowIndex = `${td.rowIndex}` - rowLine.style.width = td.width! * scale + 'px' - rowLine.style.height = LINE_THRESHOLD_VALUE + 'px' - rowLine.style.top = td.y! * scale + td.height! * scale - LINE_THRESHOLD_VALUE / 2 + 'px' - rowLine.style.left = td.x! * scale + 'px' - rowLine.onmousedown = (evt) => { + // 渲染单元格边框拖拽工具 + const tableHeight = element.height! * scale + const tableWidth = element.width! * scale + const borderContainer = document.createElement('div') + borderContainer.classList.add(`${EDITOR_PREFIX}-table-tool__border`) + borderContainer.style.height = `${tableHeight}px` + borderContainer.style.width = `${tableWidth}px` + borderContainer.style.left = `${tableX}px` + borderContainer.style.top = `${tableY}px` + for (let r = 0; r < trList!.length; r++) { + const tr = trList![r] + for (let d = 0; d < tr.tdList.length; d++) { + const td = tr.tdList[d] + const rowBorder = document.createElement('div') + rowBorder.classList.add(`${EDITOR_PREFIX}-table-tool__border__row`) + rowBorder.style.width = `${td.width! * scale}px` + rowBorder.style.height = `${this.BORDER_VALUE}px` + rowBorder.style.top = `${(td.y! + td.height!) * scale - this.BORDER_VALUE / 2}px` + rowBorder.style.left = `${td.x! * scale}px` + rowBorder.onmousedown = (evt) => { this._mousedown({ evt, element, - position, - index: td.rowIndex || 0, + index: td.rowIndex!, order: TableOrder.ROW }) } - tableLineTool.appendChild(rowLine) - - const colLine = document.createElement('div') - colLine.classList.add(`${EDITOR_PREFIX}-table-tool__cline__resize`) - colLine.dataset.colIndex = `${td.colIndex}` - colLine.style.height = td.height! * scale + 'px' - colLine.style.width = LINE_THRESHOLD_VALUE + 'px' - colLine.style.left = td.x! * scale + (td.width! * scale) - LINE_THRESHOLD_VALUE / 2 + 'px' - colLine.style.top = td.y! * scale + 'px' - colLine.onmousedown = (evt) => { + borderContainer.appendChild(rowBorder) + const colBorder = document.createElement('div') + colBorder.classList.add(`${EDITOR_PREFIX}-table-tool__border__col`) + colBorder.style.width = `${this.BORDER_VALUE}px` + colBorder.style.height = `${td.height! * scale}px` + colBorder.style.top = `${td.y! * scale}px` + colBorder.style.left = `${(td.x! + td.width!) * scale - this.BORDER_VALUE / 2}px` + colBorder.onmousedown = (evt) => { this._mousedown({ evt, element, - position, - index: td.colIndex || 0, + index: td.colIndex!, order: TableOrder.COL }) } - tableLineTool.appendChild(colLine) + borderContainer.appendChild(colBorder) } } - - this.toolBox = tableLineTool - this.container.append(tableLineTool) + this.container.append(borderContainer) + this.toolBorderContainer = borderContainer } private _mousedown(payload: IAnchorMouseDown) { - const { evt, index, order, element, position } = payload + const { evt, index, order, element } = payload this.canvas = this.draw.getPage() const { scale } = this.options const width = this.draw.getWidth() @@ -253,10 +255,10 @@ export class TableTool { const curColWidth = colgroup[index].width // 最小移动距离计算 const moveColWidth = curColWidth + dx - const nextColWidth = colgroup[index + 1]?.width - // 如果移动距离小于最小宽度,或者大于当前列和下一列宽度之和,那么就不移动 - if (moveColWidth < this.minTdWidth || moveColWidth > curColWidth + nextColWidth) { - dx = this.minTdWidth - curColWidth + const nextColWidth = colgroup[index + 1]?.width || 0 + // 如果移动距离小于最小宽度,或者大于当前列和下一列宽度之和则移动最小宽度 + if (moveColWidth < this.MIN_TD_WIDTH || moveColWidth > curColWidth + nextColWidth) { + dx = this.MIN_TD_WIDTH - curColWidth } // 最大移动距离计算 let moveTableWidth = 0 @@ -290,7 +292,6 @@ export class TableTool { } if (isChangeSize) { this.draw.render({ isSetCursor: false }) - this.render(element, position) } // 还原副作用 anchorLine.remove() diff --git a/src/editor/core/event/handlers/mousedown.ts b/src/editor/core/event/handlers/mousedown.ts index fb4d196..37dd683 100644 --- a/src/editor/core/event/handlers/mousedown.ts +++ b/src/editor/core/event/handlers/mousedown.ts @@ -100,9 +100,7 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) { const tableTool = draw.getTableTool() tableTool.dispose() if (isTable && !isReadonly) { - const originalElementList = draw.getOriginalElementList() - const originalPositionList = position.getOriginalPositionList() - tableTool.render(originalElementList[index], originalPositionList[index]) + tableTool.render() } // 超链接 const hyperlinkParticle = draw.getHyperlinkParticle()