From a96a77a237a62f0881a2b106b040f29c840fff58 Mon Sep 17 00:00:00 2001 From: Hufe921 Date: Thu, 3 Aug 2023 21:44:03 +0800 Subject: [PATCH] fix: cursor navigation across pages #229 --- src/editor/core/event/handlers/keydown.ts | 149 ++++++++++++---------- 1 file changed, 82 insertions(+), 67 deletions(-) diff --git a/src/editor/core/event/handlers/keydown.ts b/src/editor/core/event/handlers/keydown.ts index b6460aa..c2f2ca7 100644 --- a/src/editor/core/event/handlers/keydown.ts +++ b/src/editor/core/event/handlers/keydown.ts @@ -205,86 +205,101 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) { } } const { - rowNo, index, - pageNo, - coordinate: { leftTop, rightTop } + rowNo, + rowIndex, + coordinate: { + leftTop: [curLeftX], + rightTop: [curRightX] + } } = anchorPosition - if ((isUp && rowNo !== 0) || (!isUp && rowNo !== draw.getRowCount())) { - // 下一个光标点所在行位置集合 - const probablePosition = isUp - ? positionList - .slice(0, index) - .filter(p => p.rowNo === rowNo - 1 && pageNo === p.pageNo) - : positionList - .slice(index, positionList.length - 1) - .filter(p => p.rowNo === rowNo + 1 && pageNo === p.pageNo) - // 查找与当前位置元素点交叉最多的位置 - let maxIndex = 0 - let maxDistance = 0 - for (let p = 0; p < probablePosition.length; p++) { - const position = probablePosition[p] - // 当前光标在前 + // 向上时在首行、向下时再最尾则忽略 + if ( + (isUp && rowIndex === 0) || + (!isUp && rowIndex === draw.getRowCount() - 1) + ) { + return + } + // 查找下一行信息 + const probablePosition: IElementPosition[] = [] + if (isUp) { + let p = index - 1 + while (p > 0) { + const position = positionList[p] + p-- + if (position.rowNo === rowNo) continue if ( - position.coordinate.leftTop[0] >= leftTop[0] && - position.coordinate.leftTop[0] <= rightTop[0] + probablePosition[0] && + probablePosition[0].rowNo !== position.rowNo ) { - const curDistance = rightTop[0] - position.coordinate.leftTop[0] - if (curDistance > maxDistance) { - maxIndex = position.index - maxDistance = curDistance - break - } + break } - // 当前光标在后 - else if ( - position.coordinate.leftTop[0] <= leftTop[0] && - position.coordinate.rightTop[0] >= leftTop[0] + probablePosition.unshift(position) + } + } else { + let p = index + 1 + while (p < positionList.length) { + const position = positionList[p] + p++ + if (position.rowNo === rowNo) continue + if ( + probablePosition[0] && + probablePosition[0].rowNo !== position.rowNo ) { - const curDistance = position.coordinate.rightTop[0] - leftTop[0] - if (curDistance > maxDistance) { - maxIndex = position.index - maxDistance = curDistance - break - } + break } - // 匹配不到 - if (p === probablePosition.length - 1 && maxIndex === 0) { - maxIndex = position.index + probablePosition.push(position) + } + } + // 查找下一行位置:第一个存在交叉宽度的元素位置 + let nextIndex = 0 + for (let p = 0; p < probablePosition.length; p++) { + const nextPosition = probablePosition[p] + const { + coordinate: { + leftTop: [nextLeftX], + rightTop: [nextRightX] } + } = nextPosition + if (p === probablePosition.length - 1) { + nextIndex = nextPosition.index } - const curIndex = maxIndex - // shift则缩放选区 - let anchorStartIndex = curIndex - let anchorEndIndex = curIndex - if (evt.shiftKey) { - if (startIndex !== endIndex) { - if (startIndex === cursorPosition.index) { - anchorStartIndex = startIndex - } else { - anchorEndIndex = endIndex - } + if (curRightX <= nextLeftX || curLeftX >= nextRightX) continue + nextIndex = nextPosition.index + break + } + if (!nextIndex) return + const curIndex = nextIndex + // shift则缩放选区 + let anchorStartIndex = curIndex + let anchorEndIndex = curIndex + if (evt.shiftKey) { + if (startIndex !== endIndex) { + if (startIndex === cursorPosition.index) { + anchorStartIndex = startIndex } else { - if (isUp) { - anchorEndIndex = endIndex - } else { - anchorStartIndex = startIndex - } + anchorEndIndex = endIndex + } + } else { + if (isUp) { + anchorEndIndex = endIndex + } else { + anchorStartIndex = startIndex } } - if (anchorStartIndex > anchorEndIndex) { - // prettier-ignore - [anchorStartIndex, anchorEndIndex] = [anchorEndIndex, anchorStartIndex] - } - rangeManager.setRange(anchorStartIndex, anchorEndIndex) - const isCollapsed = anchorStartIndex === anchorEndIndex - draw.render({ - curIndex: isCollapsed ? anchorStartIndex : undefined, - isSetCursor: isCollapsed, - isSubmitHistory: false, - isCompute: false - }) } + if (anchorStartIndex > anchorEndIndex) { + // prettier-ignore + [anchorStartIndex, anchorEndIndex] = [anchorEndIndex, anchorStartIndex] + } + rangeManager.setRange(anchorStartIndex, anchorEndIndex) + const isCollapsed = anchorStartIndex === anchorEndIndex + draw.render({ + curIndex: isCollapsed ? anchorStartIndex : undefined, + isSetCursor: isCollapsed, + isSubmitHistory: false, + isCompute: false + }) } else if (isMod(evt) && evt.key === KeyMap.Z) { if (isReadonly) return historyManager.undo()