diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index ecac428..3a511a5 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -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 diff --git a/src/editor/core/draw/richtext/AbstractRichText.ts b/src/editor/core/draw/richtext/AbstractRichText.ts new file mode 100644 index 0000000..3cd0ebd --- /dev/null +++ b/src/editor/core/draw/richtext/AbstractRichText.ts @@ -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 + +} \ No newline at end of file diff --git a/src/editor/core/draw/richtext/Highlight.ts b/src/editor/core/draw/richtext/Highlight.ts index e95ea87..19883f3 100644 --- a/src/editor/core/draw/richtext/Highlight.ts +++ b/src/editor/core/draw/richtext/Highlight.ts @@ -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 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() } } \ No newline at end of file diff --git a/src/editor/core/draw/richtext/Strikeout.ts b/src/editor/core/draw/richtext/Strikeout.ts index 21b4850..d00e382 100644 --- a/src/editor/core/draw/richtext/Strikeout.ts +++ b/src/editor/core/draw/richtext/Strikeout.ts @@ -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 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() } } \ No newline at end of file diff --git a/src/editor/core/draw/richtext/Underline.ts b/src/editor/core/draw/richtext/Underline.ts index 4ccca11..020769e 100644 --- a/src/editor/core/draw/richtext/Underline.ts +++ b/src/editor/core/draw/richtext/Underline.ts @@ -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 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() } } \ No newline at end of file