Skip to content

Commit

Permalink
feat: add image surround display #554
Browse files Browse the repository at this point in the history
  • Loading branch information
Hufe921 authored Sep 11, 2024
1 parent a833f85 commit a9f80a4
Show file tree
Hide file tree
Showing 24 changed files with 294 additions and 36 deletions.
5 changes: 3 additions & 2 deletions docs/en/guide/contextmenu-internal.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions docs/en/guide/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ interface ILang {
textWrapType: {
embed: string
upDown: string
surround: string
floatTop: string
floatBottom: string
}
}
table: {
Expand Down
5 changes: 5 additions & 0 deletions docs/en/guide/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ interface IElement {
INLINE = 'inline',
BLOCK = 'block'
}
imgFloatPosition?: {
x: number;
y: number;
pageNo?: number;
}
// block
block?: {
type: {
Expand Down
1 change: 1 addition & 0 deletions docs/guide/contextmenu-internal.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- 文字环绕
- 嵌入型
- 上下型环绕
- 四周型环绕
- 浮于文字上方
- 衬于文字下方

Expand Down
4 changes: 3 additions & 1 deletion docs/guide/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ interface ILang {
textWrapType: {
embed: string
upDown: string
}
surround: string
floatTop: string
floatBottom: string
}
table: {
insertRowCol: string
Expand Down
5 changes: 5 additions & 0 deletions docs/guide/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ interface IElement {
INLINE = 'inline',
BLOCK = 'block'
}
imgFloatPosition?: {
x: number;
y: number;
pageNo?: number;
}
// 内容块
block?: {
type: {
Expand Down
3 changes: 3 additions & 0 deletions src/editor/core/command/CommandAdapt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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]
}
Expand Down
12 changes: 12 additions & 0 deletions src/editor/core/contextmenu/menus/imageMenus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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',
Expand Down
109 changes: 98 additions & 11 deletions src/editor/core/draw/Draw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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
) {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1610,6 +1630,7 @@ export class Draw {
rowMargin
const rowElement: IRowElement = Object.assign(element, {
metrics,
left: 0,
style: this.getElementFont(element, scale)
})
// 暂时只考虑非换行场景:控件开始时统计宽度,结束时消费宽度及还原
Expand All @@ -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
}
Expand Down Expand Up @@ -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 ||
Expand All @@ -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,
Expand Down Expand Up @@ -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 =
Expand All @@ -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
}
Expand Down Expand Up @@ -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
) {
Expand Down Expand Up @@ -2227,15 +2301,16 @@ 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
if (
(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!
Expand Down Expand Up @@ -2286,7 +2361,7 @@ export class Draw {
// 渲染衬于文字下方元素
this._drawFloat(ctx, {
pageNo,
imgDisplay: ImageDisplay.FLOAT_BOTTOM
imgDisplays: [ImageDisplay.FLOAT_BOTTOM]
})
// 控件高亮
this.control.renderHighlightList(ctx, pageNo)
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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
})
// 页面信息
Expand Down
8 changes: 7 additions & 1 deletion src/editor/core/draw/frame/Header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -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
})
}

Expand Down
1 change: 1 addition & 0 deletions src/editor/core/event/handlers/mousedown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
) {
Expand Down
3 changes: 2 additions & 1 deletion src/editor/core/event/handlers/mousemove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Loading

0 comments on commit a9f80a4

Please sign in to comment.