diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index 736537a..3fa7524 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -34,6 +34,7 @@ import { SeparatorParticle } from './particle/Separator' import { PageBreakParticle } from './particle/PageBreak' import { Watermark } from './frame/Watermark' import { EditorMode } from '../../dataset/enum/Editor' +import { Control } from './control/Control' export class Draw { @@ -70,6 +71,7 @@ export class Draw { private pageBreakParticle: PageBreakParticle private superscriptParticle: SuperscriptParticle private subscriptParticle: SubscriptParticle + private control: Control private rowList: IRow[] private painterStyle: IElementStyle | null @@ -116,6 +118,7 @@ export class Draw { this.pageBreakParticle = new PageBreakParticle(this) this.superscriptParticle = new SuperscriptParticle() this.subscriptParticle = new SubscriptParticle() + this.control = new Control(this) new ScrollObserver(this) new SelectionObserver() @@ -301,6 +304,10 @@ export class Draw { return this.hyperlinkParticle } + public getControl(): Control { + return this.control + } + public getRowCount(): number { return this.rowList.length } diff --git a/src/editor/core/draw/control/Control.ts b/src/editor/core/draw/control/Control.ts index db7fd68..b3b597a 100644 --- a/src/editor/core/draw/control/Control.ts +++ b/src/editor/core/draw/control/Control.ts @@ -1,3 +1,71 @@ +import { ControlComponent } from '../../../dataset/enum/Control' +import { ElementType } from '../../../dataset/enum/Element' +import { IElement } from '../../../interface/Element' +import { ICurrentPosition } from '../../../interface/Position' +import { Draw } from '../Draw' + export class Control { - + + private draw: Draw + + constructor(draw: Draw) { + this.draw = draw + } + + // 调整起始光标位置到控件合适的位置 + public moveCursorIndex(position: ICurrentPosition) { + const { index, trIndex, tdIndex, tdValueIndex } = position + let elementList = this.draw.getOriginalElementList() + let element: IElement + if (position.isTable) { + elementList = elementList[index!].trList![trIndex!].tdList[tdIndex!].value + element = elementList[tdValueIndex!] + } else { + element = elementList[index] + } + if (element.type !== ElementType.CONTROL) return + // VALUE-无需移动 + if (element.controlComponent === ControlComponent.VALUE) return + // POSTFIX-移动到最后一个后缀字符后 + if (element.controlComponent === ControlComponent.POSTFIX) { + let startIndex = index + 1 + while (startIndex < elementList.length) { + const nextElement = elementList[startIndex] + if (nextElement.controlId !== element.controlId) { + position.index = startIndex - 1 + break + } + startIndex++ + } + } else if (element.controlComponent === ControlComponent.PREFIX) { + // PREFIX-移动到最后一个前缀字符后 + let startIndex = index + 1 + while (startIndex < elementList.length) { + const nextElement = elementList[startIndex] + if ( + nextElement.controlId !== element.controlId + || nextElement.controlComponent !== ControlComponent.PREFIX + ) { + position.index = startIndex - 1 + break + } + startIndex++ + } + } else if (element.controlComponent === ControlComponent.PLACEHOLDER) { + // PLACEHOLDER-移动到第一个前缀后 + let startIndex = index - 1 + while (startIndex > 0) { + const preElement = elementList[startIndex] + if ( + preElement.controlId !== element.controlId + || preElement.controlComponent === ControlComponent.PREFIX + ) { + position.index = startIndex + break + } + startIndex-- + } + } + } + } \ No newline at end of file diff --git a/src/editor/core/event/CanvasEvent.ts b/src/editor/core/event/CanvasEvent.ts index dbe45a6..342d0ac 100644 --- a/src/editor/core/event/CanvasEvent.ts +++ b/src/editor/core/event/CanvasEvent.ts @@ -20,6 +20,7 @@ import { Listener } from '../listener/Listener' import { Position } from '../position/Position' import { RangeManager } from '../range/RangeManager' import { LETTER_REG, NUMBER_LIKE_REG } from '../../dataset/constant/Regular' +import { Control } from '../draw/control/Control' export class CanvasEvent { @@ -38,6 +39,7 @@ export class CanvasEvent { private tableTool: TableTool private hyperlinkParticle: HyperlinkParticle private listener: Listener + private control: Control constructor(draw: Draw) { this.isAllowDrag = false @@ -55,6 +57,7 @@ export class CanvasEvent { this.tableTool = this.draw.getTableTool() this.hyperlinkParticle = this.draw.getHyperlinkParticle() this.listener = this.draw.getListener() + this.control = this.draw.getControl() } public register() { @@ -163,9 +166,14 @@ export class CanvasEvent { x: evt.offsetX, y: evt.offsetY }) + // 如果是控件-光标需移动到合适位置 + if (positionResult.isControl) { + this.control.moveCursorIndex(positionResult) + } const { index, isDirectHit, + isControl, isImage, isTable, trIndex, @@ -178,6 +186,7 @@ export class CanvasEvent { // 设置位置上下文 this.position.setPositionContext({ isTable: isTable || false, + isControl: isControl || false, index, trIndex, tdIndex, diff --git a/src/editor/core/position/Position.ts b/src/editor/core/position/Position.ts index 281bceb..cccacf9 100644 --- a/src/editor/core/position/Position.ts +++ b/src/editor/core/position/Position.ts @@ -18,7 +18,8 @@ export class Position { this.positionList = [] this.cursorPosition = null this.positionContext = { - isTable: false + isTable: false, + isControl: false } this.draw = draw @@ -92,14 +93,16 @@ export class Position { positionList: td.positionList }) if (~tablePosition.index) { + const { index: tdValueIndex } = tablePosition return { index, + isControl: td.value[tdValueIndex].type === ElementType.CONTROL, isImage: tablePosition.isImage, isDirectHit: tablePosition.isDirectHit, isTable: true, tdIndex: d, trIndex: t, - tdValueIndex: tablePosition.index, + tdValueIndex, tdId: td.id, trId: tr.id, tableId: element.id @@ -110,7 +113,11 @@ export class Position { } // 图片区域均为命中 if (element.type === ElementType.IMAGE) { - return { index: curPositionIndex, isDirectHit: true, isImage: true } + return { + index: curPositionIndex, + isDirectHit: true, + isImage: true + } } // 判断是否在文字中间前后 if (elementList[index].value !== ZERO) { @@ -119,7 +126,10 @@ export class Position { curPositionIndex = j - 1 } } - return { index: curPositionIndex } + return { + index: curPositionIndex, + isControl: element.type === ElementType.CONTROL, + } } } // 非命中区域 @@ -135,7 +145,9 @@ export class Position { const tdWidth = td.width! const tdHeight = td.height! if (!(tdX < x && x < tdX + tdWidth && tdY < y && y < tdY + tdHeight)) { - return { index: curPositionIndex } + return { + index: curPositionIndex + } } } } @@ -161,7 +173,10 @@ export class Position { // 当前页最后一行 return { index: firstLetterList[firstLetterList.length - 1]?.index || positionList.length - 1 } } - return { index: curPositionIndex } + return { + index: curPositionIndex, + isControl: elementList[curPositionIndex].type === ElementType.CONTROL + } } } \ No newline at end of file diff --git a/src/editor/dataset/constant/Control.ts b/src/editor/dataset/constant/Control.ts index ff2ee47..2190bc3 100644 --- a/src/editor/dataset/constant/Control.ts +++ b/src/editor/dataset/constant/Control.ts @@ -2,5 +2,7 @@ import { IControlOption } from '../../interface/Control' export const defaultControlOption: Readonly> = { placeholderColor: '#9c9b9b', - bracketColor: '#000000' + bracketColor: '#000000', + prefix: '{', + postfix: '}' } \ No newline at end of file diff --git a/src/editor/dataset/enum/Control.ts b/src/editor/dataset/enum/Control.ts index 15ea71a..00670db 100644 --- a/src/editor/dataset/enum/Control.ts +++ b/src/editor/dataset/enum/Control.ts @@ -4,7 +4,7 @@ export enum ControlType { } export enum ControlComponent { - SUFFIX = 'suffix', + PREFIX = 'prefix', POSTFIX = 'postfix', PLACEHOLDER = 'placeholder', VALUE = 'value' diff --git a/src/editor/interface/Control.ts b/src/editor/interface/Control.ts index a380a0d..78f56a0 100644 --- a/src/editor/interface/Control.ts +++ b/src/editor/interface/Control.ts @@ -24,4 +24,6 @@ export type IControl = IControlBasic & Partial export interface IControlOption { placeholderColor?: string; bracketColor?: string; + prefix?: string; + postfix?: string; } \ No newline at end of file diff --git a/src/editor/interface/Position.ts b/src/editor/interface/Position.ts index 2461ce4..4e95072 100644 --- a/src/editor/interface/Position.ts +++ b/src/editor/interface/Position.ts @@ -4,6 +4,7 @@ import { ITd } from './table/Td' export interface ICurrentPosition { index: number; + isControl?: boolean; isImage?: boolean; isTable?: boolean; isDirectHit?: boolean; @@ -27,6 +28,7 @@ export interface IGetPositionByXYPayload { export interface IPositionContext { isTable: boolean; + isControl?: boolean; index?: number; trIndex?: number; tdIndex?: number; diff --git a/src/editor/utils/element.ts b/src/editor/utils/element.ts index 507f3d3..8af8aa7 100644 --- a/src/editor/utils/element.ts +++ b/src/editor/utils/element.ts @@ -75,9 +75,9 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme // 移除父节点 elementList.splice(i, 1) // 前后缀个性化设置 - const thePreSuffixArgs: Pick = {} + const thePrePostfixArgs: Pick = {} if (editorOptions && editorOptions.control) { - thePreSuffixArgs.color = editorOptions.control.bracketColor + thePrePostfixArgs.color = editorOptions.control.bracketColor } // 前缀 if (prefix) { @@ -89,8 +89,8 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme value, type: el.type, control: el.control, - controlComponent: ControlComponent.SUFFIX, - ...thePreSuffixArgs + controlComponent: ControlComponent.PREFIX, + ...thePrePostfixArgs }) i++ } @@ -143,7 +143,7 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme type: el.type, control: el.control, controlComponent: ControlComponent.POSTFIX, - ...thePreSuffixArgs + ...thePrePostfixArgs }) i++ } diff --git a/src/editor/utils/index.ts b/src/editor/utils/index.ts index 18578ae..f571403 100644 --- a/src/editor/utils/index.ts +++ b/src/editor/utils/index.ts @@ -19,7 +19,7 @@ export function deepClone(obj: T): T { if (Array.isArray(obj)) { newObj = obj.map(item => deepClone(item)) } else { - Object.keys(obj).forEach((key) => { + Object.keys(obj as any).forEach((key) => { // @ts-ignore return newObj[key] = deepClone(obj[key]) })