improve:position compute separate from draw row
This commit is contained in:
@@ -118,7 +118,7 @@ export class CommandAdapt {
|
|||||||
const isCollapsed = startIndex === endIndex
|
const isCollapsed = startIndex === endIndex
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
curIndex: isCollapsed ? startIndex : undefined,
|
curIndex: isCollapsed ? startIndex : undefined,
|
||||||
isComputeRowList: false,
|
isCompute: false,
|
||||||
isSubmitHistory: false,
|
isSubmitHistory: false,
|
||||||
isSetCursor: isCollapsed
|
isSetCursor: isCollapsed
|
||||||
})
|
})
|
||||||
@@ -1092,7 +1092,7 @@ export class CommandAdapt {
|
|||||||
const { endIndex } = this.range.getRange()
|
const { endIndex } = this.range.getRange()
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
curIndex: endIndex,
|
curIndex: endIndex,
|
||||||
isComputeRowList: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1112,7 +1112,7 @@ export class CommandAdapt {
|
|||||||
const { endIndex } = this.range.getRange()
|
const { endIndex } = this.range.getRange()
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
curIndex: endIndex,
|
curIndex: endIndex,
|
||||||
isComputeRowList: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+96
-109
@@ -1,11 +1,11 @@
|
|||||||
import { version } from '../../../../package.json'
|
import { version } from '../../../../package.json'
|
||||||
import { ZERO } from '../../dataset/constant/Common'
|
import { ZERO } from '../../dataset/constant/Common'
|
||||||
import { RowFlex } from '../../dataset/enum/Row'
|
import { RowFlex } from '../../dataset/enum/Row'
|
||||||
import { IDrawOption, IDrawRowPayload, IDrawRowResult, IPainterOptions } from '../../interface/Draw'
|
import { IDrawOption, IDrawRowPayload, IPainterOptions } from '../../interface/Draw'
|
||||||
import { IEditorOption, IEditorResult } from '../../interface/Editor'
|
import { IEditorOption, IEditorResult } from '../../interface/Editor'
|
||||||
import { IElement, IElementMetrics, IElementPosition, IElementFillRect, IElementStyle } from '../../interface/Element'
|
import { IElement, IElementMetrics, IElementPosition, IElementFillRect, IElementStyle } from '../../interface/Element'
|
||||||
import { IRow, IRowElement } from '../../interface/Row'
|
import { IRow, IRowElement } from '../../interface/Row'
|
||||||
import { deepClone, getUUID } from '../../utils'
|
import { deepClone, getUUID, nextTick } from '../../utils'
|
||||||
import { Cursor } from '../cursor/Cursor'
|
import { Cursor } from '../cursor/Cursor'
|
||||||
import { CanvasEvent } from '../event/CanvasEvent'
|
import { CanvasEvent } from '../event/CanvasEvent'
|
||||||
import { GlobalEvent } from '../event/GlobalEvent'
|
import { GlobalEvent } from '../event/GlobalEvent'
|
||||||
@@ -98,6 +98,7 @@ export class Draw {
|
|||||||
private selectionObserver: SelectionObserver
|
private selectionObserver: SelectionObserver
|
||||||
|
|
||||||
private rowList: IRow[]
|
private rowList: IRow[]
|
||||||
|
private pageRowList: IRow[][]
|
||||||
private painterStyle: IElementStyle | null
|
private painterStyle: IElementStyle | null
|
||||||
private painterOptions: IPainterOptions | null
|
private painterOptions: IPainterOptions | null
|
||||||
private visiblePageNoList: number[]
|
private visiblePageNoList: number[]
|
||||||
@@ -163,6 +164,7 @@ export class Draw {
|
|||||||
this.workerManager = new WorkerManager(this)
|
this.workerManager = new WorkerManager(this)
|
||||||
|
|
||||||
this.rowList = []
|
this.rowList = []
|
||||||
|
this.pageRowList = []
|
||||||
this.painterStyle = null
|
this.painterStyle = null
|
||||||
this.painterOptions = null
|
this.painterOptions = null
|
||||||
this.visiblePageNoList = []
|
this.visiblePageNoList = []
|
||||||
@@ -290,6 +292,14 @@ export class Draw {
|
|||||||
return this.pageList
|
return this.pageList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getRowList(): IRow[] {
|
||||||
|
return this.rowList
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPageRowList(): IRow[][] {
|
||||||
|
return this.pageRowList
|
||||||
|
}
|
||||||
|
|
||||||
public getCtx(): CanvasRenderingContext2D {
|
public getCtx(): CanvasRenderingContext2D {
|
||||||
return this.ctxList[this.pageNo]
|
return this.ctxList[this.pageNo]
|
||||||
}
|
}
|
||||||
@@ -596,7 +606,6 @@ export class Draw {
|
|||||||
private _computeRowList(innerWidth: number, elementList: IElement[]) {
|
private _computeRowList(innerWidth: number, elementList: IElement[]) {
|
||||||
const { defaultSize, defaultRowMargin, scale, tdPadding, defaultTabWidth } = this.options
|
const { defaultSize, defaultRowMargin, scale, tdPadding, defaultTabWidth } = this.options
|
||||||
const defaultBasicRowMarginHeight = this.getDefaultBasicRowMarginHeight()
|
const defaultBasicRowMarginHeight = this.getDefaultBasicRowMarginHeight()
|
||||||
const tdGap = tdPadding * 2
|
|
||||||
const canvas = document.createElement('canvas')
|
const canvas = document.createElement('canvas')
|
||||||
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
|
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
|
||||||
const rowList: IRow[] = []
|
const rowList: IRow[] = []
|
||||||
@@ -606,6 +615,7 @@ export class Draw {
|
|||||||
height: 0,
|
height: 0,
|
||||||
ascent: 0,
|
ascent: 0,
|
||||||
elementList: [],
|
elementList: [],
|
||||||
|
startIndex: 0,
|
||||||
rowFlex: elementList?.[1]?.rowFlex
|
rowFlex: elementList?.[1]?.rowFlex
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -639,6 +649,7 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
metrics.boundingBoxAscent = 0
|
metrics.boundingBoxAscent = 0
|
||||||
} else if (element.type === ElementType.TABLE) {
|
} else if (element.type === ElementType.TABLE) {
|
||||||
|
const tdGap = tdPadding * 2
|
||||||
// 计算表格行列
|
// 计算表格行列
|
||||||
this.tableParticle.computeRowColInfo(element)
|
this.tableParticle.computeRowColInfo(element)
|
||||||
// 计算表格内元素信息
|
// 计算表格内元素信息
|
||||||
@@ -817,6 +828,7 @@ export class Draw {
|
|||||||
rowList.push({
|
rowList.push({
|
||||||
width: metrics.width,
|
width: metrics.width,
|
||||||
height,
|
height,
|
||||||
|
startIndex: i,
|
||||||
elementList: [rowElement],
|
elementList: [rowElement],
|
||||||
ascent,
|
ascent,
|
||||||
rowFlex: elementList[i + 1]?.rowFlex,
|
rowFlex: elementList[i + 1]?.rowFlex,
|
||||||
@@ -838,6 +850,45 @@ export class Draw {
|
|||||||
return rowList
|
return rowList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _computePageList(): IRow[][] {
|
||||||
|
const pageRowList: IRow[][] = [[]]
|
||||||
|
const { pageMode } = this.options
|
||||||
|
const height = this.getHeight()
|
||||||
|
const margins = this.getMargins()
|
||||||
|
const marginHeight = margins[0] + margins[2]
|
||||||
|
let pageHeight = marginHeight
|
||||||
|
let pageNo = 0
|
||||||
|
if (pageMode === PageMode.CONTINUITY) {
|
||||||
|
pageRowList[0] = this.rowList
|
||||||
|
// 重置高度
|
||||||
|
pageHeight += this.rowList.reduce((pre, cur) => pre + cur.height, 0)
|
||||||
|
const dpr = window.devicePixelRatio
|
||||||
|
const pageDom = this.pageList[0]
|
||||||
|
const pageDomHeight = Number(pageDom.style.height.replace('px', ''))
|
||||||
|
if (pageHeight > pageDomHeight) {
|
||||||
|
pageDom.style.height = `${pageHeight}px`
|
||||||
|
pageDom.height = pageHeight * dpr
|
||||||
|
} else {
|
||||||
|
const reduceHeight = pageHeight < height ? height : pageHeight
|
||||||
|
pageDom.style.height = `${reduceHeight}px`
|
||||||
|
pageDom.height = reduceHeight * dpr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < this.rowList.length; i++) {
|
||||||
|
const row = this.rowList[i]
|
||||||
|
if (row.height + pageHeight > height || this.rowList[i - 1]?.isPageBreak) {
|
||||||
|
pageHeight = marginHeight + row.height
|
||||||
|
pageRowList.push([row])
|
||||||
|
pageNo++
|
||||||
|
} else {
|
||||||
|
pageHeight += row.height
|
||||||
|
pageRowList[pageNo].push(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pageRowList
|
||||||
|
}
|
||||||
|
|
||||||
private _drawRichText(ctx: CanvasRenderingContext2D) {
|
private _drawRichText(ctx: CanvasRenderingContext2D) {
|
||||||
this.underline.render(ctx)
|
this.underline.render(ctx)
|
||||||
this.strikeout.render(ctx)
|
this.strikeout.render(ctx)
|
||||||
@@ -845,25 +896,13 @@ export class Draw {
|
|||||||
this.textParticle.complete()
|
this.textParticle.complete()
|
||||||
}
|
}
|
||||||
|
|
||||||
private _drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload): IDrawRowResult {
|
private _drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload) {
|
||||||
const { positionList, rowList, pageNo, startX, startY, startIndex, innerWidth } = payload
|
const { rowList, pageNo, positionList, startIndex } = payload
|
||||||
const { scale, tdPadding } = this.options
|
const { scale, tdPadding } = this.options
|
||||||
const { isCrossRowCol, tableId } = this.range.getRange()
|
const { isCrossRowCol, tableId } = this.range.getRange()
|
||||||
const tdGap = tdPadding * 2
|
|
||||||
let x = startX
|
|
||||||
let y = startY
|
|
||||||
let index = startIndex
|
let index = startIndex
|
||||||
for (let i = 0; i < rowList.length; i++) {
|
for (let i = 0; i < rowList.length; i++) {
|
||||||
const curRow = rowList[i]
|
const curRow = rowList[i]
|
||||||
// 计算行偏移量(行居中、居右)
|
|
||||||
if (curRow.rowFlex === RowFlex.CENTER) {
|
|
||||||
x += (innerWidth - curRow.width) / 2
|
|
||||||
} else if (curRow.rowFlex === RowFlex.RIGHT) {
|
|
||||||
x += innerWidth - curRow.width
|
|
||||||
}
|
|
||||||
// 当前td所在位置
|
|
||||||
const tablePreX = x
|
|
||||||
const tablePreY = y
|
|
||||||
// 选区绘制记录
|
// 选区绘制记录
|
||||||
const rangeRecord: IElementFillRect = {
|
const rangeRecord: IElementFillRect = {
|
||||||
x: 0,
|
x: 0,
|
||||||
@@ -875,28 +914,13 @@ export class Draw {
|
|||||||
for (let j = 0; j < curRow.elementList.length; j++) {
|
for (let j = 0; j < curRow.elementList.length; j++) {
|
||||||
const element = curRow.elementList[j]
|
const element = curRow.elementList[j]
|
||||||
const metrics = element.metrics
|
const metrics = element.metrics
|
||||||
const offsetY =
|
// 当前元素位置信息
|
||||||
(element.imgDisplay !== ImageDisplay.INLINE && element.type === ElementType.IMAGE)
|
const {
|
||||||
|| element.type === ElementType.LATEX
|
|
||||||
? curRow.ascent - metrics.height
|
|
||||||
: curRow.ascent
|
|
||||||
const positionItem: IElementPosition = {
|
|
||||||
pageNo,
|
|
||||||
index,
|
|
||||||
value: element.value,
|
|
||||||
rowNo: i,
|
|
||||||
metrics,
|
|
||||||
ascent: offsetY,
|
ascent: offsetY,
|
||||||
lineHeight: curRow.height,
|
|
||||||
isLastLetter: j === curRow.elementList.length - 1,
|
|
||||||
coordinate: {
|
coordinate: {
|
||||||
leftTop: [x, y],
|
leftTop: [x, y]
|
||||||
leftBottom: [x, y + curRow.height],
|
|
||||||
rightTop: [x + metrics.width, y],
|
|
||||||
rightBottom: [x + metrics.width, y + curRow.height]
|
|
||||||
}
|
}
|
||||||
}
|
} = positionList[curRow.startIndex + j]
|
||||||
positionList.push(positionItem)
|
|
||||||
// 元素绘制
|
// 元素绘制
|
||||||
if (element.type === ElementType.IMAGE) {
|
if (element.type === ElementType.IMAGE) {
|
||||||
this._drawRichText(ctx)
|
this._drawRichText(ctx)
|
||||||
@@ -1001,30 +1025,22 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
index++
|
index++
|
||||||
x += metrics.width
|
|
||||||
// 绘制表格内元素
|
// 绘制表格内元素
|
||||||
if (element.type === ElementType.TABLE) {
|
if (element.type === ElementType.TABLE) {
|
||||||
|
const tdGap = tdPadding * 2
|
||||||
for (let t = 0; t < element.trList!.length; t++) {
|
for (let t = 0; t < element.trList!.length; t++) {
|
||||||
const tr = element.trList![t]
|
const tr = element.trList![t]
|
||||||
for (let d = 0; d < tr.tdList!.length; d++) {
|
for (let d = 0; d < tr.tdList!.length; d++) {
|
||||||
const td = tr.tdList[d]
|
const td = tr.tdList[d]
|
||||||
td.positionList = []
|
this._drawRow(ctx, {
|
||||||
const drawRowResult = this._drawRow(ctx, {
|
positionList: td.positionList!,
|
||||||
positionList: td.positionList,
|
|
||||||
rowList: td.rowList!,
|
rowList: td.rowList!,
|
||||||
pageNo,
|
pageNo,
|
||||||
startIndex: 0,
|
startIndex: 0,
|
||||||
startX: (td.x! + tdPadding) * scale + tablePreX,
|
|
||||||
startY: td.y! * scale + tablePreY,
|
|
||||||
innerWidth: (td.width! - tdGap) * scale
|
innerWidth: (td.width! - tdGap) * scale
|
||||||
})
|
})
|
||||||
x = drawRowResult.x
|
|
||||||
y = drawRowResult.y
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 恢复初始x、y
|
|
||||||
x = tablePreX
|
|
||||||
y = tablePreY
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 绘制富文本及文字
|
// 绘制富文本及文字
|
||||||
@@ -1035,12 +1051,10 @@ export class Draw {
|
|||||||
this.range.render(ctx, x, y, width, height)
|
this.range.render(ctx, x, y, width, height)
|
||||||
}
|
}
|
||||||
if (isCrossRowCol && tableRangeElement && tableRangeElement.id === tableId) {
|
if (isCrossRowCol && tableRangeElement && tableRangeElement.id === tableId) {
|
||||||
|
const { coordinate: { leftTop: [x, y] } } = positionList[curRow.startIndex]
|
||||||
this.tableParticle.drawRange(ctx, tableRangeElement, x, y)
|
this.tableParticle.drawRange(ctx, tableRangeElement, x, y)
|
||||||
}
|
}
|
||||||
x = startX
|
|
||||||
y += curRow.height
|
|
||||||
}
|
}
|
||||||
return { x, y, index }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _clearPage(pageNo: number) {
|
private _clearPage(pageNo: number) {
|
||||||
@@ -1052,31 +1066,22 @@ export class Draw {
|
|||||||
|
|
||||||
private _drawPage(positionList: IElementPosition[], rowList: IRow[], pageNo: number) {
|
private _drawPage(positionList: IElementPosition[], rowList: IRow[], pageNo: number) {
|
||||||
const { pageMode } = this.options
|
const { pageMode } = this.options
|
||||||
const margins = this.getMargins()
|
|
||||||
const innerWidth = this.getInnerWidth()
|
const innerWidth = this.getInnerWidth()
|
||||||
const ctx = this.ctxList[pageNo]
|
const ctx = this.ctxList[pageNo]
|
||||||
this._clearPage(pageNo)
|
this._clearPage(pageNo)
|
||||||
// 绘制背景
|
// 绘制背景
|
||||||
this.background.render(ctx)
|
this.background.render(ctx)
|
||||||
// 绘制页边距
|
// 绘制页边距
|
||||||
const leftTopPoint: [number, number] = [margins[3], margins[0]]
|
|
||||||
this.margin.render(ctx)
|
this.margin.render(ctx)
|
||||||
// 渲染元素
|
// 渲染元素
|
||||||
let x = leftTopPoint[0]
|
const index = rowList[0].startIndex
|
||||||
let y = leftTopPoint[1]
|
this._drawRow(ctx, {
|
||||||
let index = positionList.length
|
|
||||||
const drawRowResult = this._drawRow(ctx, {
|
|
||||||
positionList,
|
positionList,
|
||||||
rowList,
|
rowList,
|
||||||
pageNo,
|
pageNo,
|
||||||
startIndex: index,
|
startIndex: index,
|
||||||
startX: x,
|
|
||||||
startY: y,
|
|
||||||
innerWidth
|
innerWidth
|
||||||
})
|
})
|
||||||
x = drawRowResult.x
|
|
||||||
y = drawRowResult.y
|
|
||||||
index = drawRowResult.index
|
|
||||||
// 绘制页眉
|
// 绘制页眉
|
||||||
this.header.render(ctx)
|
this.header.render(ctx)
|
||||||
// 绘制页码
|
// 绘制页码
|
||||||
@@ -1092,72 +1097,54 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render(payload?: IDrawOption) {
|
public render(payload?: IDrawOption) {
|
||||||
const { pageMode } = this.options
|
|
||||||
const {
|
const {
|
||||||
isSubmitHistory = true,
|
isSubmitHistory = true,
|
||||||
isSetCursor = true,
|
isSetCursor = true,
|
||||||
isComputeRowList = true
|
isCompute = true
|
||||||
} = payload || {}
|
} = payload || {}
|
||||||
let { curIndex } = payload || {}
|
let { curIndex } = payload || {}
|
||||||
const height = this.getHeight()
|
|
||||||
const innerWidth = this.getInnerWidth()
|
const innerWidth = this.getInnerWidth()
|
||||||
// 计算行信息
|
// 计算文档信息
|
||||||
if (isComputeRowList) {
|
if (isCompute) {
|
||||||
|
// 行信息
|
||||||
this.rowList = this._computeRowList(innerWidth, this.elementList)
|
this.rowList = this._computeRowList(innerWidth, this.elementList)
|
||||||
|
// 页面信息
|
||||||
|
this.pageRowList = this._computePageList()
|
||||||
|
// 位置信息
|
||||||
|
this.position.computePositionList()
|
||||||
|
// 搜索信息
|
||||||
const searchKeyword = this.search.getSearchKeyword()
|
const searchKeyword = this.search.getSearchKeyword()
|
||||||
if (searchKeyword) {
|
if (searchKeyword) {
|
||||||
this.search.compute(searchKeyword)
|
this.search.compute(searchKeyword)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 清除光标等副作用
|
// 清除光标
|
||||||
this.cursor.recoveryCursor()
|
this.cursor.recoveryCursor()
|
||||||
this.position.setPositionList([])
|
|
||||||
const positionList = this.position.getOriginalPositionList()
|
|
||||||
// 按页渲染
|
|
||||||
const margins = this.getMargins()
|
|
||||||
const marginHeight = margins[0] + margins[2]
|
|
||||||
let pageHeight = marginHeight
|
|
||||||
let pageNo = 0
|
|
||||||
const pageRowList: IRow[][] = [[]]
|
|
||||||
if (pageMode === PageMode.CONTINUITY) {
|
|
||||||
pageRowList[0] = this.rowList
|
|
||||||
// 重置高度
|
|
||||||
pageHeight += this.rowList.reduce((pre, cur) => pre + cur.height, 0)
|
|
||||||
const dpr = window.devicePixelRatio
|
|
||||||
const pageDom = this.pageList[0]
|
|
||||||
const pageDomHeight = Number(pageDom.style.height.replace('px', ''))
|
|
||||||
if (pageHeight > pageDomHeight) {
|
|
||||||
pageDom.style.height = `${pageHeight}px`
|
|
||||||
pageDom.height = pageHeight * dpr
|
|
||||||
} else {
|
|
||||||
const reduceHeight = pageHeight < height ? height : pageHeight
|
|
||||||
pageDom.style.height = `${reduceHeight}px`
|
|
||||||
pageDom.height = reduceHeight * dpr
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (let i = 0; i < this.rowList.length; i++) {
|
|
||||||
const row = this.rowList[i]
|
|
||||||
if (row.height + pageHeight > height || this.rowList[i - 1]?.isPageBreak) {
|
|
||||||
pageHeight = marginHeight + row.height
|
|
||||||
pageRowList.push([row])
|
|
||||||
pageNo++
|
|
||||||
} else {
|
|
||||||
pageHeight += row.height
|
|
||||||
pageRowList[pageNo].push(row)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 绘制元素
|
// 绘制元素
|
||||||
for (let i = 0; i < pageRowList.length; i++) {
|
const positionList = this.position.getOriginalPositionList()
|
||||||
|
const { visiblePageNoList } = this.scrollObserver.getPageVisibleInfo()
|
||||||
|
const minPageNo = visiblePageNoList[0]
|
||||||
|
const maxPageNo = visiblePageNoList[visiblePageNoList.length - 1]
|
||||||
|
for (let i = 0; i < this.pageRowList.length; i++) {
|
||||||
if (!this.pageList[i]) {
|
if (!this.pageList[i]) {
|
||||||
this._createPage(i)
|
this._createPage(i)
|
||||||
}
|
}
|
||||||
const rowList = pageRowList[i]
|
// 优先绘制可见页
|
||||||
this._drawPage(positionList, rowList, i)
|
if (i >= minPageNo && i <= maxPageNo) {
|
||||||
|
this._drawPage(positionList, this.pageRowList[i], i)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// 渲染后续不可见页
|
||||||
|
nextTick(() => {
|
||||||
|
for (let i = 0; i < this.pageRowList.length; i++) {
|
||||||
|
if (i < minPageNo || i > maxPageNo) {
|
||||||
|
this._drawPage(positionList, this.pageRowList[i], i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
// 移除多余页
|
// 移除多余页
|
||||||
setTimeout(() => {
|
nextTick(() => {
|
||||||
const curPageCount = pageRowList.length
|
const curPageCount = this.pageRowList.length
|
||||||
const prePageCount = this.pageList.length
|
const prePageCount = this.pageList.length
|
||||||
if (prePageCount > curPageCount) {
|
if (prePageCount > curPageCount) {
|
||||||
const deleteCount = prePageCount - curPageCount
|
const deleteCount = prePageCount - curPageCount
|
||||||
@@ -1205,7 +1192,7 @@ export class Draw {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 页面尺寸改变
|
// 页面尺寸改变
|
||||||
if (this.listener.pageSizeChange) {
|
if (this.listener.pageSizeChange) {
|
||||||
this.listener.pageSizeChange(pageRowList.length)
|
this.listener.pageSizeChange(this.pageRowList.length)
|
||||||
}
|
}
|
||||||
// 文档内容改变
|
// 文档内容改变
|
||||||
if (this.listener.contentChange && isSubmitHistory) {
|
if (this.listener.contentChange && isSubmitHistory) {
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ export class CanvasEvent {
|
|||||||
this.draw.render({
|
this.draw.render({
|
||||||
isSubmitHistory: false,
|
isSubmitHistory: false,
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isComputeRowList: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ function dblclick(host: CanvasEvent) {
|
|||||||
draw.render({
|
draw.render({
|
||||||
isSubmitHistory: false,
|
isSubmitHistory: false,
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isComputeRowList: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ function threeClick(host: CanvasEvent) {
|
|||||||
draw.render({
|
draw.render({
|
||||||
isSubmitHistory: false,
|
isSubmitHistory: false,
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isComputeRowList: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
curIndex: isCollapsed ? anchorStartIndex : undefined,
|
curIndex: isCollapsed ? anchorStartIndex : undefined,
|
||||||
isSetCursor: isCollapsed,
|
isSetCursor: isCollapsed,
|
||||||
isSubmitHistory: false,
|
isSubmitHistory: false,
|
||||||
isComputeRowList: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,7 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
curIndex: isCollapsed ? anchorStartIndex : undefined,
|
curIndex: isCollapsed ? anchorStartIndex : undefined,
|
||||||
isSetCursor: isCollapsed,
|
isSetCursor: isCollapsed,
|
||||||
isSubmitHistory: false,
|
isSubmitHistory: false,
|
||||||
isComputeRowList: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
}
|
}
|
||||||
@@ -229,7 +229,7 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
curIndex: isCollapsed ? anchorStartIndex : undefined,
|
curIndex: isCollapsed ? anchorStartIndex : undefined,
|
||||||
isSetCursor: isCollapsed,
|
isSetCursor: isCollapsed,
|
||||||
isSubmitHistory: false,
|
isSubmitHistory: false,
|
||||||
isComputeRowList: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if (isMod(evt) && evt.key === KeyMap.Z) {
|
} else if (isMod(evt) && evt.key === KeyMap.Z) {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
curIndex,
|
curIndex,
|
||||||
isSubmitHistory: isSetCheckbox,
|
isSubmitHistory: isSetCheckbox,
|
||||||
isSetCursor: !isDirectHitImage && !isDirectHitCheckbox,
|
isSetCursor: !isDirectHitImage && !isDirectHitCheckbox,
|
||||||
isComputeRowList: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 预览工具组件
|
// 预览工具组件
|
||||||
|
|||||||
@@ -73,6 +73,6 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
draw.render({
|
draw.render({
|
||||||
isSubmitHistory: false,
|
isSubmitHistory: false,
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isComputeRowList: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { ElementType } from '../..'
|
import { ElementType, RowFlex } from '../..'
|
||||||
import { ZERO } from '../../dataset/constant/Common'
|
import { ZERO } from '../../dataset/constant/Common'
|
||||||
import { ControlComponent } from '../../dataset/enum/Control'
|
import { ControlComponent, ImageDisplay } from '../../dataset/enum/Control'
|
||||||
|
import { IComputePageRowPositionPayload, IComputePageRowPositionResult } from '../../interface/Position'
|
||||||
import { IEditorOption } from '../../interface/Editor'
|
import { IEditorOption } from '../../interface/Editor'
|
||||||
import { IElementPosition } from '../../interface/Element'
|
import { IElementPosition } from '../../interface/Element'
|
||||||
import { ICurrentPosition, IGetPositionByXYPayload, IPositionContext } from '../../interface/Position'
|
import { ICurrentPosition, IGetPositionByXYPayload, IPositionContext } from '../../interface/Position'
|
||||||
@@ -45,6 +46,106 @@ export class Position {
|
|||||||
this.positionList = payload
|
this.positionList = payload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private computePageRowPosition(payload: IComputePageRowPositionPayload): IComputePageRowPositionResult {
|
||||||
|
const { positionList, rowList, pageNo, startX, startY, startIndex, innerWidth } = payload
|
||||||
|
const { scale, tdPadding } = this.options
|
||||||
|
let x = startX
|
||||||
|
let y = startY
|
||||||
|
let index = startIndex
|
||||||
|
for (let i = 0; i < rowList.length; i++) {
|
||||||
|
const curRow = rowList[i]
|
||||||
|
// 计算行偏移量(行居中、居右)
|
||||||
|
if (curRow.rowFlex === RowFlex.CENTER) {
|
||||||
|
x += (innerWidth - curRow.width) / 2
|
||||||
|
} else if (curRow.rowFlex === RowFlex.RIGHT) {
|
||||||
|
x += innerWidth - curRow.width
|
||||||
|
}
|
||||||
|
// 当前td所在位置
|
||||||
|
const tablePreX = x
|
||||||
|
const tablePreY = y
|
||||||
|
for (let j = 0; j < curRow.elementList.length; j++) {
|
||||||
|
const element = curRow.elementList[j]
|
||||||
|
const metrics = element.metrics
|
||||||
|
const offsetY =
|
||||||
|
(element.imgDisplay !== ImageDisplay.INLINE && element.type === ElementType.IMAGE)
|
||||||
|
|| element.type === ElementType.LATEX
|
||||||
|
? curRow.ascent - metrics.height
|
||||||
|
: curRow.ascent
|
||||||
|
const positionItem: IElementPosition = {
|
||||||
|
pageNo,
|
||||||
|
index,
|
||||||
|
value: element.value,
|
||||||
|
rowNo: i,
|
||||||
|
metrics,
|
||||||
|
ascent: offsetY,
|
||||||
|
lineHeight: curRow.height,
|
||||||
|
isLastLetter: j === curRow.elementList.length - 1,
|
||||||
|
coordinate: {
|
||||||
|
leftTop: [x, y],
|
||||||
|
leftBottom: [x, y + curRow.height],
|
||||||
|
rightTop: [x + metrics.width, y],
|
||||||
|
rightBottom: [x + metrics.width, y + curRow.height]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
positionList.push(positionItem)
|
||||||
|
index++
|
||||||
|
x += metrics.width
|
||||||
|
// 绘制表格内元素
|
||||||
|
if (element.type === ElementType.TABLE) {
|
||||||
|
const tdGap = tdPadding * 2
|
||||||
|
for (let t = 0; t < element.trList!.length; t++) {
|
||||||
|
const tr = element.trList![t]
|
||||||
|
for (let d = 0; d < tr.tdList!.length; d++) {
|
||||||
|
const td = tr.tdList[d]
|
||||||
|
td.positionList = []
|
||||||
|
const drawRowResult = this.computePageRowPosition({
|
||||||
|
positionList: td.positionList,
|
||||||
|
rowList: td.rowList!,
|
||||||
|
pageNo,
|
||||||
|
startIndex: 0,
|
||||||
|
startX: (td.x! + tdPadding) * scale + tablePreX,
|
||||||
|
startY: td.y! * scale + tablePreY,
|
||||||
|
innerWidth: (td.width! - tdGap) * scale
|
||||||
|
})
|
||||||
|
x = drawRowResult.x
|
||||||
|
y = drawRowResult.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 恢复初始x、y
|
||||||
|
x = tablePreX
|
||||||
|
y = tablePreY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x = startX
|
||||||
|
y += curRow.height
|
||||||
|
}
|
||||||
|
return { x, y, index }
|
||||||
|
}
|
||||||
|
|
||||||
|
public computePositionList() {
|
||||||
|
// 置空原位置信息
|
||||||
|
this.positionList = []
|
||||||
|
// 按每页行计算
|
||||||
|
const innerWidth = this.draw.getInnerWidth()
|
||||||
|
const pageRowList = this.draw.getPageRowList()
|
||||||
|
const margins = this.draw.getMargins()
|
||||||
|
const startX = margins[3]
|
||||||
|
const startY = margins[0]
|
||||||
|
for (let i = 0; i < pageRowList.length; i++) {
|
||||||
|
const rowList = pageRowList[i]
|
||||||
|
const startIndex = rowList[0].startIndex
|
||||||
|
this.computePageRowPosition({
|
||||||
|
positionList: this.positionList,
|
||||||
|
rowList,
|
||||||
|
pageNo: i,
|
||||||
|
startIndex,
|
||||||
|
startX,
|
||||||
|
startY,
|
||||||
|
innerWidth
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public setCursorPosition(position: IElementPosition | null) {
|
public setCursorPosition(position: IElementPosition | null) {
|
||||||
this.cursorPosition = position
|
this.cursorPosition = position
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export interface IDrawOption {
|
|||||||
curIndex?: number;
|
curIndex?: number;
|
||||||
isSetCursor?: boolean;
|
isSetCursor?: boolean;
|
||||||
isSubmitHistory?: boolean;
|
isSubmitHistory?: boolean;
|
||||||
isComputeRowList?: boolean;
|
isCompute?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDrawImagePayload {
|
export interface IDrawImagePayload {
|
||||||
@@ -19,17 +19,9 @@ export interface IDrawRowPayload {
|
|||||||
rowList: IRow[];
|
rowList: IRow[];
|
||||||
pageNo: number;
|
pageNo: number;
|
||||||
startIndex: number;
|
startIndex: number;
|
||||||
startX: number;
|
|
||||||
startY: number;
|
|
||||||
innerWidth: number;
|
innerWidth: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDrawRowResult {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
index: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IPainterOptions {
|
export interface IPainterOptions {
|
||||||
isDblclick: boolean;
|
isDblclick: boolean;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { IElement } from '..'
|
import { IElement } from '..'
|
||||||
import { IElementPosition } from './Element'
|
import { IElementPosition } from './Element'
|
||||||
|
import { IRow } from './Row'
|
||||||
import { ITd } from './table/Td'
|
import { ITd } from './table/Td'
|
||||||
|
|
||||||
export interface ICurrentPosition {
|
export interface ICurrentPosition {
|
||||||
@@ -38,3 +39,19 @@ export interface IPositionContext {
|
|||||||
trId?: string;
|
trId?: string;
|
||||||
tableId?: string;
|
tableId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IComputePageRowPositionPayload {
|
||||||
|
positionList: IElementPosition[];
|
||||||
|
rowList: IRow[];
|
||||||
|
pageNo: number;
|
||||||
|
startIndex: number;
|
||||||
|
startX: number;
|
||||||
|
startY: number;
|
||||||
|
innerWidth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IComputePageRowPositionResult {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
index: number;
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ export interface IRow {
|
|||||||
height: number;
|
height: number;
|
||||||
ascent: number;
|
ascent: number;
|
||||||
rowFlex?: RowFlex;
|
rowFlex?: RowFlex;
|
||||||
|
startIndex: number;
|
||||||
isPageBreak?: boolean;
|
isPageBreak?: boolean;
|
||||||
elementList: IRowElement[];
|
elementList: IRowElement[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,3 +112,9 @@ export function mergeObject<T>(source: T, target: T): T {
|
|||||||
}
|
}
|
||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function nextTick(fn: Function) {
|
||||||
|
setTimeout(() => {
|
||||||
|
fn()
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user