diff --git a/src/editor/core/command/CommandAdapt.ts b/src/editor/core/command/CommandAdapt.ts index 9f98fb1..265f43f 100644 --- a/src/editor/core/command/CommandAdapt.ts +++ b/src/editor/core/command/CommandAdapt.ts @@ -29,6 +29,7 @@ import { import { IAppendElementListOption, IDrawImagePayload, + IDrawOption, IForceUpdateOption, IGetImageOption, IGetValueOption, @@ -271,16 +272,32 @@ export class CommandAdapt { this.draw.isReadonly() || this.control.isDisabledControl() if (isDisabled) return const selection = this.range.getSelectionElementList() - if (!selection) return - selection.forEach(el => { - el.font = '' - el.color = '' - el.bold = false - el.italic = false - el.underline = false - el.strikeout = false + // 选区设置或设置换行处样式 + let renderOption: IDrawOption = {} + let changeElementList: IElement[] = [] + if (selection?.length) { + changeElementList = selection + renderOption = { isSetCursor: false } + } else { + const { endIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + const enterElement = elementList[endIndex] + if (enterElement?.value === ZERO) { + changeElementList.push(enterElement) + renderOption = { curIndex: endIndex } + } + } + if (!changeElementList.length) return + changeElementList.forEach(el => { + delete el.size + delete el.font + delete el.color + delete el.bold + delete el.italic + delete el.underline + delete el.strikeout }) - this.draw.render({ isSetCursor: false }) + this.draw.render(renderOption) } public font(payload: string) { @@ -288,11 +305,20 @@ export class CommandAdapt { this.draw.isReadonly() || this.control.isDisabledControl() if (isDisabled) return const selection = this.range.getSelectionElementList() - if (!selection) return - selection.forEach(el => { - el.font = payload - }) - this.draw.render({ isSetCursor: false }) + if (selection?.length) { + selection.forEach(el => { + el.font = payload + }) + this.draw.render({ isSetCursor: false }) + } else { + const { endIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + const enterElement = elementList[endIndex] + if (enterElement?.value === ZERO) { + enterElement.font = payload + this.draw.render({ curIndex: endIndex, isCompute: false }) + } + } } public size(payload: number) { @@ -301,10 +327,25 @@ export class CommandAdapt { const isDisabled = this.draw.isReadonly() || this.control.isDisabledControl() if (isDisabled) return + // 选区设置或设置换行处样式 + let renderOption: IDrawOption = {} + let changeElementList: IElement[] = [] const selection = this.range.getTextLikeSelectionElementList() - if (!selection || !selection.length) return + if (selection?.length) { + changeElementList = selection + renderOption = { isSetCursor: false } + } else { + const { endIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + const enterElement = elementList[endIndex] + if (enterElement?.value === ZERO) { + changeElementList.push(enterElement) + renderOption = { curIndex: endIndex } + } + } + if (!changeElementList.length) return let isExistUpdate = false - selection.forEach(el => { + changeElementList.forEach(el => { if ( (!el.size && payload === defaultSize) || (el.size && el.size === payload) @@ -315,7 +356,7 @@ export class CommandAdapt { isExistUpdate = true }) if (isExistUpdate) { - this.draw.render({ isSetCursor: false }) + this.draw.render(renderOption) } } @@ -324,10 +365,25 @@ export class CommandAdapt { this.draw.isReadonly() || this.control.isDisabledControl() if (isDisabled) return const selection = this.range.getTextLikeSelectionElementList() - if (!selection || !selection.length) return + // 选区设置或设置换行处样式 + let renderOption: IDrawOption = {} + let changeElementList: IElement[] = [] + if (selection?.length) { + changeElementList = selection + renderOption = { isSetCursor: false } + } else { + const { endIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + const enterElement = elementList[endIndex] + if (enterElement?.value === ZERO) { + changeElementList.push(enterElement) + renderOption = { curIndex: endIndex } + } + } + if (!changeElementList.length) return const { defaultSize, maxSize } = this.options let isExistUpdate = false - selection.forEach(el => { + changeElementList.forEach(el => { if (!el.size) { el.size = defaultSize } @@ -340,7 +396,7 @@ export class CommandAdapt { isExistUpdate = true }) if (isExistUpdate) { - this.draw.render({ isSetCursor: false }) + this.draw.render(renderOption) } } @@ -349,10 +405,25 @@ export class CommandAdapt { this.draw.isReadonly() || this.control.isDisabledControl() if (isDisabled) return const selection = this.range.getTextLikeSelectionElementList() - if (!selection || !selection.length) return + // 选区设置或设置换行处样式 + let renderOption: IDrawOption = {} + let changeElementList: IElement[] = [] + if (selection?.length) { + changeElementList = selection + renderOption = { isSetCursor: false } + } else { + const { endIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + const enterElement = elementList[endIndex] + if (enterElement?.value === ZERO) { + changeElementList.push(enterElement) + renderOption = { curIndex: endIndex } + } + } + if (!changeElementList.length) return const { defaultSize, minSize } = this.options let isExistUpdate = false - selection.forEach(el => { + changeElementList.forEach(el => { if (!el.size) { el.size = defaultSize } @@ -365,7 +436,7 @@ export class CommandAdapt { isExistUpdate = true }) if (isExistUpdate) { - this.draw.render({ isSetCursor: false }) + this.draw.render(renderOption) } } @@ -374,12 +445,21 @@ export class CommandAdapt { this.draw.isReadonly() || this.control.isDisabledControl() if (isDisabled) return const selection = this.range.getSelectionElementList() - if (!selection) return - const noBoldIndex = selection.findIndex(s => !s.bold) - selection.forEach(el => { - el.bold = !!~noBoldIndex - }) - this.draw.render({ isSetCursor: false }) + if (selection?.length) { + const noBoldIndex = selection.findIndex(s => !s.bold) + selection.forEach(el => { + el.bold = !!~noBoldIndex + }) + this.draw.render({ isSetCursor: false }) + } else { + const { endIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + const enterElement = elementList[endIndex] + if (enterElement?.value === ZERO) { + enterElement.bold = !enterElement.bold + this.draw.render({ curIndex: endIndex, isCompute: false }) + } + } } public italic() { @@ -387,12 +467,21 @@ export class CommandAdapt { this.draw.isReadonly() || this.control.isDisabledControl() if (isDisabled) return const selection = this.range.getSelectionElementList() - if (!selection) return - const noItalicIndex = selection.findIndex(s => !s.italic) - selection.forEach(el => { - el.italic = !!~noItalicIndex - }) - this.draw.render({ isSetCursor: false }) + if (selection?.length) { + const noItalicIndex = selection.findIndex(s => !s.italic) + selection.forEach(el => { + el.italic = !!~noItalicIndex + }) + this.draw.render({ isSetCursor: false }) + } else { + const { endIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + const enterElement = elementList[endIndex] + if (enterElement?.value === ZERO) { + enterElement.italic = !enterElement.italic + this.draw.render({ curIndex: endIndex, isCompute: false }) + } + } } public underline() { @@ -400,15 +489,24 @@ export class CommandAdapt { this.draw.isReadonly() || this.control.isDisabledControl() if (isDisabled) return const selection = this.range.getSelectionElementList() - if (!selection) return - const noUnderlineIndex = selection.findIndex(s => !s.underline) - selection.forEach(el => { - el.underline = !!~noUnderlineIndex - }) - this.draw.render({ - isSetCursor: false, - isCompute: false - }) + if (selection?.length) { + const noUnderlineIndex = selection.findIndex(s => !s.underline) + selection.forEach(el => { + el.underline = !!~noUnderlineIndex + }) + this.draw.render({ + isSetCursor: false, + isCompute: false + }) + } else { + const { endIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + const enterElement = elementList[endIndex] + if (enterElement?.value === ZERO) { + enterElement.underline = !enterElement.underline + this.draw.render({ curIndex: endIndex, isCompute: false }) + } + } } public strikeout() { @@ -416,15 +514,24 @@ export class CommandAdapt { this.draw.isReadonly() || this.control.isDisabledControl() if (isDisabled) return const selection = this.range.getSelectionElementList() - if (!selection) return - const noStrikeoutIndex = selection.findIndex(s => !s.strikeout) - selection.forEach(el => { - el.strikeout = !!~noStrikeoutIndex - }) - this.draw.render({ - isSetCursor: false, - isCompute: false - }) + if (selection?.length) { + const noStrikeoutIndex = selection.findIndex(s => !s.strikeout) + selection.forEach(el => { + el.strikeout = !!~noStrikeoutIndex + }) + this.draw.render({ + isSetCursor: false, + isCompute: false + }) + } else { + const { endIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + const enterElement = elementList[endIndex] + if (enterElement?.value === ZERO) { + enterElement.strikeout = !enterElement.strikeout + this.draw.render({ curIndex: endIndex, isCompute: false }) + } + } } public superscript() { @@ -492,14 +599,23 @@ export class CommandAdapt { this.draw.isReadonly() || this.control.isDisabledControl() if (isDisabled) return const selection = this.range.getSelectionElementList() - if (!selection) return - selection.forEach(el => { - el.color = payload - }) - this.draw.render({ - isSetCursor: false, - isCompute: false - }) + if (selection?.length) { + selection.forEach(el => { + el.color = payload + }) + this.draw.render({ + isSetCursor: false, + isCompute: false + }) + } else { + const { endIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + const enterElement = elementList[endIndex] + if (enterElement?.value === ZERO) { + enterElement.color = payload + this.draw.render({ curIndex: endIndex, isCompute: false }) + } + } } public highlight(payload: string) { @@ -507,14 +623,23 @@ export class CommandAdapt { this.draw.isReadonly() || this.control.isDisabledControl() if (isDisabled) return const selection = this.range.getSelectionElementList() - if (!selection) return - selection.forEach(el => { - el.highlight = payload - }) - this.draw.render({ - isSetCursor: false, - isCompute: false - }) + if (selection?.length) { + selection.forEach(el => { + el.highlight = payload + }) + this.draw.render({ + isSetCursor: false, + isCompute: false + }) + } else { + const { endIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + const enterElement = elementList[endIndex] + if (enterElement?.value === ZERO) { + enterElement.highlight = payload + this.draw.render({ curIndex: endIndex, isCompute: false }) + } + } } public title(payload: TitleLevel | null) { diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index 384c4c3..f49f979 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -1327,7 +1327,7 @@ export class Draw { } metrics.boundingBoxAscent = (element.value === ZERO - ? defaultSize + ? element.size || defaultSize : fontMetrics.actualBoundingBoxAscent) * scale metrics.boundingBoxDescent = fontMetrics.actualBoundingBoxDescent * scale diff --git a/src/editor/core/event/handlers/input.ts b/src/editor/core/event/handlers/input.ts index 69abc95..27ce6f1 100644 --- a/src/editor/core/event/handlers/input.ts +++ b/src/editor/core/event/handlers/input.ts @@ -41,8 +41,8 @@ export function input(data: string, host: CanvasEvent) { } const nextElement = elementList[endIndex + 1] if ( + !copyElement.type || copyElement.type === TEXT || - (!copyElement.type && copyElement.value !== ZERO) || (copyElement.type === HYPERLINK && nextElement?.type === HYPERLINK) || (copyElement.type === DATE && nextElement?.type === DATE) || (copyElement.type === SUBSCRIPT && nextElement?.type === SUBSCRIPT) || diff --git a/src/editor/core/event/handlers/keydown/enter.ts b/src/editor/core/event/handlers/keydown/enter.ts index 1c1c9a2..33a2144 100644 --- a/src/editor/core/event/handlers/keydown/enter.ts +++ b/src/editor/core/event/handlers/keydown/enter.ts @@ -1,6 +1,10 @@ import { ZERO } from '../../../../dataset/constant/Common' +import { EDITOR_ELEMENT_STYLE_ATTR } from '../../../../dataset/constant/Element' import { IElement } from '../../../../interface/Element' -import { formatElementContext } from '../../../../utils/element' +import { + formatElementContext, + getAnchorElement +} from '../../../../utils/element' import { CanvasEvent } from '../../CanvasEvent' export function enter(evt: KeyboardEvent, host: CanvasEvent) { @@ -40,6 +44,16 @@ export function enter(evt: KeyboardEvent, host: CanvasEvent) { ) { formatElementContext(elementList, [enterText], startIndex) } + // 复制样式属性 + const copyElement = getAnchorElement(elementList, endIndex) + if (copyElement) { + EDITOR_ELEMENT_STYLE_ATTR.forEach(attr => { + const value = copyElement[attr] as never + if (value !== undefined) { + enterText[attr] = value + } + }) + } // 控件或文档插入换行元素 const activeControl = control.getActiveControl() let curIndex: number