diff --git a/packages/vrender-core/src/graphic/config.ts b/packages/vrender-core/src/graphic/config.ts index 7da138023..f3f6885b5 100644 --- a/packages/vrender-core/src/graphic/config.ts +++ b/packages/vrender-core/src/graphic/config.ts @@ -346,6 +346,7 @@ export const DefaultRichTextAttribute: Required = { ...DefaultTextStyle, editable: false, editOptions: null, + ascentDescentMode: 'actual', width: 300, height: 300, ellipsis: true, diff --git a/packages/vrender-core/src/graphic/richtext.ts b/packages/vrender-core/src/graphic/richtext.ts index bad0b7cc3..a9549c7ba 100644 --- a/packages/vrender-core/src/graphic/richtext.ts +++ b/packages/vrender-core/src/graphic/richtext.ts @@ -381,7 +381,8 @@ export class RichText extends Graphic implements IRic layoutDirection, singleLine, disableAutoWrapLine, - editable + editable, + ascentDescentMode } = this.attribute; let { textConfig: _tc = [] } = this.attribute; @@ -427,10 +428,10 @@ export class RichText extends Graphic implements IRic // 如果有文字内有换行符,将该段文字切为多段,并在后一段加入newLine标记 const textParts = richTextConfig.text.split('\n'); for (let j = 0; j < textParts.length; j++) { - paragraphs.push(new Paragraph(textParts[j], j !== 0, richTextConfig)); + paragraphs.push(new Paragraph(textParts[j], j !== 0, richTextConfig, ascentDescentMode)); } } else if (richTextConfig.text) { - paragraphs.push(new Paragraph(richTextConfig.text, false, richTextConfig)); + paragraphs.push(new Paragraph(richTextConfig.text, false, richTextConfig, ascentDescentMode)); } } } diff --git a/packages/vrender-core/src/graphic/richtext/line.ts b/packages/vrender-core/src/graphic/richtext/line.ts index f3e09c2e3..81a8408c8 100644 --- a/packages/vrender-core/src/graphic/richtext/line.ts +++ b/packages/vrender-core/src/graphic/richtext/line.ts @@ -178,7 +178,7 @@ export default class Line { const ellipsis = drawEllipsis === true ? '...' : drawEllipsis || ''; paragraph.ellipsisStr = ellipsis; // const { width } = measureText('...', paragraph.style); - const { width } = measureTextCanvas(ellipsis, paragraph.character); + const { width } = measureTextCanvas(ellipsis, paragraph.character, paragraph.ascentDescentMode); const ellipsisWidth = width || 0; if (ellipsisWidth <= this.blankWidth + otherParagraphWidth) { // 省略号可以直接接在后面paragraph @@ -243,7 +243,7 @@ export default class Line { break; // todo: 处理最后为图标,显示省略号的情况 } - const { width } = measureTextCanvas(ellipsis, paragraph.character); + const { width } = measureTextCanvas(ellipsis, paragraph.character, paragraph.ascentDescentMode); const ellipsisWidth = width || 0; if (ellipsisWidth <= this.blankWidth + otherParagraphWidth) { // 省略号可以直接接在后面paragraph diff --git a/packages/vrender-core/src/graphic/richtext/paragraph.ts b/packages/vrender-core/src/graphic/richtext/paragraph.ts index d8d690619..fc231ecfc 100644 --- a/packages/vrender-core/src/graphic/richtext/paragraph.ts +++ b/packages/vrender-core/src/graphic/richtext/paragraph.ts @@ -66,6 +66,7 @@ export default class Paragraph { widthOrigin?: number; heightOrigin?: number; textBaseline?: CanvasTextBaseline; + ascentDescentMode?: 'actual' | 'font'; ellipsis: 'normal' | 'add' | 'replace' | 'hide'; ellipsisStr: string; @@ -74,10 +75,16 @@ export default class Paragraph { verticalEllipsis?: boolean; overflow?: boolean; - constructor(text: string, newLine: boolean, character: IRichTextParagraphCharacter) { + constructor( + text: string, + newLine: boolean, + character: IRichTextParagraphCharacter, + ascentDescentMode?: 'actual' | 'font' + ) { // 测量文字 this.fontSize = character.fontSize || 16; this.textBaseline = character.textBaseline || 'alphabetic'; + this.ascentDescentMode = ascentDescentMode; // 处理行高: // lineHeight为数字时,大于fontSize取lineHeight,小于fontSize时取fontSize @@ -91,7 +98,7 @@ export default class Paragraph { this.height = this.lineHeight; - const { ascent, height, descent, width } = measureTextCanvas(text, character); + const { ascent, height, descent, width } = measureTextCanvas(text, character, this.ascentDescentMode); let halfDetaHeight = 0; let deltaAscent = 0; @@ -150,7 +157,7 @@ export default class Paragraph { } updateWidth() { - const { width } = measureTextCanvas(this.text, this.character); + const { width } = measureTextCanvas(this.text, this.character, this.ascentDescentMode); this.width = width; if (this.direction === 'vertical') { this.widthOrigin = this.width; @@ -202,7 +209,7 @@ export default class Paragraph { text += this.ellipsisStr; if (textAlign === 'right' || textAlign === 'end') { - const { width } = measureTextCanvas(this.text.slice(index), this.character); + const { width } = measureTextCanvas(this.text.slice(index), this.character, this.ascentDescentMode); if (direction === 'vertical') { // baseline -= this.ellipsisWidth - width; } else { @@ -286,7 +293,7 @@ export default class Paragraph { text += this.ellipsisStr; if (textAlign === 'right' || textAlign === 'end') { - const { width } = measureTextCanvas(this.text.slice(index), this.character); + const { width } = measureTextCanvas(this.text.slice(index), this.character, this.ascentDescentMode); if (direction === 'vertical') { // baseline -= this.ellipsisWidth - width; } else { @@ -407,7 +414,7 @@ export default class Paragraph { text = text.slice(0, index); text += this.ellipsisStr; - const { width: measureWidth } = measureTextCanvas(this.text.slice(index), this.character); + const { width: measureWidth } = measureTextCanvas(this.text.slice(index), this.character, this.ascentDescentMode); return width + this.ellipsisWidth - measureWidth; } return width; @@ -417,8 +424,8 @@ export default class Paragraph { export function seperateParagraph(paragraph: Paragraph, index: number) { const text1 = paragraph.text.slice(0, index); const text2 = paragraph.text.slice(index); - const p1 = new Paragraph(text1, paragraph.newLine, paragraph.character); - const p2 = new Paragraph(text2, true, paragraph.character); + const p1 = new Paragraph(text1, paragraph.newLine, paragraph.character, paragraph.ascentDescentMode); + const p2 = new Paragraph(text2, true, paragraph.character, paragraph.ascentDescentMode); return [p1, p2]; } diff --git a/packages/vrender-core/src/graphic/richtext/utils.ts b/packages/vrender-core/src/graphic/richtext/utils.ts index 1e4247318..a491ddbe8 100644 --- a/packages/vrender-core/src/graphic/richtext/utils.ts +++ b/packages/vrender-core/src/graphic/richtext/utils.ts @@ -341,7 +341,8 @@ export function measureTextDom( // 测量文字详细信息 export function measureTextCanvas( text: string, - character: IRichTextParagraphCharacter + character: IRichTextParagraphCharacter, + mode: 'actual' | 'font' = 'actual' ): { ascent: number; height: number; descent: number; width: number } { const textMeasure = application.graphicUtil.textMeasure; const measurement = textMeasure.measureText(text, character as any) as TextMetrics; @@ -351,15 +352,17 @@ export function measureTextCanvas( descent: 0, width: 0 }; - if (typeof measurement.fontBoundingBoxAscent !== 'number' || typeof measurement.fontBoundingBoxDescent !== 'number') { + const ascent = mode === 'actual' ? measurement.actualBoundingBoxAscent : measurement.fontBoundingBoxAscent; + const descent = mode === 'actual' ? measurement.actualBoundingBoxDescent : measurement.fontBoundingBoxDescent; + if (typeof ascent !== 'number' || typeof descent !== 'number') { result.width = measurement.width; result.height = character.fontSize || 0; result.ascent = result.height; result.descent = 0; } else { result.width = measurement.width; - result.height = Math.floor(measurement.fontBoundingBoxAscent + measurement.fontBoundingBoxDescent); - result.ascent = Math.floor(measurement.fontBoundingBoxAscent); + result.height = Math.floor(ascent + descent); + result.ascent = Math.floor(ascent); result.descent = result.height - result.ascent; } return result; diff --git a/packages/vrender-core/src/interface/graphic/richText.ts b/packages/vrender-core/src/interface/graphic/richText.ts index 3d760b1d6..29fde09ef 100644 --- a/packages/vrender-core/src/interface/graphic/richText.ts +++ b/packages/vrender-core/src/interface/graphic/richText.ts @@ -30,6 +30,10 @@ export type IRichTextAttribute = { * 是否可编辑 */ editable: boolean; + /** + * 测量ascent和descent的模式,预览的时候actual比较合适,而如果需要编辑的话,font比较合适 + */ + ascentDescentMode?: 'actual' | 'font'; /** * 富文本的编辑配置 */ diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index 769a912d2..90b1bc1b5 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -214,11 +214,11 @@ export class EditModule { this.composingConfigIdx = this.cursorIndex < 0 ? 0 : findConfigIndexByCursorIdx(textConfig, this.cursorIndex); if (this.cursorIndex < 0) { const config = textConfig[0]; - textConfig.unshift({ ...getDefaultCharacterConfig(this.currRt.attribute), ...config, text: '' }); + textConfig.unshift({ fill: 'black', ...getDefaultCharacterConfig(this.currRt.attribute), ...config, text: '' }); } else { const configIdx = this.composingConfigIdx; const lastConfig = textConfig[configIdx] || textConfig[configIdx - 1]; - textConfig.splice(configIdx, 0, { ...lastConfig, text: '' }); + textConfig.splice(configIdx, 0, { fill: 'black', ...lastConfig, text: '' }); } }; handleCompositionEnd = () => {