feat: image element floating #363
This commit is contained in:
@@ -19,8 +19,10 @@
|
|||||||
- Change the picture
|
- Change the picture
|
||||||
- Save as picture
|
- Save as picture
|
||||||
- Text wrapping
|
- Text wrapping
|
||||||
- Embedded type
|
- Embedded
|
||||||
- Upper and lower surrounding
|
- Upper and lower surrounding
|
||||||
|
- Float above text
|
||||||
|
- Float below text
|
||||||
|
|
||||||
## Table
|
## Table
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
- 文字环绕
|
- 文字环绕
|
||||||
- 嵌入型
|
- 嵌入型
|
||||||
- 上下型环绕
|
- 上下型环绕
|
||||||
|
- 浮于文字上方
|
||||||
|
- 衬于文字下方
|
||||||
|
|
||||||
## 表格
|
## 表格
|
||||||
|
|
||||||
|
|||||||
@@ -69,3 +69,9 @@
|
|||||||
opacity: 1
|
opacity: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ce-float-image {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
@@ -54,6 +54,7 @@
|
|||||||
height: 20px;
|
height: 20px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
z-index: 9;
|
||||||
top: -30px;
|
top: -30px;
|
||||||
left: 0;
|
left: 0;
|
||||||
opacity: .9;
|
opacity: .9;
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { NBSP, WRAP, ZERO } from '../../dataset/constant/Common'
|
|||||||
import { EDITOR_ELEMENT_STYLE_ATTR } from '../../dataset/constant/Element'
|
import { EDITOR_ELEMENT_STYLE_ATTR } from '../../dataset/constant/Element'
|
||||||
import { titleSizeMapping } from '../../dataset/constant/Title'
|
import { titleSizeMapping } from '../../dataset/constant/Title'
|
||||||
import { defaultWatermarkOption } from '../../dataset/constant/Watermark'
|
import { defaultWatermarkOption } from '../../dataset/constant/Watermark'
|
||||||
import { ControlComponent, ImageDisplay } from '../../dataset/enum/Control'
|
import { ImageDisplay } from '../../dataset/enum/Common'
|
||||||
|
import { ControlComponent } from '../../dataset/enum/Control'
|
||||||
import {
|
import {
|
||||||
EditorContext,
|
EditorContext,
|
||||||
EditorMode,
|
EditorMode,
|
||||||
@@ -1944,6 +1945,22 @@ export class CommandAdapt {
|
|||||||
public changeImageDisplay(element: IElement, display: ImageDisplay) {
|
public changeImageDisplay(element: IElement, display: ImageDisplay) {
|
||||||
if (element.imgDisplay === display) return
|
if (element.imgDisplay === display) return
|
||||||
element.imgDisplay = display
|
element.imgDisplay = display
|
||||||
|
if (
|
||||||
|
display === ImageDisplay.FLOAT_TOP ||
|
||||||
|
display === ImageDisplay.FLOAT_BOTTOM
|
||||||
|
) {
|
||||||
|
const positionList = this.position.getPositionList()
|
||||||
|
const { startIndex } = this.range.getRange()
|
||||||
|
const {
|
||||||
|
coordinate: { leftTop }
|
||||||
|
} = positionList[startIndex]
|
||||||
|
element.imgFloatPosition = {
|
||||||
|
x: leftTop[0],
|
||||||
|
y: leftTop[1]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
delete element.imgFloatPosition
|
||||||
|
}
|
||||||
this.draw.getPreviewer().clearResizer()
|
this.draw.getPreviewer().clearResizer()
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
isSetCursor: false
|
isSetCursor: false
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { INTERNAL_CONTEXT_MENU_KEY } from '../../../dataset/constant/ContextMenu'
|
import { INTERNAL_CONTEXT_MENU_KEY } from '../../../dataset/constant/ContextMenu'
|
||||||
import { ImageDisplay } from '../../../dataset/enum/Control'
|
import { ImageDisplay } from '../../../dataset/enum/Common'
|
||||||
import { ElementType } from '../../../dataset/enum/Element'
|
import { ElementType } from '../../../dataset/enum/Element'
|
||||||
import {
|
import {
|
||||||
IContextMenuContext,
|
IContextMenuContext,
|
||||||
@@ -7,7 +7,15 @@ import {
|
|||||||
} from '../../../interface/contextmenu/ContextMenu'
|
} from '../../../interface/contextmenu/ContextMenu'
|
||||||
import { Command } from '../../command/Command'
|
import { Command } from '../../command/Command'
|
||||||
const {
|
const {
|
||||||
IMAGE: { CHANGE, SAVE_AS, TEXT_WRAP, TEXT_WRAP_EMBED, TEXT_WRAP_UP_DOWN }
|
IMAGE: {
|
||||||
|
CHANGE,
|
||||||
|
SAVE_AS,
|
||||||
|
TEXT_WRAP,
|
||||||
|
TEXT_WRAP_EMBED,
|
||||||
|
TEXT_WRAP_UP_DOWN,
|
||||||
|
TEXT_WRAP_FLOAT_TOP,
|
||||||
|
TEXT_WRAP_FLOAT_BOTTOM
|
||||||
|
}
|
||||||
} = INTERNAL_CONTEXT_MENU_KEY
|
} = INTERNAL_CONTEXT_MENU_KEY
|
||||||
|
|
||||||
export const imageMenus: IRegisterContextMenu[] = [
|
export const imageMenus: IRegisterContextMenu[] = [
|
||||||
@@ -86,6 +94,28 @@ export const imageMenus: IRegisterContextMenu[] = [
|
|||||||
ImageDisplay.INLINE
|
ImageDisplay.INLINE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: TEXT_WRAP_FLOAT_TOP,
|
||||||
|
i18nPath: 'contextmenu.image.textWrapType.floatTop',
|
||||||
|
when: () => true,
|
||||||
|
callback: (command: Command, context: IContextMenuContext) => {
|
||||||
|
command.executeChangeImageDisplay(
|
||||||
|
context.startElement!,
|
||||||
|
ImageDisplay.FLOAT_TOP
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: TEXT_WRAP_FLOAT_BOTTOM,
|
||||||
|
i18nPath: 'contextmenu.image.textWrapType.floatBottom',
|
||||||
|
when: () => true,
|
||||||
|
callback: (command: Command, context: IContextMenuContext) => {
|
||||||
|
command.executeChangeImageDisplay(
|
||||||
|
context.startElement!,
|
||||||
|
ImageDisplay.FLOAT_BOTTOM
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { ZERO } from '../../dataset/constant/Common'
|
|||||||
import { RowFlex } from '../../dataset/enum/Row'
|
import { RowFlex } from '../../dataset/enum/Row'
|
||||||
import {
|
import {
|
||||||
IAppendElementListOption,
|
IAppendElementListOption,
|
||||||
|
IDrawFloatPayload,
|
||||||
IDrawOption,
|
IDrawOption,
|
||||||
IDrawPagePayload,
|
IDrawPagePayload,
|
||||||
IDrawRowPayload,
|
IDrawRowPayload,
|
||||||
@@ -66,8 +67,7 @@ import { CheckboxParticle } from './particle/CheckboxParticle'
|
|||||||
import { DeepRequired, IPadding } from '../../interface/Common'
|
import { DeepRequired, IPadding } from '../../interface/Common'
|
||||||
import {
|
import {
|
||||||
ControlComponent,
|
ControlComponent,
|
||||||
ControlIndentation,
|
ControlIndentation
|
||||||
ImageDisplay
|
|
||||||
} from '../../dataset/enum/Control'
|
} from '../../dataset/enum/Control'
|
||||||
import { formatElementList } from '../../utils/element'
|
import { formatElementList } from '../../utils/element'
|
||||||
import { WorkerManager } from '../worker/WorkerManager'
|
import { WorkerManager } from '../worker/WorkerManager'
|
||||||
@@ -87,6 +87,7 @@ import { EventBus } from '../event/eventbus/EventBus'
|
|||||||
import { EventBusMap } from '../../interface/EventBus'
|
import { EventBusMap } from '../../interface/EventBus'
|
||||||
import { Group } from './interactive/Group'
|
import { Group } from './interactive/Group'
|
||||||
import { Override } from '../override/Override'
|
import { Override } from '../override/Override'
|
||||||
|
import { ImageDisplay } from '../../dataset/enum/Common'
|
||||||
|
|
||||||
export class Draw {
|
export class Draw {
|
||||||
private container: HTMLDivElement
|
private container: HTMLDivElement
|
||||||
@@ -1106,28 +1107,39 @@ export class Draw {
|
|||||||
element.type === ElementType.IMAGE ||
|
element.type === ElementType.IMAGE ||
|
||||||
element.type === ElementType.LATEX
|
element.type === ElementType.LATEX
|
||||||
) {
|
) {
|
||||||
const elementWidth = element.width! * scale
|
// 浮动图片无需计算数据
|
||||||
const elementHeight = element.height! * scale
|
if (
|
||||||
// 图片超出尺寸后自适应
|
element.imgDisplay === ImageDisplay.FLOAT_TOP ||
|
||||||
const curRowWidth =
|
element.imgDisplay === ImageDisplay.FLOAT_BOTTOM
|
||||||
element.imgDisplay === ImageDisplay.INLINE ? 0 : curRow.width
|
) {
|
||||||
if (curRowWidth + elementWidth > availableWidth) {
|
metrics.width = 0
|
||||||
// 计算剩余大小
|
metrics.height = 0
|
||||||
const surplusWidth = availableWidth - curRowWidth
|
metrics.boundingBoxDescent = 0
|
||||||
const adaptiveWidth =
|
|
||||||
surplusWidth > 0
|
|
||||||
? surplusWidth
|
|
||||||
: Math.min(elementWidth, availableWidth)
|
|
||||||
const adaptiveHeight = (elementHeight * adaptiveWidth) / elementWidth
|
|
||||||
element.width = adaptiveWidth / scale
|
|
||||||
element.height = adaptiveHeight / scale
|
|
||||||
metrics.width = adaptiveWidth
|
|
||||||
metrics.height = adaptiveHeight
|
|
||||||
metrics.boundingBoxDescent = adaptiveHeight
|
|
||||||
} else {
|
} else {
|
||||||
metrics.width = elementWidth
|
const elementWidth = element.width! * scale
|
||||||
metrics.height = elementHeight
|
const elementHeight = element.height! * scale
|
||||||
metrics.boundingBoxDescent = elementHeight
|
// 图片超出尺寸后自适应
|
||||||
|
const curRowWidth =
|
||||||
|
element.imgDisplay === ImageDisplay.INLINE ? 0 : curRow.width
|
||||||
|
if (curRowWidth + elementWidth > availableWidth) {
|
||||||
|
// 计算剩余大小
|
||||||
|
const surplusWidth = availableWidth - curRowWidth
|
||||||
|
const adaptiveWidth =
|
||||||
|
surplusWidth > 0
|
||||||
|
? surplusWidth
|
||||||
|
: Math.min(elementWidth, availableWidth)
|
||||||
|
const adaptiveHeight =
|
||||||
|
(elementHeight * adaptiveWidth) / elementWidth
|
||||||
|
element.width = adaptiveWidth / scale
|
||||||
|
element.height = adaptiveHeight / scale
|
||||||
|
metrics.width = adaptiveWidth
|
||||||
|
metrics.height = adaptiveHeight
|
||||||
|
metrics.boundingBoxDescent = adaptiveHeight
|
||||||
|
} else {
|
||||||
|
metrics.width = elementWidth
|
||||||
|
metrics.height = elementHeight
|
||||||
|
metrics.boundingBoxDescent = elementHeight
|
||||||
|
}
|
||||||
}
|
}
|
||||||
metrics.boundingBoxAscent = 0
|
metrics.boundingBoxAscent = 0
|
||||||
} else if (element.type === ElementType.TABLE) {
|
} else if (element.type === ElementType.TABLE) {
|
||||||
@@ -1607,7 +1619,13 @@ export class Draw {
|
|||||||
// 元素绘制
|
// 元素绘制
|
||||||
if (element.type === ElementType.IMAGE) {
|
if (element.type === ElementType.IMAGE) {
|
||||||
this._drawRichText(ctx)
|
this._drawRichText(ctx)
|
||||||
this.imageParticle.render(ctx, element, x, y + offsetY)
|
// 浮动图片单独绘制
|
||||||
|
if (
|
||||||
|
element.imgDisplay !== ImageDisplay.FLOAT_TOP &&
|
||||||
|
element.imgDisplay !== ImageDisplay.FLOAT_BOTTOM
|
||||||
|
) {
|
||||||
|
this.imageParticle.render(ctx, element, x, y + offsetY)
|
||||||
|
}
|
||||||
} else if (element.type === ElementType.LATEX) {
|
} else if (element.type === ElementType.LATEX) {
|
||||||
this._drawRichText(ctx)
|
this._drawRichText(ctx)
|
||||||
this.laTexParticle.render(ctx, element, x, y + offsetY)
|
this.laTexParticle.render(ctx, element, x, y + offsetY)
|
||||||
@@ -1816,6 +1834,31 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _drawFloat(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
payload: IDrawFloatPayload
|
||||||
|
) {
|
||||||
|
const floatPositionList = this.position.getFloatPositionList()
|
||||||
|
const { imgDisplay, pageNo } = payload
|
||||||
|
for (let e = 0; e < floatPositionList.length; e++) {
|
||||||
|
const floatPosition = floatPositionList[e]
|
||||||
|
const element = floatPosition.element
|
||||||
|
if (
|
||||||
|
pageNo === floatPosition.pageNo &&
|
||||||
|
element.imgDisplay === imgDisplay &&
|
||||||
|
element.type === ElementType.IMAGE
|
||||||
|
) {
|
||||||
|
const imgFloatPosition = element.imgFloatPosition!
|
||||||
|
this.imageParticle.render(
|
||||||
|
ctx,
|
||||||
|
element,
|
||||||
|
imgFloatPosition.x,
|
||||||
|
imgFloatPosition.y
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _clearPage(pageNo: number) {
|
private _clearPage(pageNo: number) {
|
||||||
const ctx = this.ctxList[pageNo]
|
const ctx = this.ctxList[pageNo]
|
||||||
const pageDom = this.pageList[pageNo]
|
const pageDom = this.pageList[pageNo]
|
||||||
@@ -1837,6 +1880,11 @@ export class Draw {
|
|||||||
if (this.mode !== EditorMode.PRINT) {
|
if (this.mode !== EditorMode.PRINT) {
|
||||||
this.margin.render(ctx, pageNo)
|
this.margin.render(ctx, pageNo)
|
||||||
}
|
}
|
||||||
|
// 渲染衬于文字下方元素
|
||||||
|
this._drawFloat(ctx, {
|
||||||
|
pageNo,
|
||||||
|
imgDisplay: ImageDisplay.FLOAT_BOTTOM
|
||||||
|
})
|
||||||
// 控件高亮
|
// 控件高亮
|
||||||
this.control.renderHighlightList(ctx, pageNo)
|
this.control.renderHighlightList(ctx, pageNo)
|
||||||
// 渲染元素
|
// 渲染元素
|
||||||
@@ -1864,6 +1912,11 @@ export class Draw {
|
|||||||
this.footer.render(ctx, pageNo)
|
this.footer.render(ctx, pageNo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 渲染浮于文字上方元素
|
||||||
|
this._drawFloat(ctx, {
|
||||||
|
pageNo,
|
||||||
|
imgDisplay: ImageDisplay.FLOAT_TOP
|
||||||
|
})
|
||||||
// 搜索匹配绘制
|
// 搜索匹配绘制
|
||||||
if (this.search.getSearchKeyword()) {
|
if (this.search.getSearchKeyword()) {
|
||||||
this.search.render(ctx, pageNo)
|
this.search.render(ctx, pageNo)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { EDITOR_PREFIX } from '../../../dataset/constant/Editor'
|
||||||
|
import { ImageDisplay } from '../../../dataset/enum/Common'
|
||||||
import { IEditorOption } from '../../../interface/Editor'
|
import { IEditorOption } from '../../../interface/Editor'
|
||||||
import { IElement } from '../../../interface/Element'
|
import { IElement } from '../../../interface/Element'
|
||||||
import { convertStringToBase64 } from '../../../utils'
|
import { convertStringToBase64 } from '../../../utils'
|
||||||
@@ -7,11 +9,62 @@ export class ImageParticle {
|
|||||||
private draw: Draw
|
private draw: Draw
|
||||||
protected options: Required<IEditorOption>
|
protected options: Required<IEditorOption>
|
||||||
protected imageCache: Map<string, HTMLImageElement>
|
protected imageCache: Map<string, HTMLImageElement>
|
||||||
|
private container: HTMLDivElement
|
||||||
|
private floatImageContainer: HTMLDivElement | null
|
||||||
|
private floatImage: HTMLImageElement | null
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
this.draw = draw
|
this.draw = draw
|
||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
|
this.container = draw.getContainer()
|
||||||
this.imageCache = new Map()
|
this.imageCache = new Map()
|
||||||
|
this.floatImageContainer = null
|
||||||
|
this.floatImage = null
|
||||||
|
}
|
||||||
|
|
||||||
|
public createFloatImage(element: IElement) {
|
||||||
|
const { scale } = this.options
|
||||||
|
// 复用浮动元素
|
||||||
|
let floatImageContainer = this.floatImageContainer
|
||||||
|
let floatImage = this.floatImage
|
||||||
|
if (!floatImageContainer) {
|
||||||
|
floatImageContainer = document.createElement('div')
|
||||||
|
floatImageContainer.classList.add(`${EDITOR_PREFIX}-float-image`)
|
||||||
|
this.container.append(floatImageContainer)
|
||||||
|
this.floatImageContainer = floatImageContainer
|
||||||
|
}
|
||||||
|
if (!floatImage) {
|
||||||
|
floatImage = document.createElement('img')
|
||||||
|
floatImageContainer.append(floatImage)
|
||||||
|
this.floatImage = floatImage
|
||||||
|
}
|
||||||
|
floatImageContainer.style.display = 'none'
|
||||||
|
floatImage.style.width = `${element.width! * scale}px`
|
||||||
|
floatImage.style.height = `${element.height! * scale}px`
|
||||||
|
// 浮动图片初始信息
|
||||||
|
const height = this.draw.getHeight()
|
||||||
|
const pageGap = this.draw.getPageGap()
|
||||||
|
const preY = this.draw.getPageNo() * (height + pageGap)
|
||||||
|
const imgFloatPosition = element.imgFloatPosition!
|
||||||
|
floatImageContainer.style.left = `${imgFloatPosition.x}px`
|
||||||
|
floatImageContainer.style.top = `${preY + imgFloatPosition.y}px`
|
||||||
|
floatImage.src = element.value
|
||||||
|
}
|
||||||
|
|
||||||
|
public dragFloatImage(movementX: number, movementY: number) {
|
||||||
|
if (!this.floatImageContainer) return
|
||||||
|
this.floatImageContainer.style.display = 'block'
|
||||||
|
// 之前的坐标加移动长度
|
||||||
|
const x = parseFloat(this.floatImageContainer.style.left) + movementX
|
||||||
|
const y = parseFloat(this.floatImageContainer.style.top) + movementY
|
||||||
|
this.floatImageContainer.style.left = `${x}px`
|
||||||
|
this.floatImageContainer.style.top = `${y}px`
|
||||||
|
}
|
||||||
|
|
||||||
|
public destroyFloatImage() {
|
||||||
|
if (this.floatImageContainer) {
|
||||||
|
this.floatImageContainer.style.display = 'none'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected addImageObserver(promise: Promise<unknown>) {
|
protected addImageObserver(promise: Promise<unknown>) {
|
||||||
@@ -58,9 +111,18 @@ export class ImageParticle {
|
|||||||
img.setAttribute('crossOrigin', 'Anonymous')
|
img.setAttribute('crossOrigin', 'Anonymous')
|
||||||
img.src = element.value
|
img.src = element.value
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
ctx.drawImage(img, x, y, width, height)
|
|
||||||
this.imageCache.set(element.id!, img)
|
this.imageCache.set(element.id!, img)
|
||||||
resolve(element)
|
resolve(element)
|
||||||
|
// 衬于文字下方图片需要重新首先绘制
|
||||||
|
if (element.imgDisplay === ImageDisplay.FLOAT_BOTTOM) {
|
||||||
|
this.draw.render({
|
||||||
|
isCompute: false,
|
||||||
|
isSetCursor: false,
|
||||||
|
isSubmitHistory: false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
ctx.drawImage(img, x, y, width, height)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
img.onerror = error => {
|
img.onerror = error => {
|
||||||
const fallbackImage = this.getFallbackImage(width, height)
|
const fallbackImage = this.getFallbackImage(width, height)
|
||||||
|
|||||||
@@ -63,6 +63,32 @@ export class Previewer {
|
|||||||
this.previewerImage = null
|
this.previewerImage = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _getElementPosition(
|
||||||
|
element: IElement,
|
||||||
|
position: IElementPosition | null = null
|
||||||
|
): { x: number; y: number } {
|
||||||
|
let x = 0
|
||||||
|
let y = 0
|
||||||
|
const height = this.draw.getHeight()
|
||||||
|
const pageGap = this.draw.getPageGap()
|
||||||
|
const preY = this.draw.getPageNo() * (height + pageGap)
|
||||||
|
// 优先使用浮动位置
|
||||||
|
if (element.imgFloatPosition) {
|
||||||
|
x = element.imgFloatPosition.x!
|
||||||
|
y = element.imgFloatPosition.y + preY
|
||||||
|
} else if (position) {
|
||||||
|
const {
|
||||||
|
coordinate: {
|
||||||
|
leftTop: [left, top]
|
||||||
|
},
|
||||||
|
ascent
|
||||||
|
} = position
|
||||||
|
x = left
|
||||||
|
y = top + preY + ascent
|
||||||
|
}
|
||||||
|
return { x, y }
|
||||||
|
}
|
||||||
|
|
||||||
private _createResizerDom(): IPreviewerCreateResult {
|
private _createResizerDom(): IPreviewerCreateResult {
|
||||||
// 拖拽边框
|
// 拖拽边框
|
||||||
const resizerSelection = document.createElement('div')
|
const resizerSelection = document.createElement('div')
|
||||||
@@ -114,10 +140,8 @@ export class Previewer {
|
|||||||
|
|
||||||
private _mousedown(evt: MouseEvent) {
|
private _mousedown(evt: MouseEvent) {
|
||||||
this.canvas = this.draw.getPage()
|
this.canvas = this.draw.getPage()
|
||||||
if (!this.curPosition || !this.curElement) return
|
if (!this.curElement) return
|
||||||
const { scale } = this.options
|
const { scale } = this.options
|
||||||
const height = this.draw.getHeight()
|
|
||||||
const pageGap = this.draw.getPageGap()
|
|
||||||
this.mousedownX = evt.x
|
this.mousedownX = evt.x
|
||||||
this.mousedownY = evt.y
|
this.mousedownY = evt.y
|
||||||
const target = evt.target as HTMLDivElement
|
const target = evt.target as HTMLDivElement
|
||||||
@@ -129,15 +153,13 @@ export class Previewer {
|
|||||||
// 拖拽图片镜像
|
// 拖拽图片镜像
|
||||||
this.resizerImage.src = this.curElementSrc
|
this.resizerImage.src = this.curElementSrc
|
||||||
this.resizerImageContainer.style.display = 'block'
|
this.resizerImageContainer.style.display = 'block'
|
||||||
const {
|
// 优先使用浮动位置信息
|
||||||
coordinate: {
|
const { x: resizerLeft, y: resizerTop } = this._getElementPosition(
|
||||||
leftTop: [left, top]
|
this.curElement,
|
||||||
},
|
this.curPosition
|
||||||
ascent
|
)
|
||||||
} = this.curPosition
|
this.resizerImageContainer.style.left = `${resizerLeft}px`
|
||||||
const prePageHeight = this.draw.getPageNo() * (height + pageGap)
|
this.resizerImageContainer.style.top = `${resizerTop}px`
|
||||||
this.resizerImageContainer.style.left = `${left}px`
|
|
||||||
this.resizerImageContainer.style.top = `${top + prePageHeight + ascent}px`
|
|
||||||
this.resizerImage.style.width = `${this.curElement.width! * scale}px`
|
this.resizerImage.style.width = `${this.curElement.width! * scale}px`
|
||||||
this.resizerImage.style.height = `${this.curElement.height! * scale}px`
|
this.resizerImage.style.height = `${this.curElement.height! * scale}px`
|
||||||
// 追加全局事件
|
// 追加全局事件
|
||||||
@@ -147,7 +169,7 @@ export class Previewer {
|
|||||||
'mouseup',
|
'mouseup',
|
||||||
() => {
|
() => {
|
||||||
// 改变尺寸
|
// 改变尺寸
|
||||||
if (this.curElement && this.curPosition) {
|
if (this.curElement) {
|
||||||
this.curElement.width = this.width
|
this.curElement.width = this.width
|
||||||
this.curElement.height = this.height
|
this.curElement.height = this.height
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render({ isSetCursor: false })
|
||||||
@@ -398,27 +420,22 @@ export class Previewer {
|
|||||||
|
|
||||||
public drawResizer(
|
public drawResizer(
|
||||||
element: IElement,
|
element: IElement,
|
||||||
position: IElementPosition,
|
position: IElementPosition | null = null,
|
||||||
options: IPreviewerDrawOption = {}
|
options: IPreviewerDrawOption = {}
|
||||||
) {
|
) {
|
||||||
this.previewerDrawOption = options
|
this.previewerDrawOption = options
|
||||||
const { scale } = this.options
|
const { scale } = this.options
|
||||||
const {
|
|
||||||
coordinate: {
|
|
||||||
leftTop: [left, top]
|
|
||||||
},
|
|
||||||
ascent
|
|
||||||
} = position
|
|
||||||
const elementWidth = element.width! * scale
|
const elementWidth = element.width! * scale
|
||||||
const elementHeight = element.height! * scale
|
const elementHeight = element.height! * scale
|
||||||
const height = this.draw.getHeight()
|
|
||||||
const pageGap = this.draw.getPageGap()
|
|
||||||
const preY = this.draw.getPageNo() * (height + pageGap)
|
|
||||||
// 尺寸预览
|
// 尺寸预览
|
||||||
this._updateResizerSizeView(elementWidth, elementHeight)
|
this._updateResizerSizeView(elementWidth, elementHeight)
|
||||||
// 边框
|
// 优先使用浮动位置信息
|
||||||
this.resizerSelection.style.left = `${left}px`
|
const { x: resizerLeft, y: resizerTop } = this._getElementPosition(
|
||||||
this.resizerSelection.style.top = `${top + preY + ascent}px`
|
element,
|
||||||
|
position
|
||||||
|
)
|
||||||
|
this.resizerSelection.style.left = `${resizerLeft}px`
|
||||||
|
this.resizerSelection.style.top = `${resizerTop}px`
|
||||||
// 更新预览包围框尺寸
|
// 更新预览包围框尺寸
|
||||||
this._updateResizerRect(elementWidth, elementHeight)
|
this._updateResizerRect(elementWidth, elementHeight)
|
||||||
this.resizerSelection.style.display = 'block'
|
this.resizerSelection.style.display = 'block'
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { ImageDisplay } from '../../../dataset/enum/Common'
|
||||||
import { ElementType } from '../../../dataset/enum/Element'
|
import { ElementType } from '../../../dataset/enum/Element'
|
||||||
import { MouseEventButton } from '../../../dataset/enum/Event'
|
import { MouseEventButton } from '../../../dataset/enum/Event'
|
||||||
import { deepClone } from '../../../utils'
|
import { deepClone } from '../../../utils'
|
||||||
@@ -60,7 +61,9 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
// 记录选区开始位置
|
// 记录选区开始位置
|
||||||
host.mouseDownStartPosition = {
|
host.mouseDownStartPosition = {
|
||||||
...positionResult,
|
...positionResult,
|
||||||
index: isTable ? tdValueIndex! : index
|
index: isTable ? tdValueIndex! : index,
|
||||||
|
x: evt.offsetX,
|
||||||
|
y: evt.offsetY
|
||||||
}
|
}
|
||||||
const elementList = draw.getElementList()
|
const elementList = draw.getElementList()
|
||||||
const positionList = position.getPositionList()
|
const positionList = position.getPositionList()
|
||||||
@@ -129,6 +132,13 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
})
|
})
|
||||||
// 点击图片允许拖拽调整位置
|
// 点击图片允许拖拽调整位置
|
||||||
setRangeCache(host)
|
setRangeCache(host)
|
||||||
|
// 浮动元素创建镜像图片
|
||||||
|
if (
|
||||||
|
curElement.imgDisplay === ImageDisplay.FLOAT_TOP ||
|
||||||
|
curElement.imgDisplay === ImageDisplay.FLOAT_BOTTOM
|
||||||
|
) {
|
||||||
|
draw.getImageParticle().createFloatImage(curElement)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 表格工具组件
|
// 表格工具组件
|
||||||
const tableTool = draw.getTableTool()
|
const tableTool = draw.getTableTool()
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { ImageDisplay } from '../../../dataset/enum/Common'
|
||||||
|
import { ElementType } from '../../../dataset/enum/Element'
|
||||||
import { CanvasEvent } from '../CanvasEvent'
|
import { CanvasEvent } from '../CanvasEvent'
|
||||||
|
|
||||||
export function mousemove(evt: MouseEvent, host: CanvasEvent) {
|
export function mousemove(evt: MouseEvent, host: CanvasEvent) {
|
||||||
@@ -22,6 +24,19 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const cacheStartIndex = host.cacheRange?.startIndex
|
||||||
|
if (cacheStartIndex) {
|
||||||
|
// 浮动元素拖拽调整位置
|
||||||
|
const dragElement = host.cacheElementList![cacheStartIndex]
|
||||||
|
if (
|
||||||
|
dragElement?.type === ElementType.IMAGE &&
|
||||||
|
(dragElement.imgDisplay === ImageDisplay.FLOAT_TOP ||
|
||||||
|
dragElement.imgDisplay === ImageDisplay.FLOAT_BOTTOM)
|
||||||
|
) {
|
||||||
|
draw.getPreviewer().clearResizer()
|
||||||
|
draw.getImageParticle().dragFloatImage(evt.movementX, evt.movementY)
|
||||||
|
}
|
||||||
|
}
|
||||||
host.dragover(evt)
|
host.dragover(evt)
|
||||||
host.isAllowDrop = true
|
host.isAllowDrop = true
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { EDITOR_ELEMENT_STYLE_ATTR } from '../../../dataset/constant/Element'
|
import { EDITOR_ELEMENT_STYLE_ATTR } from '../../../dataset/constant/Element'
|
||||||
|
import { ImageDisplay } from '../../../dataset/enum/Common'
|
||||||
import { ControlComponent, ControlType } from '../../../dataset/enum/Control'
|
import { ControlComponent, ControlType } from '../../../dataset/enum/Control'
|
||||||
import { ElementType } from '../../../dataset/enum/Element'
|
import { ElementType } from '../../../dataset/enum/Element'
|
||||||
import { IElement } from '../../../interface/Element'
|
import { IElement } from '../../../interface/Element'
|
||||||
@@ -18,6 +19,28 @@ function getElementIndexByDragId(dragId: string, elementList: IElement[]) {
|
|||||||
return (<IDragElement[]>elementList).findIndex(el => el.dragId === dragId)
|
return (<IDragElement[]>elementList).findIndex(el => el.dragId === dragId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 移动悬浮图片位置
|
||||||
|
function moveImgPosition(
|
||||||
|
element: IElement,
|
||||||
|
evt: MouseEvent,
|
||||||
|
host: CanvasEvent
|
||||||
|
) {
|
||||||
|
const draw = host.getDraw()
|
||||||
|
if (
|
||||||
|
element.imgDisplay === ImageDisplay.FLOAT_TOP ||
|
||||||
|
element.imgDisplay === ImageDisplay.FLOAT_BOTTOM
|
||||||
|
) {
|
||||||
|
const moveX = evt.offsetX - host.mouseDownStartPosition!.x!
|
||||||
|
const moveY = evt.offsetY - host.mouseDownStartPosition!.y!
|
||||||
|
const imgFloatPosition = element.imgFloatPosition!
|
||||||
|
element.imgFloatPosition = {
|
||||||
|
x: imgFloatPosition.x + moveX,
|
||||||
|
y: imgFloatPosition.y + moveY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw.getImageParticle().destroyFloatImage()
|
||||||
|
}
|
||||||
|
|
||||||
export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
||||||
// 判断是否允许拖放
|
// 判断是否允许拖放
|
||||||
if (host.isAllowDrop) {
|
if (host.isAllowDrop) {
|
||||||
@@ -42,13 +65,34 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
range.startIndex >= cacheStartIndex &&
|
range.startIndex >= cacheStartIndex &&
|
||||||
range.endIndex <= cacheEndIndex
|
range.endIndex <= cacheEndIndex
|
||||||
) {
|
) {
|
||||||
|
// 清除渲染副作用
|
||||||
|
draw.clearSideEffect()
|
||||||
|
// 浮动元素拖拽需要提交历史
|
||||||
|
let isSubmitHistory = false
|
||||||
|
if (isCacheRangeCollapsed) {
|
||||||
|
// 图片移动
|
||||||
|
const dragElement = cacheElementList[cacheEndIndex]
|
||||||
|
if (dragElement.type === ElementType.IMAGE) {
|
||||||
|
moveImgPosition(dragElement, evt, host)
|
||||||
|
if (
|
||||||
|
dragElement.imgDisplay === ImageDisplay.FLOAT_TOP ||
|
||||||
|
dragElement.imgDisplay === ImageDisplay.FLOAT_BOTTOM
|
||||||
|
) {
|
||||||
|
draw.getPreviewer().drawResizer(dragElement)
|
||||||
|
isSubmitHistory = true
|
||||||
|
} else {
|
||||||
|
const cachePosition = cachePositionList[cacheEndIndex]
|
||||||
|
draw.getPreviewer().drawResizer(dragElement, cachePosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
rangeManager.replaceRange({
|
rangeManager.replaceRange({
|
||||||
...cacheRange
|
...cacheRange
|
||||||
})
|
})
|
||||||
draw.render({
|
draw.render({
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isCompute: false,
|
isCompute: false,
|
||||||
isSubmitHistory: false
|
isSubmitHistory
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -207,11 +251,35 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
range.startTrIndex,
|
range.startTrIndex,
|
||||||
range.endTrIndex
|
range.endTrIndex
|
||||||
)
|
)
|
||||||
|
// 清除渲染副作用
|
||||||
|
draw.clearSideEffect()
|
||||||
|
// 移动图片
|
||||||
|
let imgElement: IElement | null = null
|
||||||
|
if (isCacheRangeCollapsed) {
|
||||||
|
const elementList = draw.getElementList()
|
||||||
|
const dragElement = elementList[rangeEndIndex]
|
||||||
|
if (dragElement.type === ElementType.IMAGE) {
|
||||||
|
moveImgPosition(dragElement, evt, host)
|
||||||
|
imgElement = dragElement
|
||||||
|
}
|
||||||
|
}
|
||||||
// 重新渲染
|
// 重新渲染
|
||||||
draw.render({
|
draw.render({
|
||||||
isSetCursor: false
|
isSetCursor: false
|
||||||
})
|
})
|
||||||
draw.clearSideEffect()
|
// 拖拽后渲染图片工具
|
||||||
|
if (imgElement) {
|
||||||
|
if (
|
||||||
|
imgElement.imgDisplay === ImageDisplay.FLOAT_TOP ||
|
||||||
|
imgElement.imgDisplay === ImageDisplay.FLOAT_BOTTOM
|
||||||
|
) {
|
||||||
|
draw.getPreviewer().drawResizer(imgElement)
|
||||||
|
} else {
|
||||||
|
const dragPositionList = position.getPositionList()
|
||||||
|
const dragPosition = dragPositionList[rangeEndIndex]
|
||||||
|
draw.getPreviewer().drawResizer(imgElement, dragPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (host.isAllowDrag) {
|
} else if (host.isAllowDrag) {
|
||||||
// 如果是允许拖拽不允许拖放则光标重置
|
// 如果是允许拖拽不允许拖放则光标重置
|
||||||
host.mousedown(evt)
|
host.mousedown(evt)
|
||||||
|
|||||||
@@ -21,7 +21,9 @@
|
|||||||
"textWrap": "Text wrap",
|
"textWrap": "Text wrap",
|
||||||
"textWrapType": {
|
"textWrapType": {
|
||||||
"embed": "Embed",
|
"embed": "Embed",
|
||||||
"upDown": "Up down"
|
"upDown": "Up down",
|
||||||
|
"floatTop": "Float above text",
|
||||||
|
"floatBottom": "Float below text"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
|
|||||||
@@ -21,7 +21,9 @@
|
|||||||
"textWrap": "文字环绕",
|
"textWrap": "文字环绕",
|
||||||
"textWrapType": {
|
"textWrapType": {
|
||||||
"embed": "嵌入型",
|
"embed": "嵌入型",
|
||||||
"upDown": "上下型环绕"
|
"upDown": "上下型环绕",
|
||||||
|
"floatTop": "浮于文字上方",
|
||||||
|
"floatBottom": "衬于文字下方"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { ElementType, RowFlex, VerticalAlign } from '../..'
|
import { ElementType, RowFlex, VerticalAlign } from '../..'
|
||||||
import { ZERO } from '../../dataset/constant/Common'
|
import { ZERO } from '../../dataset/constant/Common'
|
||||||
import { ControlComponent, ImageDisplay } from '../../dataset/enum/Control'
|
import { ControlComponent } from '../../dataset/enum/Control'
|
||||||
import {
|
import {
|
||||||
IComputePageRowPositionPayload,
|
IComputePageRowPositionPayload,
|
||||||
IComputePageRowPositionResult,
|
IComputePageRowPositionResult,
|
||||||
IComputeRowPositionPayload
|
IComputeRowPositionPayload,
|
||||||
|
IFloatPosition,
|
||||||
|
IGetFloatPositionByXYPayload
|
||||||
} from '../../interface/Position'
|
} from '../../interface/Position'
|
||||||
import { IEditorOption } from '../../interface/Editor'
|
import { IEditorOption } from '../../interface/Editor'
|
||||||
import { IElement, IElementPosition } from '../../interface/Element'
|
import { IElement, IElementPosition } from '../../interface/Element'
|
||||||
@@ -16,17 +18,20 @@ import {
|
|||||||
import { Draw } from '../draw/Draw'
|
import { Draw } from '../draw/Draw'
|
||||||
import { EditorMode, EditorZone } from '../../dataset/enum/Editor'
|
import { EditorMode, EditorZone } from '../../dataset/enum/Editor'
|
||||||
import { deepClone } from '../../utils'
|
import { deepClone } from '../../utils'
|
||||||
|
import { ImageDisplay } from '../../dataset/enum/Common'
|
||||||
|
|
||||||
export class Position {
|
export class Position {
|
||||||
private cursorPosition: IElementPosition | null
|
private cursorPosition: IElementPosition | null
|
||||||
private positionContext: IPositionContext
|
private positionContext: IPositionContext
|
||||||
private positionList: IElementPosition[]
|
private positionList: IElementPosition[]
|
||||||
|
private floatPositionList: IFloatPosition[]
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
this.positionList = []
|
this.positionList = []
|
||||||
|
this.floatPositionList = []
|
||||||
this.cursorPosition = null
|
this.cursorPosition = null
|
||||||
this.positionContext = {
|
this.positionContext = {
|
||||||
isTable: false,
|
isTable: false,
|
||||||
@@ -37,6 +42,10 @@ export class Position {
|
|||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getFloatPositionList(): IFloatPosition[] {
|
||||||
|
return this.floatPositionList
|
||||||
|
}
|
||||||
|
|
||||||
public getTablePositionList(
|
public getTablePositionList(
|
||||||
sourceElementList: IElement[]
|
sourceElementList: IElement[]
|
||||||
): IElementPosition[] {
|
): IElementPosition[] {
|
||||||
@@ -149,6 +158,28 @@ export class Position {
|
|||||||
rightBottom: [x + metrics.width, y + curRow.height]
|
rightBottom: [x + metrics.width, y + curRow.height]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 缓存浮动元素信息
|
||||||
|
if (
|
||||||
|
element.imgDisplay === ImageDisplay.FLOAT_TOP ||
|
||||||
|
element.imgDisplay === ImageDisplay.FLOAT_BOTTOM
|
||||||
|
) {
|
||||||
|
// 浮动元素使用上一位置信息
|
||||||
|
const prePosition = positionList[positionList.length - 1]
|
||||||
|
if (prePosition) {
|
||||||
|
positionItem.metrics = prePosition.metrics
|
||||||
|
positionItem.coordinate = prePosition.coordinate
|
||||||
|
}
|
||||||
|
this.floatPositionList.push({
|
||||||
|
pageNo,
|
||||||
|
element,
|
||||||
|
position: positionItem,
|
||||||
|
isTable: payload.isTable,
|
||||||
|
index: payload.index,
|
||||||
|
tdIndex: payload.tdIndex,
|
||||||
|
trIndex: payload.trIndex,
|
||||||
|
tdValueIndex: index
|
||||||
|
})
|
||||||
|
}
|
||||||
positionList.push(positionItem)
|
positionList.push(positionItem)
|
||||||
index++
|
index++
|
||||||
x += metrics.width
|
x += metrics.width
|
||||||
@@ -170,7 +201,11 @@ export class Position {
|
|||||||
startIndex: 0,
|
startIndex: 0,
|
||||||
startX: (td.x! + tdPadding[3]) * scale + tablePreX,
|
startX: (td.x! + tdPadding[3]) * scale + tablePreX,
|
||||||
startY: (td.y! + tdPadding[0]) * scale + tablePreY,
|
startY: (td.y! + tdPadding[0]) * scale + tablePreY,
|
||||||
innerWidth: (td.width! - tdPaddingWidth) * scale
|
innerWidth: (td.width! - tdPaddingWidth) * scale,
|
||||||
|
isTable: true,
|
||||||
|
index: index - 1,
|
||||||
|
tdIndex: d,
|
||||||
|
trIndex: t
|
||||||
})
|
})
|
||||||
// 垂直对齐方式
|
// 垂直对齐方式
|
||||||
if (
|
if (
|
||||||
@@ -217,6 +252,7 @@ export class Position {
|
|||||||
public computePositionList() {
|
public computePositionList() {
|
||||||
// 置空原位置信息
|
// 置空原位置信息
|
||||||
this.positionList = []
|
this.positionList = []
|
||||||
|
this.floatPositionList = []
|
||||||
// 按每页行计算
|
// 按每页行计算
|
||||||
const innerWidth = this.draw.getInnerWidth()
|
const innerWidth = this.draw.getInnerWidth()
|
||||||
const pageRowList = this.draw.getPageRowList()
|
const pageRowList = this.draw.getPageRowList()
|
||||||
@@ -291,6 +327,15 @@ export class Position {
|
|||||||
const curPageNo = payload.pageNo ?? this.draw.getPageNo()
|
const curPageNo = payload.pageNo ?? this.draw.getPageNo()
|
||||||
const isMainActive = zoneManager.isMainActive()
|
const isMainActive = zoneManager.isMainActive()
|
||||||
const positionNo = isMainActive ? curPageNo : 0
|
const positionNo = isMainActive ? curPageNo : 0
|
||||||
|
// 验证浮于文字上方元素
|
||||||
|
if (!isTable) {
|
||||||
|
const floatTopPosition = this.getFloatPositionByXY({
|
||||||
|
...payload,
|
||||||
|
imgDisplay: ImageDisplay.FLOAT_TOP
|
||||||
|
})
|
||||||
|
if (floatTopPosition) return floatTopPosition
|
||||||
|
}
|
||||||
|
// 普通元素
|
||||||
for (let j = 0; j < positionList.length; j++) {
|
for (let j = 0; j < positionList.length; j++) {
|
||||||
const {
|
const {
|
||||||
index,
|
index,
|
||||||
@@ -388,6 +433,14 @@ export class Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 验证衬于文字下方元素
|
||||||
|
if (!isTable) {
|
||||||
|
const floatBottomPosition = this.getFloatPositionByXY({
|
||||||
|
...payload,
|
||||||
|
imgDisplay: ImageDisplay.FLOAT_BOTTOM
|
||||||
|
})
|
||||||
|
if (floatBottomPosition) return floatBottomPosition
|
||||||
|
}
|
||||||
// 非命中区域
|
// 非命中区域
|
||||||
let isLastArea = false
|
let isLastArea = false
|
||||||
let curPositionIndex = -1
|
let curPositionIndex = -1
|
||||||
@@ -493,6 +546,55 @@ export class Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getFloatPositionByXY(
|
||||||
|
payload: IGetFloatPositionByXYPayload
|
||||||
|
): ICurrentPosition | void {
|
||||||
|
const { x, y } = payload
|
||||||
|
for (let f = 0; f < this.floatPositionList.length; f++) {
|
||||||
|
const {
|
||||||
|
position,
|
||||||
|
element,
|
||||||
|
isTable,
|
||||||
|
index,
|
||||||
|
trIndex,
|
||||||
|
tdIndex,
|
||||||
|
tdValueIndex
|
||||||
|
} = this.floatPositionList[f]
|
||||||
|
if (
|
||||||
|
element.type === ElementType.IMAGE &&
|
||||||
|
element.imgDisplay === payload.imgDisplay
|
||||||
|
) {
|
||||||
|
const imgFloatPosition = element.imgFloatPosition!
|
||||||
|
if (
|
||||||
|
x >= imgFloatPosition.x &&
|
||||||
|
x <= imgFloatPosition.x + element.width! &&
|
||||||
|
y >= imgFloatPosition.y &&
|
||||||
|
y <= imgFloatPosition.y + element.height!
|
||||||
|
) {
|
||||||
|
if (isTable) {
|
||||||
|
return {
|
||||||
|
index: index!,
|
||||||
|
isDirectHit: true,
|
||||||
|
isImage: true,
|
||||||
|
isTable,
|
||||||
|
trIndex,
|
||||||
|
tdIndex,
|
||||||
|
tdValueIndex,
|
||||||
|
tdId: element.tdId,
|
||||||
|
trId: element.trId,
|
||||||
|
tableId: element.tableId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
index: position.index,
|
||||||
|
isDirectHit: true,
|
||||||
|
isImage: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public adjustPositionContext(
|
public adjustPositionContext(
|
||||||
payload: IGetPositionByXYPayload
|
payload: IGetPositionByXYPayload
|
||||||
): ICurrentPosition | null {
|
): ICurrentPosition | null {
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ export const INTERNAL_CONTEXT_MENU_KEY = {
|
|||||||
SAVE_AS: 'imageSaveAs',
|
SAVE_AS: 'imageSaveAs',
|
||||||
TEXT_WRAP: 'imageTextWrap',
|
TEXT_WRAP: 'imageTextWrap',
|
||||||
TEXT_WRAP_EMBED: 'imageTextWrapEmbed',
|
TEXT_WRAP_EMBED: 'imageTextWrapEmbed',
|
||||||
TEXT_WRAP_UP_DOWN: 'imageTextWrapUpDown'
|
TEXT_WRAP_UP_DOWN: 'imageTextWrapUpDown',
|
||||||
|
TEXT_WRAP_FLOAT_TOP: 'imageTextWrapFloatTop',
|
||||||
|
TEXT_WRAP_FLOAT_BOTTOM: 'imageTextWrapFloatBottom'
|
||||||
},
|
},
|
||||||
TABLE: {
|
TABLE: {
|
||||||
BORDER: 'border',
|
BORDER: 'border',
|
||||||
|
|||||||
@@ -64,7 +64,9 @@ export const EDITOR_ELEMENT_ZIP_ATTR: Array<keyof IElement> = [
|
|||||||
'listStyle',
|
'listStyle',
|
||||||
'listWrap',
|
'listWrap',
|
||||||
'groupIds',
|
'groupIds',
|
||||||
'conceptId'
|
'conceptId',
|
||||||
|
'imgDisplay',
|
||||||
|
'imgFloatPosition'
|
||||||
]
|
]
|
||||||
|
|
||||||
export const TABLE_TD_ZIP_ATTR: Array<keyof ITd> = [
|
export const TABLE_TD_ZIP_ATTR: Array<keyof ITd> = [
|
||||||
|
|||||||
@@ -8,3 +8,10 @@ export enum NumberType {
|
|||||||
ARABIC = 'arabic',
|
ARABIC = 'arabic',
|
||||||
CHINESE = 'chinese'
|
CHINESE = 'chinese'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ImageDisplay {
|
||||||
|
INLINE = 'inline',
|
||||||
|
BLOCK = 'block',
|
||||||
|
FLOAT_TOP = 'float-top',
|
||||||
|
FLOAT_BOTTOM = 'float-bottom'
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,11 +12,6 @@ export enum ControlComponent {
|
|||||||
CHECKBOX = 'checkbox'
|
CHECKBOX = 'checkbox'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ImageDisplay {
|
|
||||||
INLINE = 'inline',
|
|
||||||
BLOCK = 'block'
|
|
||||||
}
|
|
||||||
|
|
||||||
// 控件内容缩进方式
|
// 控件内容缩进方式
|
||||||
export enum ControlIndentation {
|
export enum ControlIndentation {
|
||||||
ROW_START = 'rowStart', // 从行起始位置缩进
|
ROW_START = 'rowStart', // 从行起始位置缩进
|
||||||
|
|||||||
+2
-5
@@ -6,6 +6,7 @@ import { Command } from './core/command/Command'
|
|||||||
import { CommandAdapt } from './core/command/CommandAdapt'
|
import { CommandAdapt } from './core/command/CommandAdapt'
|
||||||
import { Listener } from './core/listener/Listener'
|
import { Listener } from './core/listener/Listener'
|
||||||
import { RowFlex } from './dataset/enum/Row'
|
import { RowFlex } from './dataset/enum/Row'
|
||||||
|
import { ImageDisplay } from './dataset/enum/Common'
|
||||||
import { ElementType } from './dataset/enum/Element'
|
import { ElementType } from './dataset/enum/Element'
|
||||||
import { formatElementList } from './utils/element'
|
import { formatElementList } from './utils/element'
|
||||||
import { Register } from './core/register/Register'
|
import { Register } from './core/register/Register'
|
||||||
@@ -27,11 +28,7 @@ import { IHeader } from './interface/Header'
|
|||||||
import { IWatermark } from './interface/Watermark'
|
import { IWatermark } from './interface/Watermark'
|
||||||
import { defaultHeaderOption } from './dataset/constant/Header'
|
import { defaultHeaderOption } from './dataset/constant/Header'
|
||||||
import { defaultWatermarkOption } from './dataset/constant/Watermark'
|
import { defaultWatermarkOption } from './dataset/constant/Watermark'
|
||||||
import {
|
import { ControlIndentation, ControlType } from './dataset/enum/Control'
|
||||||
ControlIndentation,
|
|
||||||
ControlType,
|
|
||||||
ImageDisplay
|
|
||||||
} from './dataset/enum/Control'
|
|
||||||
import { defaultControlOption } from './dataset/constant/Control'
|
import { defaultControlOption } from './dataset/constant/Control'
|
||||||
import { IControlOption } from './interface/Control'
|
import { IControlOption } from './interface/Control'
|
||||||
import { ICheckboxOption } from './interface/Checkbox'
|
import { ICheckboxOption } from './interface/Checkbox'
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { ImageDisplay } from '../dataset/enum/Common'
|
||||||
import { EditorMode, EditorZone } from '../dataset/enum/Editor'
|
import { EditorMode, EditorZone } from '../dataset/enum/Editor'
|
||||||
import { IElement, IElementPosition } from './Element'
|
import { IElement, IElementPosition } from './Element'
|
||||||
import { IRow } from './Row'
|
import { IRow } from './Row'
|
||||||
@@ -32,6 +33,11 @@ export interface IDrawRowPayload {
|
|||||||
zone?: EditorZone
|
zone?: EditorZone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IDrawFloatPayload {
|
||||||
|
pageNo: number
|
||||||
|
imgDisplay: ImageDisplay
|
||||||
|
}
|
||||||
|
|
||||||
export interface IDrawPagePayload {
|
export interface IDrawPagePayload {
|
||||||
elementList: IElement[]
|
elementList: IElement[]
|
||||||
positionList: IElementPosition[]
|
positionList: IElementPosition[]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { ControlComponent, ImageDisplay } from '../dataset/enum/Control'
|
import { ImageDisplay } from '../dataset/enum/Common'
|
||||||
|
import { ControlComponent } from '../dataset/enum/Control'
|
||||||
import { ElementType } from '../dataset/enum/Element'
|
import { ElementType } from '../dataset/enum/Element'
|
||||||
import { ListStyle, ListType } from '../dataset/enum/List'
|
import { ListStyle, ListType } from '../dataset/enum/List'
|
||||||
import { RowFlex } from '../dataset/enum/Row'
|
import { RowFlex } from '../dataset/enum/Row'
|
||||||
@@ -100,6 +101,10 @@ export interface IDateElement {
|
|||||||
|
|
||||||
export interface IImageElement {
|
export interface IImageElement {
|
||||||
imgDisplay?: ImageDisplay
|
imgDisplay?: ImageDisplay
|
||||||
|
imgFloatPosition?: {
|
||||||
|
x: number
|
||||||
|
y: number
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IBlockElement {
|
export interface IBlockElement {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IElement } from '..'
|
import { IElement, ImageDisplay } from '..'
|
||||||
import { EditorZone } from '../dataset/enum/Editor'
|
import { EditorZone } from '../dataset/enum/Editor'
|
||||||
import { IElementPosition } from './Element'
|
import { IElementPosition } from './Element'
|
||||||
import { IRow } from './Row'
|
import { IRow } from './Row'
|
||||||
@@ -6,6 +6,8 @@ import { ITd } from './table/Td'
|
|||||||
|
|
||||||
export interface ICurrentPosition {
|
export interface ICurrentPosition {
|
||||||
index: number
|
index: number
|
||||||
|
x?: number
|
||||||
|
y?: number
|
||||||
isCheckbox?: boolean
|
isCheckbox?: boolean
|
||||||
isControl?: boolean
|
isControl?: boolean
|
||||||
isImage?: boolean
|
isImage?: boolean
|
||||||
@@ -32,6 +34,10 @@ export interface IGetPositionByXYPayload {
|
|||||||
positionList?: IElementPosition[]
|
positionList?: IElementPosition[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type IGetFloatPositionByXYPayload = IGetPositionByXYPayload & {
|
||||||
|
imgDisplay: ImageDisplay
|
||||||
|
}
|
||||||
|
|
||||||
export interface IPositionContext {
|
export interface IPositionContext {
|
||||||
isTable: boolean
|
isTable: boolean
|
||||||
isCheckbox?: boolean
|
isCheckbox?: boolean
|
||||||
@@ -58,6 +64,11 @@ export interface IComputePageRowPositionPayload {
|
|||||||
startX: number
|
startX: number
|
||||||
startY: number
|
startY: number
|
||||||
innerWidth: number
|
innerWidth: number
|
||||||
|
isTable?: boolean
|
||||||
|
index?: number
|
||||||
|
tdIndex?: number
|
||||||
|
trIndex?: number
|
||||||
|
tdValueIndex?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IComputePageRowPositionResult {
|
export interface IComputePageRowPositionResult {
|
||||||
@@ -65,3 +76,14 @@ export interface IComputePageRowPositionResult {
|
|||||||
y: number
|
y: number
|
||||||
index: number
|
index: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IFloatPosition {
|
||||||
|
pageNo: number
|
||||||
|
element: IElement
|
||||||
|
position: IElementPosition
|
||||||
|
isTable?: boolean
|
||||||
|
index?: number
|
||||||
|
tdIndex?: number
|
||||||
|
trIndex?: number
|
||||||
|
tdValueIndex?: number
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user