From 1bd2e455a5f5c0bd53cb51d30e8205cd6a148e7c Mon Sep 17 00:00:00 2001 From: Hufe921 Date: Wed, 19 Jul 2023 19:52:56 +0800 Subject: [PATCH] improve: cursor position at the beginning of a line --- src/editor/core/cursor/Cursor.ts | 13 ++++++--- src/editor/core/event/handlers/mousedown.ts | 17 ++++++++++-- src/editor/core/position/Position.ts | 29 ++++++++++++++++----- src/editor/interface/Element.ts | 1 + src/editor/interface/Position.ts | 1 + 5 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/editor/core/cursor/Cursor.ts b/src/editor/core/cursor/Cursor.ts index d6d4931..568bd17 100644 --- a/src/editor/core/cursor/Cursor.ts +++ b/src/editor/core/cursor/Cursor.ts @@ -12,6 +12,7 @@ export type IDrawCursorOption = ICursorOption & { isShow?: boolean isBlink?: boolean isFocus?: boolean + hitLineStartIndex?: number } export class Cursor { @@ -82,7 +83,7 @@ export class Cursor { } public drawCursor(payload?: IDrawCursorOption) { - const cursorPosition = this.position.getCursorPosition() + let cursorPosition = this.position.getCursorPosition() if (!cursorPosition) return const { scale, cursor } = this.options const { @@ -90,11 +91,17 @@ export class Cursor { width, isShow = true, isBlink = true, - isFocus = true + isFocus = true, + hitLineStartIndex } = { ...cursor, ...payload } // 设置光标代理 const height = this.draw.getHeight() const pageGap = this.draw.getPageGap() + // 光标位置 + if (hitLineStartIndex) { + const positionList = this.position.getPositionList() + cursorPosition = positionList[hitLineStartIndex] + } const { metrics, coordinate: { leftTop, rightTop }, @@ -121,7 +128,7 @@ export class Cursor { metrics.boundingBoxDescent < 0 ? 0 : metrics.boundingBoxDescent const cursorTop = leftTop[1] + ascent + descent - (cursorHeight - offsetHeight) + preY - const cursorLeft = rightTop[0] + const cursorLeft = hitLineStartIndex ? leftTop[0] : rightTop[0] agentCursorDom.style.left = `${cursorLeft}px` agentCursorDom.style.top = `${ cursorTop + cursorHeight - CURSOR_AGENT_HEIGHT * scale diff --git a/src/editor/core/event/handlers/mousedown.ts b/src/editor/core/event/handlers/mousedown.ts index 409d178..bedbb91 100644 --- a/src/editor/core/event/handlers/mousedown.ts +++ b/src/editor/core/event/handlers/mousedown.ts @@ -40,8 +40,15 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) { y: evt.offsetY }) if (!positionResult) return - const { index, isDirectHit, isCheckbox, isImage, isTable, tdValueIndex } = - positionResult + const { + index, + isDirectHit, + isCheckbox, + isImage, + isTable, + tdValueIndex, + hitLineStartIndex + } = positionResult // 记录选区开始位置 host.mouseDownStartPosition = { ...positionResult, @@ -80,6 +87,12 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) { isSetCursor: !isDirectHitImage && !isDirectHitCheckbox, isCompute: false }) + // 首字需定位到行首,非上一行最后一个字后 + if (hitLineStartIndex) { + host.getDraw().getCursor().drawCursor({ + hitLineStartIndex + }) + } } // 预览工具组件 const previewer = draw.getPreviewer() diff --git a/src/editor/core/position/Position.ts b/src/editor/core/position/Position.ts index 0618eaa..7a1fe46 100644 --- a/src/editor/core/position/Position.ts +++ b/src/editor/core/position/Position.ts @@ -128,6 +128,7 @@ export class Position { metrics, ascent: offsetY, lineHeight: curRow.height, + isFirstLetter: j === 0, isLastLetter: j === curRow.elementList.length - 1, coordinate: { leftTop: [x, y], @@ -262,6 +263,7 @@ export class Position { const { index, pageNo, + isFirstLetter, coordinate: { leftTop, rightTop, leftBottom } } = positionList[j] if (positionNo !== pageNo) continue @@ -290,7 +292,7 @@ export class Position { positionList: td.positionList }) if (~tablePosition.index) { - const { index: tdValueIndex } = tablePosition + const { index: tdValueIndex, hitLineStartIndex } = tablePosition const tdValueElement = td.value[tdValueIndex] return { index, @@ -307,7 +309,8 @@ export class Position { tdValueIndex, tdId: td.id, trId: tr.id, - tableId: element.id + tableId: element.id, + hitLineStartIndex } } } @@ -334,14 +337,19 @@ export class Position { isCheckbox: true } } + let hitLineStartIndex: number | undefined // 判断是否在文字中间前后 if (elementList[index].value !== ZERO) { const valueWidth = rightTop[0] - leftTop[0] if (x < leftTop[0] + valueWidth / 2) { curPositionIndex = j - 1 + if (isFirstLetter) { + hitLineStartIndex = j + } } } return { + hitLineStartIndex, index: curPositionIndex, isControl: element.type === ElementType.CONTROL } @@ -350,6 +358,7 @@ export class Position { // 非命中区域 let isLastArea = false let curPositionIndex = -1 + let hitLineStartIndex: number | undefined // 判断是否在表格内 if (isTable) { const { scale } = this.options @@ -386,11 +395,16 @@ export class Position { p => p.pageNo === positionNo && p.rowNo === lastLetterList[j].rowNo ) // 头部元素为空元素时无需选中 - curPositionIndex = ~headIndex - ? positionList[headIndex].value === ZERO - ? headIndex - : headIndex - 1 - : index + if (~headIndex) { + if (positionList[headIndex].value === ZERO) { + curPositionIndex = headIndex + } else { + curPositionIndex = headIndex - 1 + hitLineStartIndex = headIndex + } + } else { + curPositionIndex = index + } } else { curPositionIndex = index } @@ -440,6 +454,7 @@ export class Position { } } return { + hitLineStartIndex, index: curPositionIndex, isControl: elementList[curPositionIndex]?.type === ElementType.CONTROL } diff --git a/src/editor/interface/Element.ts b/src/editor/interface/Element.ts index deba7f4..df83d4e 100644 --- a/src/editor/interface/Element.ts +++ b/src/editor/interface/Element.ts @@ -132,6 +132,7 @@ export interface IElementPosition { ascent: number lineHeight: number metrics: IElementMetrics + isFirstLetter: boolean isLastLetter: boolean coordinate: { leftTop: number[] diff --git a/src/editor/interface/Position.ts b/src/editor/interface/Position.ts index 69d1e6f..8c0f2d3 100644 --- a/src/editor/interface/Position.ts +++ b/src/editor/interface/Position.ts @@ -18,6 +18,7 @@ export interface ICurrentPosition { trId?: string tableId?: string zone?: EditorZone + hitLineStartIndex?: number } export interface IGetPositionByXYPayload {