From 36cdd2cbab8134c17ecbed5a69edf11572ce49c8 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 10 Feb 2025 15:55:26 +0800 Subject: [PATCH 1/2] fix: richtext support globalLineHeight support --- packages/vrender-core/src/graphic/richtext.ts | 2 + .../src/plugins/builtin-plugin/edit-module.ts | 5 +- .../browser/src/pages/richtext-editor.ts | 105 +++++++++++------- 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/packages/vrender-core/src/graphic/richtext.ts b/packages/vrender-core/src/graphic/richtext.ts index 56ce3ccff..49e365bb8 100644 --- a/packages/vrender-core/src/graphic/richtext.ts +++ b/packages/vrender-core/src/graphic/richtext.ts @@ -370,6 +370,7 @@ export class RichText extends Graphic implements IRic lineWidth, opacity, fillOpacity, + lineHeight, strokeOpacity } = this.attribute; return { @@ -382,6 +383,7 @@ export class RichText extends Graphic implements IRic lineWidth, opacity, fillOpacity, + lineHeight, strokeOpacity, ...config }; 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 f15e4f6cb..58ebd735a 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -18,7 +18,7 @@ import type { // } export function getDefaultCharacterConfig(attribute: IRichTextGraphicAttribute) { - const { fill = 'black', stroke = false, fontWeight = 'normal', fontFamily = 'Arial' } = attribute; + const { fill = 'black', stroke = false, fontWeight = 'normal', lineHeight, fontFamily = 'Arial' } = attribute; let { fontSize = 12 } = attribute; if (!isFinite(fontSize)) { fontSize = 12; @@ -28,7 +28,8 @@ export function getDefaultCharacterConfig(attribute: IRichTextGraphicAttribute) stroke, fontSize, fontWeight, - fontFamily + fontFamily, + lineHeight } as any; } diff --git a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts index 99c1d1cb4..e7a2d21da 100644 --- a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts +++ b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts @@ -34,6 +34,7 @@ export const page = () => { height: 0, x: 100, y: 100, + lineHeight: '150%', editable: true, // background: 'green', // "textAlign": "center", @@ -41,241 +42,265 @@ export const page = () => { { text: '我', fontSize: 16, - lineHeight: 26, + textAlign: 'center', - background: 'orange', + background: 'rgba(255, 0, 0, 0.3)', fill: '#0f51b5' }, { text: '们', fontSize: 16, - lineHeight: 26, + textAlign: 'center', - background: 'orange', + background: 'rgba(255, 0, 0, 0.3)', fill: '#0f51b5' }, { text: '是', fontSize: 16, - lineHeight: 26, + + textAlign: 'center', + background: 'rgba(255, 0, 0, 0.3)', + fill: '#0f51b5' + }, + { + text: '\n', + fontSize: 16, + + textAlign: 'center', + background: 'rgba(255, 0, 0, 0.3)', + fill: '#0f51b5' + }, + { + text: '\n', + fontSize: 16, + + textAlign: 'center', + background: 'rgba(255, 0, 0, 0.3)', + fill: '#0f51b5' + }, + { + text: '\n', + fontSize: 16, + textAlign: 'center', - background: 'orange', + background: 'rgba(255, 0, 0, 0.3)', fill: '#0f51b5' }, { text: '无', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '缘', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: 'a', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '无', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '故', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '的', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '尘😁', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '埃\n', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '无', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '缘', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '无', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '故', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '的', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '游', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '走\n', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '黑', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '暗', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '只', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '需', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '要', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '张', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '开', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '一', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '张', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '缝', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '隙\n', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '就', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '能', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '挂', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '起', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '飓', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, @@ -283,21 +308,21 @@ export const page = () => { text: '[4]', script: 'super', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: '风\n', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' }, { text: 'and this is our world, \nthat we call life', fontSize: 16, - lineHeight: 26, + textAlign: 'center', fill: '#0f51b5' } From 5d56a9c8802b3cc09c7571ebe8e6290796d56ca1 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 11 Feb 2025 11:45:41 +0800 Subject: [PATCH 2/2] feat: support upgraded attribute control by upgradeAttrs --- packages/vrender-core/src/graphic/config.ts | 1 + packages/vrender-core/src/graphic/richtext.ts | 19 +++++++++++++------ .../src/graphic/richtext/paragraph.ts | 9 ++++++++- .../src/interface/graphic/richText.ts | 8 ++++++++ 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/packages/vrender-core/src/graphic/config.ts b/packages/vrender-core/src/graphic/config.ts index acca145bf..54537a8b5 100644 --- a/packages/vrender-core/src/graphic/config.ts +++ b/packages/vrender-core/src/graphic/config.ts @@ -345,6 +345,7 @@ export const DefaultTextAttribute: Required = { export const DefaultRichTextAttribute: Required = { ...DefaultAttribute, ...DefaultTextStyle, + upgradeAttrs: null, editable: false, editOptions: null, ascentDescentMode: 'actual', diff --git a/packages/vrender-core/src/graphic/richtext.ts b/packages/vrender-core/src/graphic/richtext.ts index 49e365bb8..8ec7099b3 100644 --- a/packages/vrender-core/src/graphic/richtext.ts +++ b/packages/vrender-core/src/graphic/richtext.ts @@ -371,9 +371,10 @@ export class RichText extends Graphic implements IRic opacity, fillOpacity, lineHeight, - strokeOpacity + strokeOpacity, + upgradeAttrs } = this.attribute; - return { + const out = { fill, stroke, fontSize, @@ -383,10 +384,13 @@ export class RichText extends Graphic implements IRic lineWidth, opacity, fillOpacity, - lineHeight, strokeOpacity, ...config }; + if (upgradeAttrs?.lineHeight) { + out.lineHeight = lineHeight; + } + return out; } doUpdateFrameCache(tc?: IRichTextCharacter[]) { // 1. 测量,生成paragraph @@ -404,9 +408,12 @@ export class RichText extends Graphic implements IRic singleLine, disableAutoWrapLine, editable, - ascentDescentMode + ascentDescentMode, + upgradeAttrs } = this.attribute; + const enableMultiBreakLine = upgradeAttrs && upgradeAttrs.multiBreakLine; + let { textConfig: _tc = [] } = this.attribute; // 预处理editable,将textConfig中的text转换为单个字符 @@ -521,7 +528,7 @@ export class RichText extends Graphic implements IRic const wrapper = new Wrapper(frame); // @since 0.22.0 // 如果可编辑的话,则支持多换行符 - wrapper.newLine = editable; + wrapper.newLine = enableMultiBreakLine; if (disableAutoWrapLine) { let lineCount = 0; let skip = false; @@ -581,7 +588,7 @@ export class RichText extends Graphic implements IRic } // 处理空行 - if (editable) { + if (enableMultiBreakLine) { frame.lines.forEach(item => { const lastParagraphs = item.paragraphs; item.paragraphs = item.paragraphs.filter(p => (p as any).text !== ''); diff --git a/packages/vrender-core/src/graphic/richtext/paragraph.ts b/packages/vrender-core/src/graphic/richtext/paragraph.ts index e623da1d0..69b67fe7e 100644 --- a/packages/vrender-core/src/graphic/richtext/paragraph.ts +++ b/packages/vrender-core/src/graphic/richtext/paragraph.ts @@ -175,7 +175,14 @@ export default class Paragraph { textAlign: string, lineHeight: number ) { - if (!(this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0))) { + if ( + !( + this.text !== '' && + this.text !== '\n' && + this.character.background && + (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0) + ) + ) { return; } let baseline = top + ascent; diff --git a/packages/vrender-core/src/interface/graphic/richText.ts b/packages/vrender-core/src/interface/graphic/richText.ts index f14049752..de07d6c98 100644 --- a/packages/vrender-core/src/interface/graphic/richText.ts +++ b/packages/vrender-core/src/interface/graphic/richText.ts @@ -19,6 +19,14 @@ export type IRichTextEditOptionsType = { }; export type IRichTextAttribute = { + /** + * @since 0.22.1 + * 升级后避免break change,通过开关来控制 + */ + upgradeAttrs: { + lineHeight: true; + multiBreakLine: true; + } | null; /** * 富文本的总宽度 */