Merge pull request #135 from Hufe921/feature/performance
Feature/performance
This commit is contained in:
@@ -10,16 +10,16 @@ describe('菜单-打印', () => {
|
|||||||
|
|
||||||
it('打印', () => {
|
it('打印', () => {
|
||||||
|
|
||||||
cy.getEditor().then((editor: Editor) => {
|
cy.getEditor().then(async (editor: Editor) => {
|
||||||
const imageList2 = editor.command.getImage()
|
const imageList2 = await editor.command.getImage()
|
||||||
expect(imageList2.length).to.eq(2)
|
expect(imageList2.length).to.eq(2)
|
||||||
|
|
||||||
editor.command.executeSelectAll()
|
editor.command.executeSelectAll()
|
||||||
|
|
||||||
editor.command.executeBackspace()
|
editor.command.executeBackspace()
|
||||||
|
|
||||||
cy.wait(200).then(() => {
|
cy.wait(200).then(async () => {
|
||||||
const imageList1 = editor.command.getImage()
|
const imageList1 = await editor.command.getImage()
|
||||||
expect(imageList1.length).to.eq(1)
|
expect(imageList1.length).to.eq(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ export class Command {
|
|||||||
return Command.changeImageDisplay(element, display)
|
return Command.changeImageDisplay(element, display)
|
||||||
}
|
}
|
||||||
|
|
||||||
public getImage(): string[] {
|
public getImage(): Promise<string[]> {
|
||||||
return Command.getImage()
|
return Command.getImage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
})
|
})
|
||||||
@@ -327,7 +327,10 @@ export class CommandAdapt {
|
|||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
el.color = payload
|
el.color = payload
|
||||||
})
|
})
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render({
|
||||||
|
isSetCursor: false,
|
||||||
|
isCompute: false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public highlight(payload: string) {
|
public highlight(payload: string) {
|
||||||
@@ -338,7 +341,10 @@ export class CommandAdapt {
|
|||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
el.highlight = payload
|
el.highlight = payload
|
||||||
})
|
})
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render({
|
||||||
|
isSetCursor: false,
|
||||||
|
isCompute: false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public rowFlex(payload: RowFlex) {
|
public rowFlex(payload: RowFlex) {
|
||||||
@@ -1092,7 +1098,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 +1118,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
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1173,7 +1179,8 @@ export class CommandAdapt {
|
|||||||
options.watermark.font = payload.font || font
|
options.watermark.font = payload.font || font
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isSubmitHistory: false
|
isSubmitHistory: false,
|
||||||
|
isCompute: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1185,7 +1192,8 @@ export class CommandAdapt {
|
|||||||
options.watermark = { ...defaultWatermarkOption }
|
options.watermark = { ...defaultWatermarkOption }
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isSubmitHistory: false
|
isSubmitHistory: false,
|
||||||
|
isCompute: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1229,7 +1237,9 @@ export class CommandAdapt {
|
|||||||
if (index === null) return
|
if (index === null) return
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isSubmitHistory: false
|
isSubmitHistory: false,
|
||||||
|
isCompute: false,
|
||||||
|
isLazy: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1238,7 +1248,9 @@ export class CommandAdapt {
|
|||||||
if (index === null) return
|
if (index === null) return
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isSubmitHistory: false
|
isSubmitHistory: false,
|
||||||
|
isCompute: false,
|
||||||
|
isLazy: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1352,12 +1364,13 @@ export class CommandAdapt {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public print() {
|
public async print() {
|
||||||
const { width, height, scale } = this.options
|
const { width, height, scale } = this.options
|
||||||
if (scale !== 1) {
|
if (scale !== 1) {
|
||||||
this.draw.setPageScale(1)
|
this.draw.setPageScale(1)
|
||||||
}
|
}
|
||||||
printImageBase64(this.draw.getDataURL(), width, height)
|
const base64List = await this.draw.getDataURL()
|
||||||
|
printImageBase64(base64List, width, height)
|
||||||
if (scale !== 1) {
|
if (scale !== 1) {
|
||||||
this.draw.setPageScale(scale)
|
this.draw.setPageScale(scale)
|
||||||
}
|
}
|
||||||
@@ -1393,7 +1406,7 @@ export class CommandAdapt {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public getImage(): string[] {
|
public getImage(): Promise<string[]> {
|
||||||
return this.draw.getDataURL()
|
return this.draw.getDataURL()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+129
-111
@@ -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'
|
||||||
@@ -49,6 +49,7 @@ import { IMargin } from '../../interface/Margin'
|
|||||||
import { BlockParticle } from './particle/block/BlockParticle'
|
import { BlockParticle } from './particle/block/BlockParticle'
|
||||||
import { EDITOR_COMPONENT, EDITOR_PREFIX } from '../../dataset/constant/Editor'
|
import { EDITOR_COMPONENT, EDITOR_PREFIX } from '../../dataset/constant/Editor'
|
||||||
import { I18n } from '../i18n/I18n'
|
import { I18n } from '../i18n/I18n'
|
||||||
|
import { ImageObserver } from '../observer/ImageObserver'
|
||||||
|
|
||||||
export class Draw {
|
export class Draw {
|
||||||
|
|
||||||
@@ -96,12 +97,15 @@ export class Draw {
|
|||||||
private workerManager: WorkerManager
|
private workerManager: WorkerManager
|
||||||
private scrollObserver: ScrollObserver
|
private scrollObserver: ScrollObserver
|
||||||
private selectionObserver: SelectionObserver
|
private selectionObserver: SelectionObserver
|
||||||
|
private imageObserver: ImageObserver
|
||||||
|
|
||||||
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[]
|
||||||
private intersectionPageNo: number
|
private intersectionPageNo: number
|
||||||
|
private lazyRenderIntersectionObserver: IntersectionObserver | null
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
rootContainer: HTMLElement,
|
rootContainer: HTMLElement,
|
||||||
@@ -153,6 +157,7 @@ export class Draw {
|
|||||||
|
|
||||||
this.scrollObserver = new ScrollObserver(this)
|
this.scrollObserver = new ScrollObserver(this)
|
||||||
this.selectionObserver = new SelectionObserver()
|
this.selectionObserver = new SelectionObserver()
|
||||||
|
this.imageObserver = new ImageObserver()
|
||||||
|
|
||||||
this.canvasEvent = new CanvasEvent(this)
|
this.canvasEvent = new CanvasEvent(this)
|
||||||
this.cursor = new Cursor(this, this.canvasEvent)
|
this.cursor = new Cursor(this, this.canvasEvent)
|
||||||
@@ -163,10 +168,12 @@ 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 = []
|
||||||
this.intersectionPageNo = 0
|
this.intersectionPageNo = 0
|
||||||
|
this.lazyRenderIntersectionObserver = null
|
||||||
|
|
||||||
this.render({ isSetCursor: false })
|
this.render({ isSetCursor: false })
|
||||||
}
|
}
|
||||||
@@ -290,6 +297,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]
|
||||||
}
|
}
|
||||||
@@ -405,6 +420,10 @@ export class Draw {
|
|||||||
return this.workerManager
|
return this.workerManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getImageObserver(): ImageObserver {
|
||||||
|
return this.imageObserver
|
||||||
|
}
|
||||||
|
|
||||||
public getI18n(): I18n {
|
public getI18n(): I18n {
|
||||||
return this.i18n
|
return this.i18n
|
||||||
}
|
}
|
||||||
@@ -413,7 +432,14 @@ export class Draw {
|
|||||||
return this.rowList.length
|
return this.rowList.length
|
||||||
}
|
}
|
||||||
|
|
||||||
public getDataURL(): string[] {
|
public async getDataURL(): Promise<string[]> {
|
||||||
|
this.render({
|
||||||
|
isLazy: false,
|
||||||
|
isCompute: false,
|
||||||
|
isSetCursor: false,
|
||||||
|
isSubmitHistory: false
|
||||||
|
})
|
||||||
|
await this.imageObserver.allSettled()
|
||||||
return this.pageList.map(c => c.toDataURL())
|
return this.pageList.map(c => c.toDataURL())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,7 +625,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[] = []
|
||||||
@@ -609,6 +634,7 @@ export class Draw {
|
|||||||
height: 0,
|
height: 0,
|
||||||
ascent: 0,
|
ascent: 0,
|
||||||
elementList: [],
|
elementList: [],
|
||||||
|
startIndex: 0,
|
||||||
rowFlex: elementList?.[1]?.rowFlex
|
rowFlex: elementList?.[1]?.rowFlex
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -642,6 +668,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)
|
||||||
// 计算表格内元素信息
|
// 计算表格内元素信息
|
||||||
@@ -820,6 +847,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,
|
||||||
@@ -841,6 +869,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)
|
||||||
@@ -848,25 +915,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,
|
||||||
@@ -878,28 +933,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)
|
||||||
@@ -1004,30 +1044,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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 绘制富文本及文字
|
// 绘制富文本及文字
|
||||||
@@ -1038,12 +1070,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) {
|
||||||
@@ -1055,31 +1085,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)
|
||||||
// 绘制页码
|
// 绘制页码
|
||||||
@@ -1094,73 +1115,71 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _lazyRender() {
|
||||||
|
const positionList = this.position.getOriginalPositionList()
|
||||||
|
this.lazyRenderIntersectionObserver?.disconnect()
|
||||||
|
this.lazyRenderIntersectionObserver = new IntersectionObserver((entries) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
const index = Number((<HTMLCanvasElement>entry.target).dataset.index)
|
||||||
|
this._drawPage(positionList, this.pageRowList[index], index)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.pageList.forEach(el => {
|
||||||
|
this.lazyRenderIntersectionObserver!.observe(el)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private _immediateRender() {
|
||||||
|
const positionList = this.position.getOriginalPositionList()
|
||||||
|
for (let i = 0; i < this.pageRowList.length; i++) {
|
||||||
|
this._drawPage(positionList, this.pageRowList[i], i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
isLazy = 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.imageObserver.clearAll()
|
||||||
this.cursor.recoveryCursor()
|
this.cursor.recoveryCursor()
|
||||||
this.position.setPositionList([])
|
// 创建纸张
|
||||||
const positionList = this.position.getOriginalPositionList()
|
const positionList = this.position.getOriginalPositionList()
|
||||||
// 按页渲染
|
for (let i = 0; i < this.pageRowList.length; i++) {
|
||||||
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++) {
|
|
||||||
if (!this.pageList[i]) {
|
if (!this.pageList[i]) {
|
||||||
this._createPage(i)
|
this._createPage(i)
|
||||||
}
|
}
|
||||||
const rowList = pageRowList[i]
|
}
|
||||||
this._drawPage(positionList, rowList, i)
|
// 绘制元素
|
||||||
|
if (isLazy) {
|
||||||
|
this._lazyRender()
|
||||||
|
} else {
|
||||||
|
this._immediateRender()
|
||||||
}
|
}
|
||||||
// 移除多余页
|
// 移除多余页
|
||||||
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
|
||||||
@@ -1203,12 +1222,11 @@ export class Draw {
|
|||||||
self.render({ curIndex, isSubmitHistory: false })
|
self.render({ curIndex, isSubmitHistory: false })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 信息变动回调
|
// 信息变动回调
|
||||||
setTimeout(() => {
|
nextTick(() => {
|
||||||
// 页面尺寸改变
|
// 页面尺寸改变
|
||||||
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) {
|
||||||
|
|||||||
@@ -261,7 +261,11 @@ export class Search {
|
|||||||
const searchMatchIndexList = this.getSearchNavigateIndexList()
|
const searchMatchIndexList = this.getSearchNavigateIndexList()
|
||||||
if (searchMatchIndexList.includes(s)) {
|
if (searchMatchIndexList.includes(s)) {
|
||||||
ctx.fillStyle = searchNavigateMatchColor
|
ctx.fillStyle = searchNavigateMatchColor
|
||||||
|
// 是否是第一个字符,则移动到可视范围
|
||||||
|
const preSearchMatch = this.searchMatchList[s - 1]
|
||||||
|
if (!preSearchMatch || preSearchMatch.groupId !== searchMatch.groupId) {
|
||||||
this.searchNavigateScrollIntoView(position)
|
this.searchNavigateScrollIntoView(position)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx.fillStyle = searchMatchColor
|
ctx.fillStyle = searchMatchColor
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,20 @@ import { Draw } from '../Draw'
|
|||||||
|
|
||||||
export class ImageParticle {
|
export class ImageParticle {
|
||||||
|
|
||||||
|
private draw: Draw
|
||||||
protected options: Required<IEditorOption>
|
protected options: Required<IEditorOption>
|
||||||
protected imageCache: Map<string, HTMLImageElement>
|
protected imageCache: Map<string, HTMLImageElement>
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
|
this.draw = draw
|
||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
this.imageCache = new Map()
|
this.imageCache = new Map()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected addImageObserver(promise: Promise<unknown>) {
|
||||||
|
this.draw.getImageObserver().add(promise)
|
||||||
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IElement, x: number, y: number) {
|
public render(ctx: CanvasRenderingContext2D, element: IElement, x: number, y: number) {
|
||||||
const { scale } = this.options
|
const { scale } = this.options
|
||||||
const width = element.width! * scale
|
const width = element.width! * scale
|
||||||
@@ -20,12 +26,19 @@ export class ImageParticle {
|
|||||||
const img = this.imageCache.get(element.id!)!
|
const img = this.imageCache.get(element.id!)!
|
||||||
ctx.drawImage(img, x, y, width, height)
|
ctx.drawImage(img, x, y, width, height)
|
||||||
} else {
|
} else {
|
||||||
|
const imageLoadPromise = new Promise((resolve, reject) => {
|
||||||
const img = new Image()
|
const img = new Image()
|
||||||
img.src = element.value
|
img.src = element.value
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
ctx.drawImage(img, x, y, width, height)
|
ctx.drawImage(img, x, y, width, height)
|
||||||
this.imageCache.set(element.id!, img)
|
this.imageCache.set(element.id!, img)
|
||||||
|
resolve(element)
|
||||||
}
|
}
|
||||||
|
img.onerror = (error) => {
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.addImageObserver(imageLoadPromise)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,19 @@ export class LaTexParticle extends ImageParticle {
|
|||||||
const img = this.imageCache.get(element.value)!
|
const img = this.imageCache.get(element.value)!
|
||||||
ctx.drawImage(img, x, y, width, height)
|
ctx.drawImage(img, x, y, width, height)
|
||||||
} else {
|
} else {
|
||||||
|
const laTexLoadPromise = new Promise((resolve, reject) => {
|
||||||
const img = new Image()
|
const img = new Image()
|
||||||
img.src = element.laTexSVG!
|
img.src = element.laTexSVG!
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
ctx.drawImage(img, x, y, width, height)
|
ctx.drawImage(img, x, y, width, height)
|
||||||
this.imageCache.set(element.value, img)
|
this.imageCache.set(element.value, img)
|
||||||
|
resolve(element)
|
||||||
}
|
}
|
||||||
|
img.onerror = (error) => {
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.addImageObserver(laTexLoadPromise)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
export class ImageObserver {
|
||||||
|
|
||||||
|
private promiseList: Promise<unknown>[]
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.promiseList = []
|
||||||
|
}
|
||||||
|
|
||||||
|
public add(payload: Promise<unknown>) {
|
||||||
|
this.promiseList.push(payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
public clearAll() {
|
||||||
|
this.promiseList = []
|
||||||
|
}
|
||||||
|
|
||||||
|
public allSettled() {
|
||||||
|
return Promise.allSettled(this.promiseList)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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,8 @@ export interface IDrawOption {
|
|||||||
curIndex?: number;
|
curIndex?: number;
|
||||||
isSetCursor?: boolean;
|
isSetCursor?: boolean;
|
||||||
isSubmitHistory?: boolean;
|
isSubmitHistory?: boolean;
|
||||||
isComputeRowList?: boolean;
|
isCompute?: boolean;
|
||||||
|
isLazy?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDrawImagePayload {
|
export interface IDrawImagePayload {
|
||||||
@@ -19,17 +20,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