diff --git a/docs/en/guide/contextmenu-internal.md b/docs/en/guide/contextmenu-internal.md index 8b8facb2c..f81196423 100644 --- a/docs/en/guide/contextmenu-internal.md +++ b/docs/en/guide/contextmenu-internal.md @@ -19,8 +19,9 @@ - Change the picture - Save as picture - Text wrapping - - Embedded - - Upper and lower surrounding + - Embed + - Up down + - Surround - Float above text - Float below text diff --git a/docs/en/guide/i18n.md b/docs/en/guide/i18n.md index 0e3995bde..06775dc3a 100644 --- a/docs/en/guide/i18n.md +++ b/docs/en/guide/i18n.md @@ -41,6 +41,9 @@ interface ILang { textWrapType: { embed: string upDown: string + surround: string + floatTop: string + floatBottom: string } } table: { diff --git a/docs/en/guide/schema.md b/docs/en/guide/schema.md index 68e6c7aec..a9cf54185 100644 --- a/docs/en/guide/schema.md +++ b/docs/en/guide/schema.md @@ -144,6 +144,11 @@ interface IElement { INLINE = 'inline', BLOCK = 'block' } + imgFloatPosition?: { + x: number; + y: number; + pageNo?: number; + } // block block?: { type: { diff --git a/docs/guide/contextmenu-internal.md b/docs/guide/contextmenu-internal.md index 897d07c16..f6a7dd5f9 100644 --- a/docs/guide/contextmenu-internal.md +++ b/docs/guide/contextmenu-internal.md @@ -21,6 +21,7 @@ - 文字环绕 - 嵌入型 - 上下型环绕 + - 四周型环绕 - 浮于文字上方 - 衬于文字下方 diff --git a/docs/guide/i18n.md b/docs/guide/i18n.md index 2365999ca..0478d352c 100644 --- a/docs/guide/i18n.md +++ b/docs/guide/i18n.md @@ -41,7 +41,9 @@ interface ILang { textWrapType: { embed: string upDown: string - } + surround: string + floatTop: string + floatBottom: string } table: { insertRowCol: string diff --git a/docs/guide/schema.md b/docs/guide/schema.md index cd3f7003e..3a18f1617 100644 --- a/docs/guide/schema.md +++ b/docs/guide/schema.md @@ -144,6 +144,11 @@ interface IElement { INLINE = 'inline', BLOCK = 'block' } + imgFloatPosition?: { + x: number; + y: number; + pageNo?: number; + } // 内容块 block?: { type: { diff --git a/src/editor/core/command/CommandAdapt.ts b/src/editor/core/command/CommandAdapt.ts index d9b83f41e..806a63520 100644 --- a/src/editor/core/command/CommandAdapt.ts +++ b/src/editor/core/command/CommandAdapt.ts @@ -2002,14 +2002,17 @@ export class CommandAdapt { element.imgDisplay = display const { startIndex, endIndex } = this.range.getRange() if ( + display === ImageDisplay.SURROUND || display === ImageDisplay.FLOAT_TOP || display === ImageDisplay.FLOAT_BOTTOM ) { const positionList = this.position.getPositionList() const { + pageNo, coordinate: { leftTop } } = positionList[startIndex] element.imgFloatPosition = { + pageNo, x: leftTop[0], y: leftTop[1] } diff --git a/src/editor/core/contextmenu/menus/imageMenus.ts b/src/editor/core/contextmenu/menus/imageMenus.ts index 75df2b2a1..fae52ece0 100644 --- a/src/editor/core/contextmenu/menus/imageMenus.ts +++ b/src/editor/core/contextmenu/menus/imageMenus.ts @@ -13,6 +13,7 @@ const { TEXT_WRAP, TEXT_WRAP_EMBED, TEXT_WRAP_UP_DOWN, + TEXT_WRAP_SURROUND, TEXT_WRAP_FLOAT_TOP, TEXT_WRAP_FLOAT_BOTTOM } @@ -95,6 +96,17 @@ export const imageMenus: IRegisterContextMenu[] = [ ) } }, + { + key: TEXT_WRAP_SURROUND, + i18nPath: 'contextmenu.image.textWrapType.surround', + when: () => true, + callback: (command: Command, context: IContextMenuContext) => { + command.executeChangeImageDisplay( + context.startElement!, + ImageDisplay.SURROUND + ) + } + }, { key: TEXT_WRAP_FLOAT_TOP, i18nPath: 'contextmenu.image.textWrapType.floatTop', diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index 978552c15..57cf65ca3 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -65,8 +65,10 @@ import { } from '../../dataset/enum/Editor' import { Control } from './control/Control' import { + deleteSurroundElementList, getIsBlockElement, getSlimCloneElementList, + pickSurroundElementList, zipElementList } from '../../utils/element' import { CheckboxParticle } from './particle/CheckboxParticle' @@ -1223,7 +1225,17 @@ export class Draw { } public computeRowList(payload: IComputeRowListPayload) { - const { innerWidth, elementList, isPagingMode = false } = payload + const { + innerWidth, + elementList, + isPagingMode = false, + isFromTable = false, + startX = 0, + startY = 0, + pageHeight = 0, + mainOuterHeight = 0, + surroundElementList = [] + } = payload const { defaultSize, defaultRowMargin, @@ -1248,6 +1260,10 @@ export class Draw { rowFlex: elementList?.[0]?.rowFlex || elementList?.[1]?.rowFlex }) } + // 起始位置及页码计算 + let x = startX + let y = startY + let pageNo = 0 // 列表位置 let listId: string | undefined let listIndex = 0 @@ -1270,12 +1286,15 @@ export class Draw { (element.listId && listStyleMap.get(element.listId)) || 0 const availableWidth = innerWidth - offsetX + // 增加起始位置坐标偏移量 + x += curRow.elementList.length === 1 ? offsetX : 0 if ( element.type === ElementType.IMAGE || element.type === ElementType.LATEX ) { // 浮动图片无需计算数据 if ( + element.imgDisplay === ImageDisplay.SURROUND || element.imgDisplay === ImageDisplay.FLOAT_TOP || element.imgDisplay === ImageDisplay.FLOAT_BOTTOM ) { @@ -1339,6 +1358,7 @@ export class Draw { const rowList = this.computeRowList({ innerWidth: (td.width! - tdPaddingWidth) * scale, elementList: td.value, + isFromTable: true, isPagingMode }) const rowHeight = rowList.reduce((pre, cur) => pre + cur.height, 0) @@ -1610,6 +1630,7 @@ export class Draw { rowMargin const rowElement: IRowElement = Object.assign(element, { metrics, + left: 0, style: this.getElementFont(element, scale) }) // 暂时只考虑非换行场景:控件开始时统计宽度,结束时消费宽度及还原 @@ -1627,8 +1648,6 @@ export class Draw { const left = Math.min(rowRemainingWidth, extraWidth) * scale rowElement.left = left curRow.width += left - } else { - rowElement.left = 0 } controlRealWidth = 0 } @@ -1675,6 +1694,23 @@ export class Draw { } } listId = element.listId + // 计算四周环绕导致的元素偏移量 + const surroundPosition = this.position.setSurroundPosition({ + pageNo, + rowElement, + row: curRow, + rowElementRect: { + x, + y, + height, + width: metrics.width + }, + availableWidth, + surroundElementList + }) + x = surroundPosition.x + curRowWidth += surroundPosition.rowIncreaseWidth + x += metrics.width // 是否强制换行 const isForceBreak = element.type === ElementType.SEPARATOR || @@ -1688,8 +1724,9 @@ export class Draw { (i !== 0 && element.value === ZERO) // 是否宽度不足导致换行 const isWidthNotEnough = curRowWidth > availableWidth + const isWrap = isForceBreak || isWidthNotEnough // 新行数据处理 - if (isForceBreak || isWidthNotEnough) { + if (isWrap) { const row: IRow = { width: metrics.width, height, @@ -1742,13 +1779,14 @@ export class Draw { curRow.elementList.push(rowElement) } // 行结束时逻辑 - if (isForceBreak || isWidthNotEnough || i === elementList.length - 1) { + if (isWrap || i === elementList.length - 1) { // 换行原因:宽度不足 curRow.isWidthNotEnough = isWidthNotEnough && !isForceBreak // 两端对齐、分散对齐 if ( - preElement?.rowFlex === RowFlex.JUSTIFY || - (preElement?.rowFlex === RowFlex.ALIGNMENT && isWidthNotEnough) + !curRow.isSurround && + (preElement?.rowFlex === RowFlex.JUSTIFY || + (preElement?.rowFlex === RowFlex.ALIGNMENT && isWidthNotEnough)) ) { // 忽略换行符及尾部元素间隔设置 const rowElementList = @@ -1764,6 +1802,41 @@ export class Draw { curRow.width = availableWidth } } + // 重新计算坐标、页码、下一行首行元素环绕交叉 + if (isWrap) { + x = startX + y += curRow.height + if ( + isPagingMode && + !isFromTable && + pageHeight && + (y - startY + mainOuterHeight + height > pageHeight || + element.type === ElementType.PAGE_BREAK) + ) { + y = startY + // 删除多余四周环绕型元素 + deleteSurroundElementList(surroundElementList, pageNo) + pageNo += 1 + } + // 计算下一行第一个元素是否存在环绕交叉 + rowElement.left = 0 + const nextRow = rowList[rowList.length - 1] + const surroundPosition = this.position.setSurroundPosition({ + pageNo, + rowElement, + row: nextRow, + rowElementRect: { + x, + y, + height, + width: metrics.width + }, + availableWidth, + surroundElementList + }) + x = surroundPosition.x + x += metrics.width + } } return rowList } @@ -1919,6 +1992,7 @@ export class Draw { this.textParticle.complete() // 浮动图片单独绘制 if ( + element.imgDisplay !== ImageDisplay.SURROUND && element.imgDisplay !== ImageDisplay.FLOAT_TOP && element.imgDisplay !== ImageDisplay.FLOAT_BOTTOM ) { @@ -2227,7 +2301,7 @@ export class Draw { ) { const { scale } = this.options const floatPositionList = this.position.getFloatPositionList() - const { imgDisplay, pageNo } = payload + const { imgDisplays, pageNo } = payload for (let e = 0; e < floatPositionList.length; e++) { const floatPosition = floatPositionList[e] const element = floatPosition.element @@ -2235,7 +2309,8 @@ export class Draw { (pageNo === floatPosition.pageNo || floatPosition.zone === EditorZone.HEADER || floatPosition.zone == EditorZone.FOOTER) && - element.imgDisplay === imgDisplay && + element.imgDisplay && + imgDisplays.includes(element.imgDisplay) && element.type === ElementType.IMAGE ) { const imgFloatPosition = element.imgFloatPosition! @@ -2286,7 +2361,7 @@ export class Draw { // 渲染衬于文字下方元素 this._drawFloat(ctx, { pageNo, - imgDisplay: ImageDisplay.FLOAT_BOTTOM + imgDisplays: [ImageDisplay.FLOAT_BOTTOM] }) // 控件高亮 this.control.renderHighlightList(ctx, pageNo) @@ -2318,7 +2393,7 @@ export class Draw { // 渲染浮于文字上方元素 this._drawFloat(ctx, { pageNo, - imgDisplay: ImageDisplay.FLOAT_TOP + imgDisplays: [ImageDisplay.FLOAT_TOP, ImageDisplay.SURROUND] }) // 搜索匹配绘制 if (this.search.getSearchKeyword()) { @@ -2410,9 +2485,21 @@ export class Draw { } } // 行信息 + const margins = this.getMargins() + const pageHeight = this.getHeight() + const extraHeight = this.header.getExtraHeight() + const mainOuterHeight = this.getMainOuterHeight() + const startX = margins[3] + const startY = margins[0] + extraHeight + const surroundElementList = pickSurroundElementList(this.elementList) this.rowList = this.computeRowList({ + startX, + startY, + pageHeight, + mainOuterHeight, isPagingMode, innerWidth, + surroundElementList, elementList: this.elementList }) // 页面信息 diff --git a/src/editor/core/draw/frame/Header.ts b/src/editor/core/draw/frame/Header.ts index 7d399001a..98a025e85 100644 --- a/src/editor/core/draw/frame/Header.ts +++ b/src/editor/core/draw/frame/Header.ts @@ -4,6 +4,7 @@ import { DeepRequired } from '../../../interface/Common' import { IEditorOption } from '../../../interface/Editor' import { IElement, IElementPosition } from '../../../interface/Element' import { IRow } from '../../../interface/Row' +import { pickSurroundElementList } from '../../../utils/element' import { Position } from '../../position/Position' import { Draw } from '../Draw' @@ -55,9 +56,14 @@ export class Header { private _computeRowList() { const innerWidth = this.draw.getInnerWidth() + const margins = this.draw.getMargins() + const surroundElementList = pickSurroundElementList(this.elementList) this.rowList = this.draw.computeRowList({ + startX: margins[3], + startY: this.getHeaderTop(), innerWidth, - elementList: this.elementList + elementList: this.elementList, + surroundElementList }) } diff --git a/src/editor/core/event/handlers/mousedown.ts b/src/editor/core/event/handlers/mousedown.ts index 8f67026e0..f2bb4db67 100644 --- a/src/editor/core/event/handlers/mousedown.ts +++ b/src/editor/core/event/handlers/mousedown.ts @@ -205,6 +205,7 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) { setRangeCache(host) // 浮动元素创建镜像图片 if ( + curElement.imgDisplay === ImageDisplay.SURROUND || curElement.imgDisplay === ImageDisplay.FLOAT_TOP || curElement.imgDisplay === ImageDisplay.FLOAT_BOTTOM ) { diff --git a/src/editor/core/event/handlers/mousemove.ts b/src/editor/core/event/handlers/mousemove.ts index 407974c97..348564e6c 100644 --- a/src/editor/core/event/handlers/mousemove.ts +++ b/src/editor/core/event/handlers/mousemove.ts @@ -31,7 +31,8 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) { const dragElement = host.cacheElementList![cacheStartIndex] if ( dragElement?.type === ElementType.IMAGE && - (dragElement.imgDisplay === ImageDisplay.FLOAT_TOP || + (dragElement.imgDisplay === ImageDisplay.SURROUND || + dragElement.imgDisplay === ImageDisplay.FLOAT_TOP || dragElement.imgDisplay === ImageDisplay.FLOAT_BOTTOM) ) { draw.getPreviewer().clearResizer() diff --git a/src/editor/core/event/handlers/mouseup.ts b/src/editor/core/event/handlers/mouseup.ts index 81e572a74..2d9f110f1 100644 --- a/src/editor/core/event/handlers/mouseup.ts +++ b/src/editor/core/event/handlers/mouseup.ts @@ -30,6 +30,7 @@ function moveImgPosition( ) { const draw = host.getDraw() if ( + element.imgDisplay === ImageDisplay.SURROUND || element.imgDisplay === ImageDisplay.FLOAT_TOP || element.imgDisplay === ImageDisplay.FLOAT_BOTTOM ) { @@ -38,7 +39,8 @@ function moveImgPosition( const imgFloatPosition = element.imgFloatPosition! element.imgFloatPosition = { x: imgFloatPosition.x + moveX, - y: imgFloatPosition.y + moveY + y: imgFloatPosition.y + moveY, + pageNo: draw.getPageNo() } } draw.getImageParticle().destroyFloatImage() @@ -77,6 +79,7 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { draw.clearSideEffect() // 浮动元素拖拽需要提交历史 let isSubmitHistory = false + let isCompute = false if (isCacheRangeCollapsed) { // 图片移动 const dragElement = cacheElementList[cacheEndIndex] @@ -86,6 +89,7 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { ) { moveImgPosition(dragElement, evt, host) if ( + dragElement.imgDisplay === ImageDisplay.SURROUND || dragElement.imgDisplay === ImageDisplay.FLOAT_TOP || dragElement.imgDisplay === ImageDisplay.FLOAT_BOTTOM ) { @@ -95,15 +99,17 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { const cachePosition = cachePositionList[cacheEndIndex] draw.getPreviewer().drawResizer(dragElement, cachePosition) } + // 四周环绕型元素需计算 + isCompute = dragElement.imgDisplay === ImageDisplay.SURROUND } } rangeManager.replaceRange({ ...cacheRange }) draw.render({ - isSetCursor: false, - isCompute: false, - isSubmitHistory + isCompute, + isSubmitHistory, + isSetCursor: false }) return } @@ -294,6 +300,7 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { // 拖拽后渲染图片工具 if (imgElement) { if ( + imgElement.imgDisplay === ImageDisplay.SURROUND || imgElement.imgDisplay === ImageDisplay.FLOAT_TOP || imgElement.imgDisplay === ImageDisplay.FLOAT_BOTTOM ) { diff --git a/src/editor/core/i18n/lang/en.json b/src/editor/core/i18n/lang/en.json index 81bc495be..f0107a7ab 100644 --- a/src/editor/core/i18n/lang/en.json +++ b/src/editor/core/i18n/lang/en.json @@ -22,6 +22,7 @@ "textWrapType": { "embed": "Embed", "upDown": "Up down", + "surround": "Surround", "floatTop": "Float above text", "floatBottom": "Float below text" } diff --git a/src/editor/core/i18n/lang/zh-CN.json b/src/editor/core/i18n/lang/zh-CN.json index 972117789..6d72b65e2 100644 --- a/src/editor/core/i18n/lang/zh-CN.json +++ b/src/editor/core/i18n/lang/zh-CN.json @@ -22,6 +22,7 @@ "textWrapType": { "embed": "嵌入型", "upDown": "上下型环绕", + "surround": "四周型环绕", "floatTop": "浮于文字上方", "floatBottom": "衬于文字下方" } diff --git a/src/editor/core/position/Position.ts b/src/editor/core/position/Position.ts index a0d1dcfd1..ad0ae9af0 100644 --- a/src/editor/core/position/Position.ts +++ b/src/editor/core/position/Position.ts @@ -6,7 +6,8 @@ import { IComputePageRowPositionResult, IComputeRowPositionPayload, IFloatPosition, - IGetFloatPositionByXYPayload + IGetFloatPositionByXYPayload, + ISetSurroundPositionPayload } from '../../interface/Position' import { IEditorOption } from '../../interface/Editor' import { IElement, IElementPosition } from '../../interface/Element' @@ -17,11 +18,12 @@ import { } from '../../interface/Position' import { Draw } from '../draw/Draw' import { EditorMode, EditorZone } from '../../dataset/enum/Editor' -import { deepClone } from '../../utils' +import { deepClone, isRectIntersect } from '../../utils' import { ImageDisplay } from '../../dataset/enum/Common' import { DeepRequired } from '../../interface/Common' import { EventBus } from '../event/eventbus/EventBus' import { EventBusMap } from '../../interface/EventBus' +import { getIsBlockElement } from '../../utils/element' export class Position { private cursorPosition: IElementPosition | null @@ -128,12 +130,15 @@ export class Position { let index = startIndex for (let i = 0; i < rowList.length; i++) { const curRow = rowList[i] - // 计算行偏移量(行居中、居右) - const curRowWidth = curRow.width + (curRow.offsetX || 0) - if (curRow.rowFlex === RowFlex.CENTER) { - x += (innerWidth - curRowWidth) / 2 - } else if (curRow.rowFlex === RowFlex.RIGHT) { - x += innerWidth - curRowWidth + // 行存在环绕的可能性均不设置行布局 + if (!curRow.isSurround) { + // 计算行偏移量(行居中、居右) + const curRowWidth = curRow.width + (curRow.offsetX || 0) + if (curRow.rowFlex === RowFlex.CENTER) { + x += (innerWidth - curRowWidth) / 2 + } else if (curRow.rowFlex === RowFlex.RIGHT) { + x += innerWidth - curRowWidth + } } // 当前行X轴偏移量 x += curRow.offsetX || 0 @@ -174,6 +179,7 @@ export class Position { } // 缓存浮动元素信息 if ( + element.imgDisplay === ImageDisplay.SURROUND || element.imgDisplay === ImageDisplay.FLOAT_TOP || element.imgDisplay === ImageDisplay.FLOAT_BOTTOM ) { @@ -187,7 +193,8 @@ export class Position { if (!element.imgFloatPosition) { element.imgFloatPosition = { x, - y + y, + pageNo } } this.floatPositionList.push({ @@ -357,7 +364,7 @@ export class Position { if (!isTable) { const floatTopPosition = this.getFloatPositionByXY({ ...payload, - imgDisplay: ImageDisplay.FLOAT_TOP + imgDisplays: [ImageDisplay.FLOAT_TOP, ImageDisplay.SURROUND] }) if (floatTopPosition) return floatTopPosition } @@ -480,7 +487,7 @@ export class Position { if (!isTable) { const floatBottomPosition = this.getFloatPositionByXY({ ...payload, - imgDisplay: ImageDisplay.FLOAT_BOTTOM + imgDisplays: [ImageDisplay.FLOAT_BOTTOM] }) if (floatBottomPosition) return floatBottomPosition } @@ -668,7 +675,8 @@ export class Position { if ( currentPageNo === pageNo && element.type === ElementType.IMAGE && - element.imgDisplay === payload.imgDisplay && + element.imgDisplay && + payload.imgDisplays.includes(element.imgDisplay) && (!floatElementZone || floatElementZone === currentZone) ) { const imgFloatPosition = element.imgFloatPosition! @@ -758,4 +766,52 @@ export class Position { }) return positionResult } + + public setSurroundPosition(payload: ISetSurroundPositionPayload) { + const { + pageNo, + row, + rowElement, + rowElementRect, + surroundElementList, + availableWidth + } = payload + let x = rowElementRect.x + let rowIncreaseWidth = 0 + if ( + surroundElementList.length && + !getIsBlockElement(rowElement) && + !rowElement.control?.minWidth + ) { + for (let s = 0; s < surroundElementList.length; s++) { + const surroundElement = surroundElementList[s] + const floatPosition = surroundElement.imgFloatPosition! + if (floatPosition.pageNo !== pageNo) continue + const surroundRect = { + ...floatPosition, + width: surroundElement.width!, + height: surroundElement.height! + } + if (isRectIntersect(rowElementRect, surroundRect)) { + row.isSurround = true + // 需向左移动距离:浮动元素宽度 + 浮动元素左上坐标 - 元素左上坐标 + const translateX = + surroundRect.width + surroundRect.x - rowElementRect.x + rowElement.left = translateX + // 增加行宽 + row.width += translateX + rowIncreaseWidth += translateX + // 下个元素起始位置:浮动元素右坐标 - 元素宽度 + x = surroundRect.x + surroundRect.width + // 检测宽度是否足够,不够则移动到下一行,并还原状态 + if (row.width + rowElement.metrics.width > availableWidth) { + rowElement.left = 0 + row.width -= rowIncreaseWidth + break + } + } + } + } + return { x, rowIncreaseWidth } + } } diff --git a/src/editor/dataset/constant/ContextMenu.ts b/src/editor/dataset/constant/ContextMenu.ts index a50ae92f4..303a68156 100644 --- a/src/editor/dataset/constant/ContextMenu.ts +++ b/src/editor/dataset/constant/ContextMenu.ts @@ -24,6 +24,7 @@ export const INTERNAL_CONTEXT_MENU_KEY = { TEXT_WRAP: 'imageTextWrap', TEXT_WRAP_EMBED: 'imageTextWrapEmbed', TEXT_WRAP_UP_DOWN: 'imageTextWrapUpDown', + TEXT_WRAP_SURROUND: 'imageTextWrapSurround', TEXT_WRAP_FLOAT_TOP: 'imageTextWrapFloatTop', TEXT_WRAP_FLOAT_BOTTOM: 'imageTextWrapFloatBottom' }, diff --git a/src/editor/dataset/enum/Common.ts b/src/editor/dataset/enum/Common.ts index 4922f55d3..7973bd8b7 100644 --- a/src/editor/dataset/enum/Common.ts +++ b/src/editor/dataset/enum/Common.ts @@ -12,6 +12,7 @@ export enum NumberType { export enum ImageDisplay { INLINE = 'inline', BLOCK = 'block', + SURROUND = 'surround', FLOAT_TOP = 'float-top', FLOAT_BOTTOM = 'float-bottom' } diff --git a/src/editor/interface/Draw.ts b/src/editor/interface/Draw.ts index 06483fb32..594ce9425 100644 --- a/src/editor/interface/Draw.ts +++ b/src/editor/interface/Draw.ts @@ -38,7 +38,7 @@ export interface IDrawRowPayload { export interface IDrawFloatPayload { pageNo: number - imgDisplay: ImageDisplay + imgDisplays: ImageDisplay[] } export interface IDrawPagePayload { @@ -69,5 +69,11 @@ export interface IGetImageOption { export interface IComputeRowListPayload { innerWidth: number elementList: IElement[] + startX?: number + startY?: number + isFromTable?: boolean isPagingMode?: boolean + pageHeight?: number + mainOuterHeight?: number + surroundElementList?: IElement[] } diff --git a/src/editor/interface/Element.ts b/src/editor/interface/Element.ts index 52ec6f27d..0b1360b9e 100644 --- a/src/editor/interface/Element.ts +++ b/src/editor/interface/Element.ts @@ -117,6 +117,7 @@ export interface IImageElement { imgFloatPosition?: { x: number y: number + pageNo?: number } } diff --git a/src/editor/interface/Position.ts b/src/editor/interface/Position.ts index 337485450..29476ff54 100644 --- a/src/editor/interface/Position.ts +++ b/src/editor/interface/Position.ts @@ -1,7 +1,7 @@ import { IElement, ImageDisplay, IRange } from '..' import { EditorZone } from '../dataset/enum/Editor' -import { IElementPosition } from './Element' -import { IRow } from './Row' +import { IElementFillRect, IElementPosition } from './Element' +import { IRow, IRowElement } from './Row' import { ITd } from './table/Td' export interface ICurrentPosition { @@ -36,7 +36,7 @@ export interface IGetPositionByXYPayload { } export type IGetFloatPositionByXYPayload = IGetPositionByXYPayload & { - imgDisplay: ImageDisplay + imgDisplays: ImageDisplay[] } export interface IPositionContext { @@ -99,3 +99,12 @@ export interface ILocationPosition { range: IRange positionContext: IPositionContext } + +export interface ISetSurroundPositionPayload { + row: IRow + rowElement: IRowElement + rowElementRect: IElementFillRect + pageNo: number + availableWidth: number + surroundElementList: IElement[] +} diff --git a/src/editor/interface/Row.ts b/src/editor/interface/Row.ts index c77cf3652..91294779e 100644 --- a/src/editor/interface/Row.ts +++ b/src/editor/interface/Row.ts @@ -20,4 +20,5 @@ export interface IRow { elementList: IRowElement[] isWidthNotEnough?: boolean rowIndex: number + isSurround?: boolean } diff --git a/src/editor/utils/element.ts b/src/editor/utils/element.ts index 6bd4bd31f..6af146cd0 100644 --- a/src/editor/utils/element.ts +++ b/src/editor/utils/element.ts @@ -1536,3 +1536,26 @@ export function replaceHTMLElementTag( newDom.innerHTML = oldDom.innerHTML return newDom } + +export function pickSurroundElementList(elementList: IElement[]) { + const surroundElementList = [] + for (let e = 0; e < elementList.length; e++) { + const element = elementList[e] + if (element.imgDisplay === ImageDisplay.SURROUND) { + surroundElementList.push(element) + } + } + return surroundElementList +} + +export function deleteSurroundElementList( + elementList: IElement[], + pageNo: number +) { + for (let s = elementList.length - 1; s >= 0; s--) { + const surroundElement = elementList[s] + if (surroundElement.imgFloatPosition?.pageNo === pageNo) { + elementList.splice(s, 1) + } + } +} diff --git a/src/editor/utils/index.ts b/src/editor/utils/index.ts index 60c8a2777..211c3fa72 100644 --- a/src/editor/utils/index.ts +++ b/src/editor/utils/index.ts @@ -1,4 +1,5 @@ import { UNICODE_SYMBOL_REG } from '../dataset/constant/Regular' +import { IElementFillRect } from '../interface/Element' export function debounce( func: (...arg: T) => unknown, @@ -326,3 +327,26 @@ export function isObjectEqual(obj1: unknown, obj2: unknown): boolean { } return !obj1Keys.some(key => obj2[key] !== obj1[key]) } + +export function isRectIntersect( + rect1: IElementFillRect, + rect2: IElementFillRect +): boolean { + const rect1Left = rect1.x + const rect1Right = rect1.x + rect1.width + const rect1Top = rect1.y + const rect1Bottom = rect1.y + rect1.height + const rect2Left = rect2.x + const rect2Right = rect2.x + rect2.width + const rect2Top = rect2.y + const rect2Bottom = rect2.y + rect2.height + if ( + rect1Left > rect2Right || + rect1Right < rect2Left || + rect1Top > rect2Bottom || + rect1Bottom < rect2Top + ) { + return false + } + return true +}