feat:merge cell & cancel merge cell
This commit is contained in:
@@ -308,6 +308,14 @@
|
||||
background-image: url(../../assets/images/delete-table.svg);
|
||||
}
|
||||
|
||||
.contextmenu-merge-cell {
|
||||
background-image: url(../../assets/images/merge-cell.svg);
|
||||
}
|
||||
|
||||
.contextmenu-merge-cancel-cell {
|
||||
background-image: url(../../assets/images/merge-cancel-cell.svg);
|
||||
}
|
||||
|
||||
.hyperlink-popup {
|
||||
min-width: 100px;
|
||||
font-size: 12px;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M6 1v1H2v11h4v1H2a1 1 0 01-1-1V2a1 1 0 011-1h4zm3 0h4a1 1 0 011 1v11a1 1 0 01-1 1H9v-1h4V2H9V1z"/><path fill-rule="nonzero" d="M6 1h1v4H6zm2 0h1v4H8z"/><path d="M3 7.5L5 6v3zm9 0L10 6v3z"/><path d="M4 7h3v1H4zm4 0h3v1H8z"/><path fill-rule="nonzero" d="M8 10h1v4H8zm-2 0h1v4H6z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 399 B |
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M6 1v1H2v11h4v1H2a1 1 0 01-1-1V2a1 1 0 011-1h4zm3 0h4a1 1 0 011 1v11a1 1 0 01-1 1H9v-1h4V2H9V1z"/><path fill-rule="nonzero" d="M6 1h1v4H6zm2 0h1v4H8z"/><path d="M8 7.5L10 6v3zm-1 0L5 6v3z"/><path d="M9 7h3v1H9zM3 7h3v1H3z"/><path fill-rule="nonzero" d="M8 10h1v4H8zm-2 0h1v4H6z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 400 B |
@@ -34,6 +34,8 @@ export class Command {
|
||||
private static deleteTableRow: Function
|
||||
private static deleteTableCol: Function
|
||||
private static deleteTable: Function
|
||||
private static mergeTableCell: Function
|
||||
private static cancelMergeTableCell: Function
|
||||
private static image: Function
|
||||
private static hyperlink: Function
|
||||
private static search: Function
|
||||
@@ -72,6 +74,8 @@ export class Command {
|
||||
Command.deleteTableRow = adapt.deleteTableRow.bind(adapt)
|
||||
Command.deleteTableCol = adapt.deleteTableCol.bind(adapt)
|
||||
Command.deleteTable = adapt.deleteTable.bind(adapt)
|
||||
Command.mergeTableCell = adapt.mergeTableCell.bind(adapt)
|
||||
Command.cancelMergeTableCell = adapt.cancelMergeTableCell.bind(adapt)
|
||||
Command.image = adapt.image.bind(adapt)
|
||||
Command.hyperlink = adapt.hyperlink.bind(adapt)
|
||||
Command.search = adapt.search.bind(adapt)
|
||||
@@ -201,6 +205,14 @@ export class Command {
|
||||
return Command.deleteTable()
|
||||
}
|
||||
|
||||
public executMergeTableCell() {
|
||||
return Command.mergeTableCell()
|
||||
}
|
||||
|
||||
public executCancelMergeTableCell() {
|
||||
return Command.cancelMergeTableCell()
|
||||
}
|
||||
|
||||
public executeHyperlink(payload: IElement) {
|
||||
return Command.hyperlink(payload)
|
||||
}
|
||||
|
||||
@@ -644,18 +644,185 @@ export class CommandAdapt {
|
||||
|
||||
public deleteTable() {
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (positionContext.isTable) {
|
||||
const originalElementList = this.draw.getOriginalElementList()
|
||||
originalElementList.splice(positionContext.index!, 1)
|
||||
const curIndex = positionContext.index! - 1
|
||||
this.position.setPositionContext({
|
||||
isTable: false,
|
||||
index: curIndex
|
||||
})
|
||||
this.range.setRange(curIndex, curIndex)
|
||||
this.draw.render({ curIndex })
|
||||
this.tableTool.dispose()
|
||||
if (!positionContext.isTable) return
|
||||
const originalElementList = this.draw.getOriginalElementList()
|
||||
originalElementList.splice(positionContext.index!, 1)
|
||||
const curIndex = positionContext.index! - 1
|
||||
this.position.setPositionContext({
|
||||
isTable: false,
|
||||
index: curIndex
|
||||
})
|
||||
this.range.setRange(curIndex, curIndex)
|
||||
this.draw.render({ curIndex })
|
||||
this.tableTool.dispose()
|
||||
}
|
||||
|
||||
public mergeTableCell() {
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (!positionContext.isTable) return
|
||||
const { isCrossRowCol, startTdIndex, endTdIndex, startTrIndex, endTrIndex } = this.range.getRange()
|
||||
if (!isCrossRowCol) return
|
||||
const { index } = positionContext
|
||||
const originalElementList = this.draw.getOriginalElementList()
|
||||
const element = originalElementList[index!]
|
||||
const curTrList = element.trList!
|
||||
let startTd = curTrList[startTrIndex!].tdList[startTdIndex!]
|
||||
let endTd = curTrList[endTrIndex!].tdList[endTdIndex!]
|
||||
// 交换起始位置
|
||||
if (startTd.x! > endTd.x! || startTd.y! > endTd.y!) {
|
||||
[startTd, endTd] = [endTd, startTd]
|
||||
}
|
||||
const startColIndex = startTd.colIndex!
|
||||
const endColIndex = endTd.colIndex! + (endTd.colspan - 1)
|
||||
const startRowIndex = startTd.rowIndex!
|
||||
const endRowIndex = endTd.rowIndex! + (endTd.rowspan - 1)
|
||||
// 选区行列
|
||||
let rowCol: ITd[][] = []
|
||||
for (let t = 0; t < curTrList.length; t++) {
|
||||
const tr = curTrList[t]
|
||||
const tdList: ITd[] = []
|
||||
for (let d = 0; d < tr.tdList.length; d++) {
|
||||
const td = tr.tdList[d]
|
||||
const tdColIndex = td.colIndex!
|
||||
const tdRowIndex = td.rowIndex!
|
||||
if (
|
||||
tdColIndex >= startColIndex && tdColIndex <= endColIndex
|
||||
&& tdRowIndex >= startRowIndex && tdRowIndex <= endRowIndex
|
||||
) {
|
||||
tdList.push(td)
|
||||
}
|
||||
}
|
||||
if (tdList.length) {
|
||||
rowCol.push(tdList)
|
||||
}
|
||||
}
|
||||
if (!rowCol.length) return
|
||||
// 是否是矩形
|
||||
const lastRow = rowCol[rowCol.length - 1]
|
||||
const leftTop = rowCol[0][0]
|
||||
const rightBottom = lastRow[lastRow.length - 1]
|
||||
const startX = leftTop.x!
|
||||
const startY = leftTop.y!
|
||||
const endX = rightBottom.x! + rightBottom.width!
|
||||
const endY = rightBottom.y! + rightBottom.height!
|
||||
for (let t = 0; t < rowCol.length; t++) {
|
||||
const tr = rowCol[t]
|
||||
for (let d = 0; d < tr.length; d++) {
|
||||
const td = tr[d]
|
||||
const tdStartX = td.x!
|
||||
const tdStartY = td.y!
|
||||
const tdEndX = tdStartX + td.width!
|
||||
const tdEndY = tdStartY + td.height!
|
||||
// 存在不符合项
|
||||
if (startX > tdStartX || startY > tdStartY || endX < tdEndX || endY < tdEndY) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
// 合并单元格
|
||||
let mergeTdIdList: string[] = []
|
||||
const anchorTd = rowCol[0][0]
|
||||
for (let t = 0; t < rowCol.length; t++) {
|
||||
const tr = rowCol[t]
|
||||
for (let d = 0; d < tr.length; d++) {
|
||||
const td = tr[d]
|
||||
const isAnchorTd = t === 0 && d === 0
|
||||
// 待删除单元id
|
||||
if (!isAnchorTd) {
|
||||
mergeTdIdList.push(td.id!)
|
||||
}
|
||||
// 列合并
|
||||
if (t === 0 && d !== 0) {
|
||||
anchorTd.colspan += td.colspan
|
||||
}
|
||||
// 行合并
|
||||
if (t !== 0) {
|
||||
if (anchorTd.colIndex === td.colIndex) {
|
||||
anchorTd.rowspan += td.rowspan
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 移除多余单元格
|
||||
for (let t = 0; t < curTrList.length; t++) {
|
||||
const tr = curTrList[t]
|
||||
let d = 0
|
||||
while (d < tr.tdList.length) {
|
||||
const td = tr.tdList[d]
|
||||
if (mergeTdIdList.includes(td.id!)) {
|
||||
tr.tdList.splice(d, 1)
|
||||
d--
|
||||
}
|
||||
d++
|
||||
}
|
||||
}
|
||||
// 重新渲染
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
this.range.setRange(startIndex, endIndex)
|
||||
this.draw.render({
|
||||
curIndex: endIndex
|
||||
})
|
||||
const position = this.position.getOriginalPositionList()
|
||||
this.tableTool.render(element, position[index!])
|
||||
}
|
||||
|
||||
public cancelMergeTableCell() {
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (!positionContext.isTable) return
|
||||
const { index, tdIndex, trIndex } = positionContext
|
||||
const originalElementList = this.draw.getOriginalElementList()
|
||||
const element = originalElementList[index!]
|
||||
const curTrList = element.trList!
|
||||
const curTr = curTrList[trIndex!]!
|
||||
const curTd = curTr.tdList[tdIndex!]
|
||||
if (curTd.rowspan === 1 && curTd.colspan === 1) return
|
||||
// 设置跨列
|
||||
if (curTd.colspan > 1) {
|
||||
for (let c = 1; c < curTd.colspan; c++) {
|
||||
const tdId = getUUID()
|
||||
curTr.tdList.splice(tdIndex! + c, 0, {
|
||||
id: tdId,
|
||||
rowspan: 1,
|
||||
colspan: 1,
|
||||
value: [{
|
||||
value: ZERO,
|
||||
size: 16,
|
||||
tableId: element.id,
|
||||
trId: curTr.id,
|
||||
tdId
|
||||
}]
|
||||
})
|
||||
}
|
||||
curTd.colspan = 1
|
||||
}
|
||||
// 设置跨行
|
||||
if (curTd.rowspan > 1) {
|
||||
for (let c = 1; c < curTd.rowspan; c++) {
|
||||
const tr = curTrList[trIndex! + c]
|
||||
const tdId = getUUID()
|
||||
tr.tdList.splice(curTd.colIndex!, 0, {
|
||||
id: tdId,
|
||||
rowspan: 1,
|
||||
colspan: 1,
|
||||
value: [{
|
||||
value: ZERO,
|
||||
size: 16,
|
||||
tableId: element.id,
|
||||
trId: tr.id,
|
||||
tdId
|
||||
}]
|
||||
})
|
||||
}
|
||||
curTd.rowspan = 1
|
||||
}
|
||||
// 重新渲染
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
this.range.setRange(startIndex, endIndex)
|
||||
this.draw.render({
|
||||
curIndex: endIndex
|
||||
})
|
||||
const position = this.position.getOriginalPositionList()
|
||||
this.tableTool.render(element, position[index!])
|
||||
}
|
||||
|
||||
public hyperlink(payload: IElement) {
|
||||
|
||||
@@ -81,7 +81,7 @@ export class ContextMenu {
|
||||
}
|
||||
|
||||
private _getContext(): IContextMenuContext {
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
const { isCrossRowCol: crossRowCol, startIndex, endIndex } = this.range.getRange()
|
||||
// 是否存在焦点
|
||||
const editorTextFocus = !!(~startIndex || ~endIndex)
|
||||
// 是否存在选区
|
||||
@@ -89,7 +89,14 @@ export class ContextMenu {
|
||||
// 是否在表格内
|
||||
const positionContext = this.position.getPositionContext()
|
||||
const isInTable = positionContext.isTable
|
||||
return { editorHasSelection, editorTextFocus, isInTable }
|
||||
// 是否存在跨行/列
|
||||
const isCrossRowCol = isInTable && !!crossRowCol
|
||||
return {
|
||||
editorHasSelection,
|
||||
editorTextFocus,
|
||||
isInTable,
|
||||
isCrossRowCol
|
||||
}
|
||||
}
|
||||
|
||||
private _createContextMenuContainer(): HTMLDivElement {
|
||||
|
||||
@@ -19,21 +19,24 @@ export const tableMenus: IRegisterContextMenu[] = [
|
||||
callback: (command: Command) => {
|
||||
command.executeInsertTableTopRow()
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: '下方插入1行',
|
||||
icon: 'insert-bottom-row',
|
||||
when: () => true,
|
||||
callback: (command: Command) => {
|
||||
command.executeInsertTableBottomRow()
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: '左侧插入1列',
|
||||
icon: 'insert-left-col',
|
||||
when: () => true,
|
||||
callback: (command: Command) => {
|
||||
command.executeInsertTableLeftCol()
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: '右侧插入1列',
|
||||
icon: 'insert-right-col',
|
||||
when: () => true,
|
||||
@@ -65,7 +68,8 @@ export const tableMenus: IRegisterContextMenu[] = [
|
||||
callback: (command: Command) => {
|
||||
command.executDeleteTableCol()
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: '删除整个表格',
|
||||
icon: 'delete-table',
|
||||
when: () => true,
|
||||
@@ -74,5 +78,25 @@ export const tableMenus: IRegisterContextMenu[] = [
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '合并单元格',
|
||||
icon: 'merge-cell',
|
||||
when: (payload) => {
|
||||
return payload.isCrossRowCol
|
||||
},
|
||||
callback: (command: Command) => {
|
||||
command.executMergeTableCell()
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '取消合并',
|
||||
icon: 'merge-cancel-cell',
|
||||
when: (payload) => {
|
||||
return payload.isInTable
|
||||
},
|
||||
callback: (command: Command) => {
|
||||
command.executCancelMergeTableCell()
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -475,6 +475,7 @@ export class Draw {
|
||||
private _drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload): IDrawRowResult {
|
||||
const { positionList, rowList, pageNo, startX, startY, startIndex, innerWidth } = payload
|
||||
const { scale, tdPadding } = this.options
|
||||
const { isCrossRowCol, tableId } = this.range.getRange()
|
||||
const tdGap = tdPadding * 2
|
||||
let x = startX
|
||||
let y = startY
|
||||
@@ -499,6 +500,7 @@ export class Draw {
|
||||
width: 0,
|
||||
height: 0
|
||||
}
|
||||
let tableRangeElement: IElement | null = null
|
||||
for (let j = 0; j < curRow.elementList.length; j++) {
|
||||
const element = curRow.elementList[j]
|
||||
const metrics = element.metrics
|
||||
@@ -527,6 +529,11 @@ export class Draw {
|
||||
this.textParticle.complete()
|
||||
this.imageParticle.render(ctx, element, x, y + offsetY)
|
||||
} else if (element.type === ElementType.TABLE) {
|
||||
if (isCrossRowCol) {
|
||||
rangeRecord.x = x
|
||||
rangeRecord.y = y
|
||||
tableRangeElement = element
|
||||
}
|
||||
this.tableParticle.render(ctx, element, x, y)
|
||||
} else if (element.type === ElementType.HYPERLINK) {
|
||||
this.textParticle.complete()
|
||||
@@ -602,6 +609,9 @@ export class Draw {
|
||||
const { x, y, width, height } = rangeRecord
|
||||
this.range.render(ctx, x, y, width, height)
|
||||
}
|
||||
if (isCrossRowCol && tableRangeElement && tableRangeElement.id === tableId) {
|
||||
this.tableParticle.drawRange(ctx, tableRangeElement, x, y)
|
||||
}
|
||||
x = startX
|
||||
y += curRow.height
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { IElement } from "../../../.."
|
||||
import { ElementType, IElement } from "../../../.."
|
||||
import { IEditorOption } from "../../../../interface/Editor"
|
||||
import { RangeManager } from "../../../range/RangeManager"
|
||||
import { Draw } from "../../Draw"
|
||||
|
||||
export class TableParticle {
|
||||
|
||||
private range: RangeManager
|
||||
private options: Required<IEditorOption>
|
||||
|
||||
constructor(draw: Draw) {
|
||||
this.range = draw.getRange()
|
||||
this.options = draw.getOptions()
|
||||
}
|
||||
|
||||
@@ -20,16 +23,6 @@ export class TableParticle {
|
||||
ctx.stroke()
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
private _drawRange(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) {
|
||||
const { rangeAlpha, rangeColor } = this.options
|
||||
ctx.save()
|
||||
ctx.globalAlpha = rangeAlpha
|
||||
ctx.fillStyle = rangeColor
|
||||
ctx.fillRect(x, y, width, height)
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
public computeRowColInfo(element: IElement) {
|
||||
const { colgroup, trList } = element
|
||||
if (!colgroup || !trList) return
|
||||
@@ -60,7 +53,7 @@ export class TableParticle {
|
||||
if (pTdX > x) break
|
||||
if (pTd.x === x && pTdY + pTdHeight > y) {
|
||||
x += pTdWidth
|
||||
offsetXIndex += 1
|
||||
offsetXIndex += pTd.colspan
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,6 +115,47 @@ export class TableParticle {
|
||||
}
|
||||
}
|
||||
|
||||
public drawRange(ctx: CanvasRenderingContext2D, element: IElement, startX: number, startY: number) {
|
||||
const { scale, rangeAlpha, rangeColor } = this.options
|
||||
const { type, trList } = element
|
||||
if (!trList || type !== ElementType.TABLE) return
|
||||
const { isCrossRowCol, startTdIndex, endTdIndex, startTrIndex, endTrIndex } = this.range.getRange()
|
||||
// 存在跨行/列
|
||||
if (!isCrossRowCol) return
|
||||
let startTd = trList[startTrIndex!].tdList[startTdIndex!]
|
||||
let endTd = trList[endTrIndex!].tdList[endTdIndex!]
|
||||
// 交换起始位置
|
||||
if (startTd.x! > endTd.x! || startTd.y! > endTd.y!) {
|
||||
[startTd, endTd] = [endTd, startTd]
|
||||
}
|
||||
const startColIndex = startTd.colIndex!
|
||||
const endColIndex = endTd.colIndex! + (endTd.colspan - 1)
|
||||
const startRowIndex = startTd.rowIndex!
|
||||
const endRowIndex = endTd.rowIndex! + (endTd.rowspan - 1)
|
||||
ctx.save()
|
||||
for (let t = 0; t < trList.length; t++) {
|
||||
const tr = trList[t]
|
||||
for (let d = 0; d < tr.tdList.length; d++) {
|
||||
const td = tr.tdList[d]
|
||||
const tdColIndex = td.colIndex!
|
||||
const tdRowIndex = td.rowIndex!
|
||||
if (
|
||||
tdColIndex >= startColIndex && tdColIndex <= endColIndex
|
||||
&& tdRowIndex >= startRowIndex && tdRowIndex <= endRowIndex
|
||||
) {
|
||||
const x = td.x! * scale
|
||||
const y = td.y! * scale
|
||||
const width = td.width! * scale
|
||||
const height = td.height! * scale
|
||||
ctx.globalAlpha = rangeAlpha
|
||||
ctx.fillStyle = rangeColor
|
||||
ctx.fillRect(x + startX, y + startY, width, height)
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
public render(ctx: CanvasRenderingContext2D, element: IElement, startX: number, startY: number) {
|
||||
const { colgroup, trList } = element
|
||||
if (!colgroup || !trList) return
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ElementStyleKey } from "../../dataset/enum/ElementStyle"
|
||||
import { MouseEventButton } from "../../dataset/enum/Event"
|
||||
import { KeyMap } from "../../dataset/enum/Keymap"
|
||||
import { IElement } from "../../interface/Element"
|
||||
import { ICurrentPosition } from "../../interface/Position"
|
||||
import { writeTextByElementList } from "../../utils/clipboard"
|
||||
import { Cursor } from "../cursor/Cursor"
|
||||
import { Draw } from "../draw/Draw"
|
||||
@@ -19,7 +20,7 @@ export class CanvasEvent {
|
||||
|
||||
private isAllowDrag: boolean
|
||||
private isCompositing: boolean
|
||||
private mouseDownStartIndex: number
|
||||
private mouseDownStartPosition: ICurrentPosition | null
|
||||
|
||||
private draw: Draw
|
||||
private pageContainer: HTMLDivElement
|
||||
@@ -35,7 +36,7 @@ export class CanvasEvent {
|
||||
constructor(draw: Draw) {
|
||||
this.isAllowDrag = false
|
||||
this.isCompositing = false
|
||||
this.mouseDownStartIndex = 0
|
||||
this.mouseDownStartPosition = null
|
||||
|
||||
this.pageContainer = draw.getPageContainer()
|
||||
this.pageList = draw.getPageList()
|
||||
@@ -81,7 +82,7 @@ export class CanvasEvent {
|
||||
}
|
||||
|
||||
public mousemove(evt: MouseEvent) {
|
||||
if (!this.isAllowDrag) return
|
||||
if (!this.isAllowDrag || !this.mouseDownStartPosition) return
|
||||
const target = evt.target as HTMLDivElement
|
||||
const pageIndex = target.dataset.index
|
||||
// 设置pageNo
|
||||
@@ -93,16 +94,42 @@ export class CanvasEvent {
|
||||
x: evt.offsetX,
|
||||
y: evt.offsetY
|
||||
})
|
||||
const { index, isTable, tdValueIndex } = positionResult
|
||||
const {
|
||||
index,
|
||||
isTable,
|
||||
tdValueIndex,
|
||||
tdIndex,
|
||||
trIndex,
|
||||
tableId
|
||||
} = positionResult
|
||||
const {
|
||||
index: startIndex,
|
||||
isTable: startIsTable,
|
||||
tdIndex: startTdIndex,
|
||||
trIndex: startTrIndex
|
||||
} = this.mouseDownStartPosition
|
||||
let endIndex = isTable ? tdValueIndex! : index
|
||||
let end = ~endIndex ? endIndex : 0
|
||||
// 开始位置
|
||||
let start = this.mouseDownStartIndex
|
||||
if (start > end) {
|
||||
[start, end] = [end, start]
|
||||
// 判断是否是表格跨行/列
|
||||
if (isTable && startIsTable && (tdIndex !== startTdIndex || trIndex !== startTrIndex)) {
|
||||
this.range.setRange(
|
||||
endIndex,
|
||||
endIndex,
|
||||
tableId,
|
||||
startTdIndex,
|
||||
tdIndex,
|
||||
startTrIndex,
|
||||
trIndex
|
||||
)
|
||||
} else {
|
||||
let end = ~endIndex ? endIndex : 0
|
||||
// 开始位置
|
||||
let start = startIndex
|
||||
if (start > end) {
|
||||
[start, end] = [end, start]
|
||||
}
|
||||
if (start === end) return
|
||||
this.range.setRange(start, end)
|
||||
}
|
||||
if (start === end) return
|
||||
this.range.setRange(start, end)
|
||||
// 绘制
|
||||
this.draw.render({
|
||||
isSubmitHistory: false,
|
||||
@@ -147,7 +174,10 @@ export class CanvasEvent {
|
||||
tableId
|
||||
})
|
||||
// 记录选区开始位置
|
||||
this.mouseDownStartIndex = isTable ? tdValueIndex! : index
|
||||
this.mouseDownStartPosition = {
|
||||
...positionResult,
|
||||
index: isTable ? tdValueIndex! : index
|
||||
}
|
||||
// 绘制
|
||||
const isDirectHitImage = isDirectHit && isImage
|
||||
if (~index) {
|
||||
|
||||
@@ -35,9 +35,23 @@ export class RangeManager {
|
||||
return elementList.slice(startIndex + 1, endIndex + 1)
|
||||
}
|
||||
|
||||
public setRange(startIndex: number, endIndex: number) {
|
||||
public setRange(
|
||||
startIndex: number,
|
||||
endIndex: number,
|
||||
tableId?: string,
|
||||
startTdIndex?: number,
|
||||
endTdIndex?: number,
|
||||
startTrIndex?: number,
|
||||
endTrIndex?: number
|
||||
) {
|
||||
this.range.startIndex = startIndex
|
||||
this.range.endIndex = endIndex
|
||||
this.range.tableId = tableId
|
||||
this.range.startTdIndex = startTdIndex
|
||||
this.range.endTdIndex = endTdIndex
|
||||
this.range.startTrIndex = startTrIndex
|
||||
this.range.endTrIndex = endTrIndex
|
||||
this.range.isCrossRowCol = !!(startTdIndex || endTdIndex || startTrIndex || endTrIndex)
|
||||
}
|
||||
|
||||
public setRangeStyle() {
|
||||
@@ -50,6 +64,7 @@ export class RangeManager {
|
||||
curElementList = [elementList[index]]
|
||||
}
|
||||
const curElement = curElementList[curElementList.length - 1]
|
||||
if (!curElement) return
|
||||
// 富文本
|
||||
const font = curElement.font || this.options.defaultFont
|
||||
let bold = !~curElementList.findIndex(el => !el.bold)
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
export interface IRange {
|
||||
startIndex: number;
|
||||
endIndex: number;
|
||||
isCrossRowCol?: boolean;
|
||||
tableId?: string;
|
||||
startTdIndex?: number;
|
||||
endTdIndex?: number;
|
||||
startTrIndex?: number;
|
||||
endTrIndex?: number;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ export interface IContextMenuContext {
|
||||
editorHasSelection: boolean;
|
||||
editorTextFocus: boolean;
|
||||
isInTable: boolean;
|
||||
isCrossRowCol: boolean;
|
||||
}
|
||||
|
||||
export interface IRegisterContextMenu {
|
||||
|
||||
Reference in New Issue
Block a user