From 63487d4f90332be68cb07f3eacfca3a0d04f8eff Mon Sep 17 00:00:00 2001 From: Hufe921 Date: Tue, 21 Feb 2023 11:04:52 +0800 Subject: [PATCH] feat:render composing text --- src/editor/core/cursor/Cursor.ts | 8 +++ src/editor/core/cursor/CursorAgent.ts | 4 +- src/editor/core/event/CanvasEvent.ts | 18 +++++-- src/editor/core/event/handlers/composition.ts | 25 ++++++++-- src/editor/core/event/handlers/input.ts | 49 +++++++++++++------ src/editor/core/event/handlers/keydown.ts | 1 + 6 files changed, 82 insertions(+), 23 deletions(-) diff --git a/src/editor/core/cursor/Cursor.ts b/src/editor/core/cursor/Cursor.ts index 0e91df1..00eb399 100644 --- a/src/editor/core/cursor/Cursor.ts +++ b/src/editor/core/cursor/Cursor.ts @@ -35,6 +35,14 @@ export class Cursor { return this.cursorAgent.getAgentCursorDom() } + public getAgentDomValue(): string { + return this.getAgentDom().value + } + + public clearAgentDomValue(): string { + return this.getAgentDom().value = '' + } + public drawCursor() { const isReadonly = this.draw.isReadonly() const cursorPosition = this.position.getCursorPosition() diff --git a/src/editor/core/cursor/CursorAgent.ts b/src/editor/core/cursor/CursorAgent.ts index 2cfb88f..c757f39 100644 --- a/src/editor/core/cursor/CursorAgent.ts +++ b/src/editor/core/cursor/CursorAgent.ts @@ -103,8 +103,8 @@ export class CursorAgent { this.canvasEvent.compositionstart() } - private _compositionend() { - this.canvasEvent.compositionend() + private _compositionend(evt: CompositionEvent) { + this.canvasEvent.compositionend(evt) } } \ No newline at end of file diff --git a/src/editor/core/event/CanvasEvent.ts b/src/editor/core/event/CanvasEvent.ts index c2bb2df..dec3272 100644 --- a/src/editor/core/event/CanvasEvent.ts +++ b/src/editor/core/event/CanvasEvent.ts @@ -19,10 +19,19 @@ import click from './handlers/click' import composition from './handlers/composition' import drag from './handlers/drag' +export interface ICompositionInfo { + elementList: IElement[]; + startIndex: number; + endIndex: number; + value: string; +} + export class CanvasEvent { public isAllowSelection: boolean - public isCompositing: boolean + public isComposing: boolean + public compositionInfo: ICompositionInfo | null + public isAllowDrag: boolean public isAllowDrop: boolean public cacheRange: IRange | null @@ -44,7 +53,8 @@ export class CanvasEvent { this.position = this.draw.getPosition() this.isAllowSelection = false - this.isCompositing = false + this.isComposing = false + this.compositionInfo = null this.isAllowDrag = false this.isAllowDrop = false this.cacheRange = null @@ -161,8 +171,8 @@ export class CanvasEvent { composition.compositionstart(this) } - public compositionend() { - composition.compositionend(this) + public compositionend(evt: CompositionEvent) { + composition.compositionend(this, evt) } public drop(evt: DragEvent) { diff --git a/src/editor/core/event/handlers/composition.ts b/src/editor/core/event/handlers/composition.ts index 1615f40..a6cff8d 100644 --- a/src/editor/core/event/handlers/composition.ts +++ b/src/editor/core/event/handlers/composition.ts @@ -1,11 +1,30 @@ import { CanvasEvent } from '../CanvasEvent' +import { input, removeComposingInput } from './input' function compositionstart(host: CanvasEvent) { - host.isCompositing = true + host.isComposing = true } -function compositionend(host: CanvasEvent) { - host.isCompositing = false +function compositionend(host: CanvasEvent, evt: CompositionEvent) { + host.isComposing = false + removeComposingInput(host) + const draw = host.getDraw() + const cursor = draw.getCursor() + // 合成结果不存在(输入框关闭),无法触发input事件需手动触发渲染 + if (!evt.data) { + const agentText = cursor.getAgentDomValue() + if (agentText) { + input(agentText, host) + } else { + const rangeManager = draw.getRange() + const { endIndex: curIndex } = rangeManager.getRange() + draw.render({ + curIndex + }) + } + } + // 移除代理输入框数据 + cursor.clearAgentDomValue() } export default { diff --git a/src/editor/core/event/handlers/input.ts b/src/editor/core/event/handlers/input.ts index 56cf904..c0f000c 100644 --- a/src/editor/core/event/handlers/input.ts +++ b/src/editor/core/event/handlers/input.ts @@ -11,22 +11,24 @@ export function input(data: string, host: CanvasEvent) { if (isReadonly) return const position = draw.getPosition() const cursorPosition = position.getCursorPosition() - if (!data || !cursorPosition || host.isCompositing) return + if (!data || !cursorPosition) return const control = draw.getControl() if (control.isPartRangeInControlOutside()) { // 忽略选区部分在控件的输入 return } + // 移除合成输入 + if (!host.isComposing) { + const cursor = draw.getCursor() + cursor.clearAgentDomValue() + } else { + removeComposingInput(host) + } const activeControl = control.getActiveControl() const { TEXT, HYPERLINK, SUBSCRIPT, SUPERSCRIPT, DATE } = ElementType const text = data.replaceAll(`\n`, ZERO) - const cursor = draw.getCursor() - const agentDom = cursor.getAgentDom() - agentDom.value = '' - const { index } = cursorPosition const rangeManager = draw.getRange() const { startIndex, endIndex } = rangeManager.getRange() - const isCollapsed = startIndex === endIndex // 表格需要上下文信息 const positionContext = position.getPositionContext() let restArg = {} @@ -57,6 +59,9 @@ export function input(data: string, host: CanvasEvent) { } }) } + if (host.isComposing) { + newElement.underline = true + } return newElement }) // 控件-移除placeholder @@ -64,19 +69,35 @@ export function input(data: string, host: CanvasEvent) { if (activeControl && elementList[endIndex + 1]?.controlId === element.controlId) { curIndex = control.setValue(inputData) } else { - let start = 0 - if (isCollapsed) { - start = index + 1 - } else { - start = startIndex + 1 - elementList.splice(startIndex + 1, endIndex - startIndex) + const start = startIndex + 1 + if (startIndex !== endIndex) { + elementList.splice(start, endIndex - startIndex) } // 禁止直接使用解构存在性能问题 for (let i = 0; i < inputData.length; i++) { elementList.splice(start + i, 0, inputData[i]) } - curIndex = (isCollapsed ? index : startIndex) + inputData.length + curIndex = startIndex + inputData.length } rangeManager.setRange(curIndex, curIndex) - draw.render({ curIndex }) + draw.render({ + curIndex + }) + if (host.isComposing) { + host.compositionInfo = { + elementList, + value: text, + startIndex: curIndex - inputData.length, + endIndex: curIndex + } + } +} + +export function removeComposingInput(host: CanvasEvent) { + if (!host.compositionInfo) return + const { elementList, startIndex, endIndex } = host.compositionInfo + elementList.splice(startIndex + 1, endIndex - startIndex) + const rangeManager = host.getDraw().getRange() + rangeManager.setRange(startIndex, startIndex) + host.compositionInfo = null } \ No newline at end of file diff --git a/src/editor/core/event/handlers/keydown.ts b/src/editor/core/event/handlers/keydown.ts index c5568da..b09c4d9 100644 --- a/src/editor/core/event/handlers/keydown.ts +++ b/src/editor/core/event/handlers/keydown.ts @@ -6,6 +6,7 @@ import { isMod } from '../../../utils/hotkey' import { CanvasEvent } from '../CanvasEvent' export function keydown(evt: KeyboardEvent, host: CanvasEvent) { + if (host.isComposing) return const draw = host.getDraw() const position = draw.getPosition() const cursorPosition = position.getCursorPosition()