Skip to content

Commit

Permalink
feat: support multi break-line
Browse files Browse the repository at this point in the history
  • Loading branch information
neuqzxy committed Dec 17, 2024
1 parent 17878c2 commit 22c9b10
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 27 deletions.
23 changes: 19 additions & 4 deletions packages/vrender-core/src/graphic/richtext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,9 @@ export class RichText extends Graphic<IRichTextGraphicAttribute> implements IRic
this._frameCache?.icons
);
const wrapper = new Wrapper(frame);
// @since 0.22.0
// 如果可编辑的话,则支持多换行符
wrapper.newLine = editable;
if (disableAutoWrapLine) {
let lineCount = 0;
let skip = false;
Expand Down Expand Up @@ -508,11 +511,11 @@ export class RichText extends Graphic<IRichTextGraphicAttribute> implements IRic
}
} else {
for (let i = 0; i < paragraphs.length; i++) {
if (i === paragraphs.length - 1) {
wrapper.newLine = true;
}
// if (i === paragraphs.length - 1) {
// wrapper.newLine = true;
// }
wrapper.deal(paragraphs[i]);
wrapper.newLine = false;
// wrapper.newLine = false;
}
}

Expand Down Expand Up @@ -540,6 +543,18 @@ export class RichText extends Graphic<IRichTextGraphicAttribute> implements IRic
});
}

// 处理空行
if (editable) {
frame.lines.forEach(item => {
const lastParagraphs = item.paragraphs;
item.paragraphs = item.paragraphs.filter(p => (p as any).text !== '');
if (item.paragraphs.length === 0 && lastParagraphs.length) {
(lastParagraphs[0] as any).text = '\n';
item.paragraphs.push(lastParagraphs[0]);
}
});
}

this._frameCache = frame;

// this.bindIconEvent();
Expand Down
49 changes: 30 additions & 19 deletions packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import { application } from '../../application';
import type { IRichText, IRichTextCharacter, IRichTextParagraphCharacter } from '../../interface';

let isMac = false;
try {
isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
} catch (err) {
// ignore
}

function getMaxConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[]) {
let idx = 0;
for (let i = 0; i < textConfig.length; i++) {
Expand All @@ -20,22 +13,27 @@ function getMaxConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[]) {
}

/**
* 找到cursorIndex所在的textConfig的位置,忽略换行符
* 找到cursorIndex所在的textConfig的位置,忽略单个换行符,连续换行符的时候只忽略第一个
* @param textConfig
* @param cursorIndex
* @returns
*/
export function findConfigIndex(textConfig: IRichTextCharacter[], cursorIndex: number): number {
export function findConfigIndexByCursorIdx(textConfig: IRichTextCharacter[], cursorIndex: number): number {
let index = 0;
// 小于0是在最前面了
if (cursorIndex < 0) {
return -1;
}
let idx = Math.round(cursorIndex);
let lastLineBreak = true;
for (index = 0; index < textConfig.length; index++) {
const c = textConfig[index] as IRichTextParagraphCharacter;
if (c.text !== '\n') {
if (c.text === '\n') {
idx -= Number(lastLineBreak);
lastLineBreak = true;
} else {
idx--;
lastLineBreak = false;
}
if (idx < 0) {
break;
Expand All @@ -49,16 +47,29 @@ export function findConfigIndex(textConfig: IRichTextCharacter[], cursorIndex: n
return Math.min(index, textConfig.length - 1);
}

export function textConfigIgnoreLinebreakIdxToCursorIdx(textConfig: IRichTextCharacter[], cursorIndex: number): number {
export function findCursorIdxByConfigIndex(textConfig: IRichTextCharacter[], configIndex: number): number {
let index = 0;
for (let i = 0; i < cursorIndex; i++) {
// 仅有一个\n,那不算
// 如果有连续的\n,那就少算一个
let lastLineBreak = true;
let delta = 0;
for (let i = 0; i <= configIndex + delta; i++) {
const c = textConfig[i] as IRichTextParagraphCharacter;
if (c.text !== '\n') {
if (c.text === '\n') {
index += Number(lastLineBreak);
// 第一个换行符当做不存在
delta += 1 - Number(lastLineBreak);
lastLineBreak = true;
} else {
index++;
lastLineBreak = false;
// 回归
delta = 0;
}
}
index = Math.max(index - 1, 0);
// 正常Cursor是放在右边的,但如果回退到换行符了,那就放在左侧
if ((textConfig[cursorIndex] as any)?.text === '\n') {
if ((textConfig[configIndex] as any)?.text === '\n') {
index -= 0.1;
} else {
index += 0.1;
Expand Down Expand Up @@ -124,7 +135,7 @@ export class EditModule {
const config = textConfig[0];
textConfig.unshift({ fill: 'black', ...config, text: '' });
} else {
const cursorIndex = findConfigIndex(textConfig, this.cursorIndex);
const cursorIndex = findConfigIndexByCursorIdx(textConfig, this.cursorIndex);
const lastConfig = textConfig[cursorIndex];
textConfig.splice(cursorIndex + 1, 0, { ...lastConfig, text: '' });
}
Expand All @@ -135,7 +146,7 @@ export class EditModule {
this.isComposing = false;
// 拆分上一次的内容
const { textConfig = [] } = this.currRt.attribute;
const configIdx = findConfigIndex(textConfig, this.cursorIndex + 1);
const configIdx = findConfigIndexByCursorIdx(textConfig, this.cursorIndex + 1);

const lastConfig = textConfig[configIdx];
textConfig.splice(configIdx, 1);
Expand Down Expand Up @@ -187,9 +198,9 @@ export class EditModule {

// 转换成基于textConfig的
// let delta = 0;
startIdx = findConfigIndex(textConfig, startIdx);
startIdx = findConfigIndexByCursorIdx(textConfig, startIdx);
// delta = this.selectionStartCursorIdx - startIdx;
endIdx = findConfigIndex(textConfig, endIdx);
endIdx = findConfigIndexByCursorIdx(textConfig, endIdx);
// console.log(startIdx, delta, endIdx);

let idxDelta = 0;
Expand Down Expand Up @@ -238,7 +249,7 @@ export class EditModule {
}

this.currRt.setAttributes({ textConfig });
this.cursorIndex = textConfigIgnoreLinebreakIdxToCursorIdx(textConfig, startIdx);
this.cursorIndex = findCursorIdxByConfigIndex(textConfig, startIdx);

this.cursorIndex += idxDelta;
if (!this.isComposing) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import type {
ITimeline
} from '../../interface';
import { Animate, DefaultTicker, DefaultTimeline } from '../../animate';
import { EditModule, findConfigIndex } from './edit-module';
import { EditModule, findConfigIndexByCursorIdx } from './edit-module';
import { application } from '../../application';
import { getWordStartEndIdx } from '../../graphic/richtext/utils';
// import { testLetter, testLetter2 } from '../../graphic/richtext/utils';
Expand Down Expand Up @@ -48,8 +48,8 @@ class Selection {
return '';
}
const config = this.rt.attribute.textConfig as any;
const startIdx = findConfigIndex(config, Math.ceil(minCursorIdx));
const endIdx = findConfigIndex(config, Math.floor(maxCursorIdx));
const startIdx = findConfigIndexByCursorIdx(config, Math.ceil(minCursorIdx));
const endIdx = findConfigIndexByCursorIdx(config, Math.floor(maxCursorIdx));
let str = '';
for (let i = startIdx; i <= endIdx; i++) {
str += config[i].text;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const page = () => {
// "textAlign": "center",
textConfig: [
{
text: 'and this is our world, \nthat we call life',
text: 'and',
fontSize: 16,
lineHeight: 26,
textAlign: 'center',
Expand Down

0 comments on commit 22c9b10

Please sign in to comment.