feat:optimize rich text render performance

pr675
黄云飞 4 years ago
parent 7573eeece1
commit a4abaca5a7

@ -767,6 +767,13 @@ export class Draw {
return rowList
}
private _drawRichText(ctx: CanvasRenderingContext2D) {
this.underline.render(ctx)
this.strikeout.render(ctx)
this.highlight.render(ctx)
this.textParticle.complete()
}
private _drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload): IDrawRowResult {
const { positionList, rowList, pageNo, startX, startY, startIndex, innerWidth } = payload
const { scale, tdPadding } = this.options
@ -823,10 +830,10 @@ export class Draw {
positionList.push(positionItem)
// 元素绘制
if (element.type === ElementType.IMAGE) {
this.textParticle.complete()
this._drawRichText(ctx)
this.imageParticle.render(ctx, element, x, y + offsetY)
} else if (element.type === ElementType.LATEX) {
this.textParticle.complete()
this._drawRichText(ctx)
this.laTexParticle.render(ctx, element, x, y + offsetY)
} else if (element.type === ElementType.TABLE) {
if (isCrossRowCol) {
@ -836,16 +843,16 @@ export class Draw {
}
this.tableParticle.render(ctx, element, x, y)
} else if (element.type === ElementType.HYPERLINK) {
this.textParticle.complete()
this._drawRichText(ctx)
this.hyperlinkParticle.render(ctx, element, x, y + offsetY)
} else if (element.type === ElementType.DATE) {
this.textParticle.complete()
this._drawRichText(ctx)
this.dateParticle.render(ctx, element, x, y + offsetY)
} else if (element.type === ElementType.SUPERSCRIPT) {
this.textParticle.complete()
this._drawRichText(ctx)
this.superscriptParticle.render(ctx, element, x, y + offsetY)
} else if (element.type === ElementType.SUBSCRIPT) {
this.textParticle.complete()
this._drawRichText(ctx)
this.subscriptParticle.render(ctx, element, x, y + offsetY)
} else if (element.type === ElementType.SEPARATOR) {
this.separatorParticle.render(ctx, element, x, y)
@ -857,24 +864,24 @@ export class Draw {
element.type === ElementType.CHECKBOX ||
element.controlComponent === ControlComponent.CHECKBOX
) {
this.textParticle.complete()
this._drawRichText(ctx)
this.checkboxParticle.render(ctx, element, x, y + offsetY)
} else if (element.type === ElementType.TAB) {
this.textParticle.complete()
this._drawRichText(ctx)
} else {
this.textParticle.record(ctx, element, x, y + offsetY)
}
// 下划线绘制
// 下划线记录
if (element.underline) {
this.underline.render(ctx, element.color!, x, y + curRow.height, metrics.width)
this.underline.recordFillInfo(ctx, x, y + curRow.height, metrics.width, 0, element.color)
}
// 删除线绘制
// 删除线记录
if (element.strikeout) {
this.strikeout.render(ctx, x, y + curRow.height / 2, metrics.width)
this.strikeout.recordFillInfo(ctx, x, y + curRow.height / 2, metrics.width)
}
// 元素高亮
// 元素高亮记录
if (element.highlight) {
this.highlight.render(ctx, element.highlight, x, y, metrics.width, curRow.height)
this.highlight.recordFillInfo(ctx, x, y, metrics.width, curRow.height, element.highlight)
}
// 选区记录
const { startIndex, endIndex } = this.range.getRange()
@ -937,7 +944,8 @@ export class Draw {
y = tablePreY
}
}
this.textParticle.complete()
// 绘制富文本及文字
this._drawRichText(ctx)
// 绘制选区
if (rangeRecord.width && rangeRecord.height) {
const { x, y, width, height } = rangeRecord

@ -0,0 +1,41 @@
import { IElementFillRect } from '../../../interface/Element'
export abstract class AbstractRichText {
public fillRect: IElementFillRect
public fillColor?: string
constructor() {
this.fillRect = this.clearFillInfo()
}
public clearFillInfo() {
this.fillColor = undefined
return this.fillRect = {
x: 0,
y: 0,
width: 0,
height: 0
}
}
public recordFillInfo(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height?: number, color?: string) {
const isFirstRecord = !this.fillRect.width
if (!isFirstRecord && this.fillColor && this.fillColor !== color) {
this.render(ctx)
this.clearFillInfo()
return
}
if (isFirstRecord) {
this.fillRect.x = x
this.fillRect.y = y
}
if (height && this.fillRect.height < height) {
this.fillRect.height = height
}
this.fillRect.width += width
this.fillColor = color
}
public abstract render(ctx: CanvasRenderingContext2D): void
}

@ -1,21 +1,26 @@
import { AbstractRichText } from './AbstractRichText'
import { IEditorOption } from '../../../interface/Editor'
import { Draw } from '../Draw'
export class Highlight {
export class Highlight extends AbstractRichText {
private options: Required<IEditorOption>
constructor(draw: Draw) {
super()
this.options = draw.getOptions()
}
public render(ctx: CanvasRenderingContext2D, color: string, x: number, y: number, width: number, height: number) {
public render(ctx: CanvasRenderingContext2D) {
if (!this.fillRect.width) return
const { highlightAlpha } = this.options
const { x, y, width, height } = this.fillRect
ctx.save()
ctx.globalAlpha = highlightAlpha
ctx.fillStyle = color
ctx.fillStyle = this.fillColor!
ctx.fillRect(x, y, width, height)
ctx.restore()
this.clearFillInfo()
}
}

@ -1,23 +1,29 @@
import { AbstractRichText } from './AbstractRichText'
import { IEditorOption } from '../../../interface/Editor'
import { Draw } from '../Draw'
export class Strikeout {
export class Strikeout extends AbstractRichText {
private options: Required<IEditorOption>
constructor(draw: Draw) {
super()
this.options = draw.getOptions()
}
public render(ctx: CanvasRenderingContext2D, x: number, y: number, width: number) {
public render(ctx: CanvasRenderingContext2D) {
if (!this.fillRect.width) return
const { strikeoutColor } = this.options
const { x, y, width } = this.fillRect
ctx.save()
ctx.strokeStyle = strikeoutColor
const adjustY = y + 0.5 // 从1处渲染避免线宽度等于3
ctx.beginPath()
ctx.moveTo(x, y)
ctx.lineTo(x + width, y)
ctx.moveTo(x, adjustY)
ctx.lineTo(x + width, adjustY)
ctx.stroke()
ctx.restore()
this.clearFillInfo()
}
}

@ -1,23 +1,29 @@
import { AbstractRichText } from './AbstractRichText'
import { IEditorOption } from '../../../interface/Editor'
import { Draw } from '../Draw'
export class Underline {
export class Underline extends AbstractRichText {
private options: Required<IEditorOption>
constructor(draw: Draw) {
super()
this.options = draw.getOptions()
}
public render(ctx: CanvasRenderingContext2D, color: string, x: number, y: number, width: number) {
public render(ctx: CanvasRenderingContext2D) {
if (!this.fillRect.width) return
const { underlineColor } = this.options
const { x, y, width } = this.fillRect
ctx.save()
ctx.strokeStyle = color || underlineColor
ctx.strokeStyle = this.fillColor || underlineColor
const adjustY = y + 0.5 // 从1处渲染避免线宽度等于3
ctx.beginPath()
ctx.moveTo(x, y)
ctx.lineTo(x + width, y)
ctx.moveTo(x, adjustY)
ctx.lineTo(x + width, adjustY)
ctx.stroke()
ctx.restore()
this.clearFillInfo()
}
}
Loading…
Cancel
Save