refactor: add prettier and format
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 80,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"endOfLine": "lf"
|
||||||
|
}
|
||||||
Vendored
+12
-1
@@ -10,9 +10,11 @@
|
|||||||
"CRDT",
|
"CRDT",
|
||||||
"deletable",
|
"deletable",
|
||||||
"dppx",
|
"dppx",
|
||||||
|
"esbenp",
|
||||||
"inputarea",
|
"inputarea",
|
||||||
"linebreak",
|
"linebreak",
|
||||||
"noopener",
|
"noopener",
|
||||||
|
"Parens",
|
||||||
"prismjs",
|
"prismjs",
|
||||||
"resizer",
|
"resizer",
|
||||||
"richtext",
|
"richtext",
|
||||||
@@ -34,5 +36,14 @@
|
|||||||
"typescript.tsdk": "node_modules/typescript/lib",
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": true
|
"source.fixAll.eslint": true
|
||||||
|
},
|
||||||
|
"[typescript]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[javascript]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[json]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,36 +2,39 @@ import { EditorComponent, EDITOR_COMPONENT } from '../../editor'
|
|||||||
import './dialog.css'
|
import './dialog.css'
|
||||||
|
|
||||||
export interface IDialogData {
|
export interface IDialogData {
|
||||||
type: string;
|
type: string
|
||||||
label?: string;
|
label?: string
|
||||||
name: string;
|
name: string
|
||||||
value?: string;
|
value?: string
|
||||||
options?: { label: string; value: string; }[];
|
options?: { label: string; value: string }[]
|
||||||
placeholder?: string;
|
placeholder?: string
|
||||||
width?: number;
|
width?: number
|
||||||
height?: number;
|
height?: number
|
||||||
required?: boolean;
|
required?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDialogConfirm {
|
export interface IDialogConfirm {
|
||||||
name: string;
|
name: string
|
||||||
value: string;
|
value: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDialogOptions {
|
export interface IDialogOptions {
|
||||||
onClose?: () => void;
|
onClose?: () => void
|
||||||
onCancel?: () => void;
|
onCancel?: () => void
|
||||||
onConfirm?: (payload: IDialogConfirm[]) => void;
|
onConfirm?: (payload: IDialogConfirm[]) => void
|
||||||
title: string;
|
title: string
|
||||||
data: IDialogData[];
|
data: IDialogData[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Dialog {
|
export class Dialog {
|
||||||
|
|
||||||
private options: IDialogOptions
|
private options: IDialogOptions
|
||||||
private mask: HTMLDivElement | null
|
private mask: HTMLDivElement | null
|
||||||
private container: HTMLDivElement | null
|
private container: HTMLDivElement | null
|
||||||
private inputList: (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)[]
|
private inputList: (
|
||||||
|
| HTMLInputElement
|
||||||
|
| HTMLTextAreaElement
|
||||||
|
| HTMLSelectElement
|
||||||
|
)[]
|
||||||
|
|
||||||
constructor(options: IDialogOptions) {
|
constructor(options: IDialogOptions) {
|
||||||
this.options = options
|
this.options = options
|
||||||
@@ -90,7 +93,10 @@ export class Dialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 选项输入框
|
// 选项输入框
|
||||||
let optionInput: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
|
let optionInput:
|
||||||
|
| HTMLInputElement
|
||||||
|
| HTMLTextAreaElement
|
||||||
|
| HTMLSelectElement
|
||||||
if (option.type === 'select') {
|
if (option.type === 'select') {
|
||||||
optionInput = document.createElement('select')
|
optionInput = document.createElement('select')
|
||||||
option.options?.forEach(item => {
|
option.options?.forEach(item => {
|
||||||
@@ -162,5 +168,4 @@ export class Dialog {
|
|||||||
this.mask?.remove()
|
this.mask?.remove()
|
||||||
this.container?.remove()
|
this.container?.remove()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ import { EditorComponent, EDITOR_COMPONENT } from '../../editor'
|
|||||||
import './signature.css'
|
import './signature.css'
|
||||||
|
|
||||||
export interface ISignatureResult {
|
export interface ISignatureResult {
|
||||||
value: string;
|
value: string
|
||||||
width: number;
|
width: number
|
||||||
height: number;
|
height: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISignatureOptions {
|
export interface ISignatureOptions {
|
||||||
width?: number;
|
width?: number
|
||||||
height?: number;
|
height?: number
|
||||||
onClose?: () => void;
|
onClose?: () => void
|
||||||
onCancel?: () => void;
|
onCancel?: () => void
|
||||||
onConfirm?: (payload: ISignatureResult | null) => void;
|
onConfirm?: (payload: ISignatureResult | null) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Signature {
|
export class Signature {
|
||||||
@@ -43,7 +43,8 @@ export class Signature {
|
|||||||
this.dpr = window.devicePixelRatio
|
this.dpr = window.devicePixelRatio
|
||||||
this.canvasWidth = (options.width || this.DEFAULT_WIDTH) * this.dpr
|
this.canvasWidth = (options.width || this.DEFAULT_WIDTH) * this.dpr
|
||||||
this.canvasHeight = (options.height || this.DEFAULT_HEIGHT) * this.dpr
|
this.canvasHeight = (options.height || this.DEFAULT_HEIGHT) * this.dpr
|
||||||
const { mask, container, trashContainer, undoContainer, canvas } = this._render()
|
const { mask, container, trashContainer, undoContainer, canvas } =
|
||||||
|
this._render()
|
||||||
this.mask = mask
|
this.mask = mask
|
||||||
this.container = container
|
this.container = container
|
||||||
this.trashContainer = trashContainer
|
this.trashContainer = trashContainer
|
||||||
@@ -213,7 +214,8 @@ export class Signature {
|
|||||||
const targetLineWidth = Math.min(5, Math.max(1, 5 - speed * SPEED_FACTOR))
|
const targetLineWidth = Math.min(5, Math.max(1, 5 - speed * SPEED_FACTOR))
|
||||||
// 平滑过渡算法(20%的变化比例)调整线条粗细:系数0.2
|
// 平滑过渡算法(20%的变化比例)调整线条粗细:系数0.2
|
||||||
const SMOOTH_FACTOR = 0.2
|
const SMOOTH_FACTOR = 0.2
|
||||||
this.ctx.lineWidth = this.ctx.lineWidth * (1 - SMOOTH_FACTOR) + targetLineWidth * SMOOTH_FACTOR
|
this.ctx.lineWidth =
|
||||||
|
this.ctx.lineWidth * (1 - SMOOTH_FACTOR) + targetLineWidth * SMOOTH_FACTOR
|
||||||
// 绘制
|
// 绘制
|
||||||
const { offsetX, offsetY } = evt
|
const { offsetX, offsetY } = evt
|
||||||
this.ctx.beginPath()
|
this.ctx.beginPath()
|
||||||
@@ -231,7 +233,12 @@ export class Signature {
|
|||||||
private _stopDraw() {
|
private _stopDraw() {
|
||||||
this.isDrawing = false
|
this.isDrawing = false
|
||||||
if (this.isDrawn) {
|
if (this.isDrawn) {
|
||||||
const imageData = this.ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight)
|
const imageData = this.ctx.getImageData(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
this.canvasWidth,
|
||||||
|
this.canvasHeight
|
||||||
|
)
|
||||||
const self = this
|
const self = this
|
||||||
this._saveUndoFn(function () {
|
this._saveUndoFn(function () {
|
||||||
self.ctx.clearRect(0, 0, self.canvasWidth, self.canvasHeight)
|
self.ctx.clearRect(0, 0, self.canvasWidth, self.canvasHeight)
|
||||||
@@ -299,5 +306,4 @@ export class Signature {
|
|||||||
this.mask.remove()
|
this.mask.remove()
|
||||||
this.container.remove()
|
this.container.remove()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { CommandAdapt } from './CommandAdapt'
|
|||||||
|
|
||||||
// 通过CommandAdapt中转避免直接暴露编辑器上下文
|
// 通过CommandAdapt中转避免直接暴露编辑器上下文
|
||||||
export class Command {
|
export class Command {
|
||||||
|
|
||||||
public executeMode: CommandAdapt['mode']
|
public executeMode: CommandAdapt['mode']
|
||||||
public executeCut: CommandAdapt['cut']
|
public executeCut: CommandAdapt['cut']
|
||||||
public executeCopy: CommandAdapt['copy']
|
public executeCopy: CommandAdapt['copy']
|
||||||
@@ -130,7 +129,8 @@ export class Command {
|
|||||||
this.executeCancelMergeTableCell = adapt.cancelMergeTableCell.bind(adapt)
|
this.executeCancelMergeTableCell = adapt.cancelMergeTableCell.bind(adapt)
|
||||||
this.executeTableTdVerticalAlign = adapt.tableTdVerticalAlign.bind(adapt)
|
this.executeTableTdVerticalAlign = adapt.tableTdVerticalAlign.bind(adapt)
|
||||||
this.executeTableBorderType = adapt.tableBorderType.bind(adapt)
|
this.executeTableBorderType = adapt.tableBorderType.bind(adapt)
|
||||||
this.executeTableTdBackgroundColor = adapt.tableTdBackgroundColor.bind(adapt)
|
this.executeTableTdBackgroundColor =
|
||||||
|
adapt.tableTdBackgroundColor.bind(adapt)
|
||||||
this.executeImage = adapt.image.bind(adapt)
|
this.executeImage = adapt.image.bind(adapt)
|
||||||
this.executeHyperlink = adapt.hyperlink.bind(adapt)
|
this.executeHyperlink = adapt.hyperlink.bind(adapt)
|
||||||
this.executeDeleteHyperlink = adapt.deleteHyperlink.bind(adapt)
|
this.executeDeleteHyperlink = adapt.deleteHyperlink.bind(adapt)
|
||||||
@@ -174,5 +174,4 @@ export class Command {
|
|||||||
this.getPaperMargin = adapt.getPaperMargin.bind(adapt)
|
this.getPaperMargin = adapt.getPaperMargin.bind(adapt)
|
||||||
this.getSearchNavigateInfo = adapt.getSearchNavigateInfo.bind(adapt)
|
this.getSearchNavigateInfo = adapt.getSearchNavigateInfo.bind(adapt)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,12 @@ 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 { ControlComponent, ImageDisplay } from '../../dataset/enum/Control'
|
||||||
import { EditorContext, EditorMode, PageMode, PaperDirection } from '../../dataset/enum/Editor'
|
import {
|
||||||
|
EditorContext,
|
||||||
|
EditorMode,
|
||||||
|
PageMode,
|
||||||
|
PaperDirection
|
||||||
|
} from '../../dataset/enum/Editor'
|
||||||
import { ElementType } from '../../dataset/enum/Element'
|
import { ElementType } from '../../dataset/enum/Element'
|
||||||
import { ElementStyleKey } from '../../dataset/enum/ElementStyle'
|
import { ElementStyleKey } from '../../dataset/enum/ElementStyle'
|
||||||
import { ListStyle, ListType } from '../../dataset/enum/List'
|
import { ListStyle, ListType } from '../../dataset/enum/List'
|
||||||
@@ -12,8 +17,17 @@ import { TableBorder } from '../../dataset/enum/table/Table'
|
|||||||
import { TitleLevel } from '../../dataset/enum/Title'
|
import { TitleLevel } from '../../dataset/enum/Title'
|
||||||
import { VerticalAlign } from '../../dataset/enum/VerticalAlign'
|
import { VerticalAlign } from '../../dataset/enum/VerticalAlign'
|
||||||
import { ICatalog } from '../../interface/Catalog'
|
import { ICatalog } from '../../interface/Catalog'
|
||||||
import { IAppendElementListOption, IDrawImagePayload, IGetValueOption, IPainterOption } from '../../interface/Draw'
|
import {
|
||||||
import { IEditorData, IEditorOption, IEditorResult } from '../../interface/Editor'
|
IAppendElementListOption,
|
||||||
|
IDrawImagePayload,
|
||||||
|
IGetValueOption,
|
||||||
|
IPainterOption
|
||||||
|
} from '../../interface/Draw'
|
||||||
|
import {
|
||||||
|
IEditorData,
|
||||||
|
IEditorOption,
|
||||||
|
IEditorResult
|
||||||
|
} from '../../interface/Editor'
|
||||||
import { IElement, IElementStyle } from '../../interface/Element'
|
import { IElement, IElementStyle } from '../../interface/Element'
|
||||||
import { IMargin } from '../../interface/Margin'
|
import { IMargin } from '../../interface/Margin'
|
||||||
import { RangeContext } from '../../interface/Range'
|
import { RangeContext } from '../../interface/Range'
|
||||||
@@ -22,7 +36,12 @@ import { ITd } from '../../interface/table/Td'
|
|||||||
import { ITr } from '../../interface/table/Tr'
|
import { ITr } from '../../interface/table/Tr'
|
||||||
import { IWatermark } from '../../interface/Watermark'
|
import { IWatermark } from '../../interface/Watermark'
|
||||||
import { deepClone, downloadFile, getUUID } from '../../utils'
|
import { deepClone, downloadFile, getUUID } from '../../utils'
|
||||||
import { formatElementContext, formatElementList, isTextLikeElement, pickElementAttr } from '../../utils/element'
|
import {
|
||||||
|
formatElementContext,
|
||||||
|
formatElementList,
|
||||||
|
isTextLikeElement,
|
||||||
|
pickElementAttr
|
||||||
|
} from '../../utils/element'
|
||||||
import { printImageBase64 } from '../../utils/print'
|
import { printImageBase64 } from '../../utils/print'
|
||||||
import { Control } from '../draw/control/Control'
|
import { Control } from '../draw/control/Control'
|
||||||
import { Draw } from '../draw/Draw'
|
import { Draw } from '../draw/Draw'
|
||||||
@@ -36,7 +55,6 @@ import { RangeManager } from '../range/RangeManager'
|
|||||||
import { WorkerManager } from '../worker/WorkerManager'
|
import { WorkerManager } from '../worker/WorkerManager'
|
||||||
|
|
||||||
export class CommandAdapt {
|
export class CommandAdapt {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private range: RangeManager
|
private range: RangeManager
|
||||||
private position: Position
|
private position: Position
|
||||||
@@ -103,11 +121,19 @@ export class CommandAdapt {
|
|||||||
const { startIndex, endIndex } = this.range.getRange()
|
const { startIndex, endIndex } = this.range.getRange()
|
||||||
const isCollapsed = startIndex === endIndex
|
const isCollapsed = startIndex === endIndex
|
||||||
// 首字符禁止删除
|
// 首字符禁止删除
|
||||||
if (isCollapsed && elementList[startIndex].value === ZERO && startIndex === 0) {
|
if (
|
||||||
|
isCollapsed &&
|
||||||
|
elementList[startIndex].value === ZERO &&
|
||||||
|
startIndex === 0
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!isCollapsed) {
|
if (!isCollapsed) {
|
||||||
this.draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
this.draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
startIndex + 1,
|
||||||
|
endIndex - startIndex
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
this.draw.spliceElementList(elementList, startIndex, 1)
|
this.draw.spliceElementList(elementList, startIndex, 1)
|
||||||
}
|
}
|
||||||
@@ -198,7 +224,12 @@ export class CommandAdapt {
|
|||||||
if (!selection || !selection.length) return
|
if (!selection || !selection.length) return
|
||||||
let isExistUpdate = false
|
let isExistUpdate = false
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
if ((!el.size && payload === defaultSize) || (el.size && el.size === payload)) return
|
if (
|
||||||
|
(!el.size && payload === defaultSize) ||
|
||||||
|
(el.size && el.size === payload)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
el.size = payload
|
el.size = payload
|
||||||
isExistUpdate = true
|
isExistUpdate = true
|
||||||
})
|
})
|
||||||
@@ -310,7 +341,9 @@ export class CommandAdapt {
|
|||||||
if (activeControl) return
|
if (activeControl) return
|
||||||
const selection = this.range.getSelection()
|
const selection = this.range.getSelection()
|
||||||
if (!selection) return
|
if (!selection) return
|
||||||
const superscriptIndex = selection.findIndex(s => s.type === ElementType.SUPERSCRIPT)
|
const superscriptIndex = selection.findIndex(
|
||||||
|
s => s.type === ElementType.SUPERSCRIPT
|
||||||
|
)
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
// 取消上标
|
// 取消上标
|
||||||
if (~superscriptIndex) {
|
if (~superscriptIndex) {
|
||||||
@@ -320,7 +353,11 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 设置上标
|
// 设置上标
|
||||||
if (!el.type || el.type === ElementType.TEXT || el.type === ElementType.SUBSCRIPT) {
|
if (
|
||||||
|
!el.type ||
|
||||||
|
el.type === ElementType.TEXT ||
|
||||||
|
el.type === ElementType.SUBSCRIPT
|
||||||
|
) {
|
||||||
el.type = ElementType.SUPERSCRIPT
|
el.type = ElementType.SUPERSCRIPT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,7 +372,9 @@ export class CommandAdapt {
|
|||||||
if (activeControl) return
|
if (activeControl) return
|
||||||
const selection = this.range.getSelection()
|
const selection = this.range.getSelection()
|
||||||
if (!selection) return
|
if (!selection) return
|
||||||
const subscriptIndex = selection.findIndex(s => s.type === ElementType.SUBSCRIPT)
|
const subscriptIndex = selection.findIndex(
|
||||||
|
s => s.type === ElementType.SUBSCRIPT
|
||||||
|
)
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
// 取消下标
|
// 取消下标
|
||||||
if (~subscriptIndex) {
|
if (~subscriptIndex) {
|
||||||
@@ -345,7 +384,11 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 设置下标
|
// 设置下标
|
||||||
if (!el.type || el.type === ElementType.TEXT || el.type === ElementType.SUPERSCRIPT) {
|
if (
|
||||||
|
!el.type ||
|
||||||
|
el.type === ElementType.TEXT ||
|
||||||
|
el.type === ElementType.SUPERSCRIPT
|
||||||
|
) {
|
||||||
el.type = ElementType.SUBSCRIPT
|
el.type = ElementType.SUBSCRIPT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,9 +431,10 @@ export class CommandAdapt {
|
|||||||
if (!~startIndex && !~endIndex) return
|
if (!~startIndex && !~endIndex) return
|
||||||
const elementList = this.draw.getElementList()
|
const elementList = this.draw.getElementList()
|
||||||
// 需要改变的元素列表
|
// 需要改变的元素列表
|
||||||
const changeElementList = startIndex === endIndex
|
const changeElementList =
|
||||||
? this.range.getRangeElementList()
|
startIndex === endIndex
|
||||||
: elementList.slice(startIndex + 1, endIndex + 1)
|
? this.range.getRangeElementList()
|
||||||
|
: elementList.slice(startIndex + 1, endIndex + 1)
|
||||||
if (!changeElementList || !changeElementList.length) return
|
if (!changeElementList || !changeElementList.length) return
|
||||||
// 设置值
|
// 设置值
|
||||||
const titleId = getUUID()
|
const titleId = getUUID()
|
||||||
@@ -428,7 +472,9 @@ export class CommandAdapt {
|
|||||||
const changeElementList = this.range.getRangeElementList()
|
const changeElementList = this.range.getRangeElementList()
|
||||||
if (!changeElementList || !changeElementList.length) return
|
if (!changeElementList || !changeElementList.length) return
|
||||||
// 如果包含列表则设置为取消列表
|
// 如果包含列表则设置为取消列表
|
||||||
const isUnsetList = changeElementList.find(el => el.listType === listType && el.listStyle === listStyle)
|
const isUnsetList = changeElementList.find(
|
||||||
|
el => el.listType === listType && el.listStyle === listStyle
|
||||||
|
)
|
||||||
// 设置值
|
// 设置值
|
||||||
const listId = getUUID()
|
const listId = getUUID()
|
||||||
changeElementList.forEach(el => {
|
changeElementList.forEach(el => {
|
||||||
@@ -601,13 +647,15 @@ export class CommandAdapt {
|
|||||||
id: newTdId,
|
id: newTdId,
|
||||||
rowspan: 1,
|
rowspan: 1,
|
||||||
colspan: curTd.colspan,
|
colspan: curTd.colspan,
|
||||||
value: [{
|
value: [
|
||||||
value: ZERO,
|
{
|
||||||
size: 16,
|
value: ZERO,
|
||||||
tableId,
|
size: 16,
|
||||||
trId: newTrId,
|
tableId,
|
||||||
tdId: newTdId
|
trId: newTrId,
|
||||||
}]
|
tdId: newTdId
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
curTrList.splice(trIndex!, 0, newTr)
|
curTrList.splice(trIndex!, 0, newTr)
|
||||||
@@ -637,9 +685,8 @@ export class CommandAdapt {
|
|||||||
const element = originalElementList[index!]
|
const element = originalElementList[index!]
|
||||||
const curTrList = element.trList!
|
const curTrList = element.trList!
|
||||||
const curTr = curTrList[trIndex!]
|
const curTr = curTrList[trIndex!]
|
||||||
const anchorTr = curTrList.length - 1 === trIndex
|
const anchorTr =
|
||||||
? curTr
|
curTrList.length - 1 === trIndex ? curTr : curTrList[trIndex! + 1]
|
||||||
: curTrList[trIndex! + 1]
|
|
||||||
// 之前/当前行跨行的增加跨行数
|
// 之前/当前行跨行的增加跨行数
|
||||||
if (anchorTr.tdList.length < element.colgroup!.length) {
|
if (anchorTr.tdList.length < element.colgroup!.length) {
|
||||||
const curTrNo = anchorTr.tdList[0].rowIndex!
|
const curTrNo = anchorTr.tdList[0].rowIndex!
|
||||||
@@ -667,13 +714,15 @@ export class CommandAdapt {
|
|||||||
id: newTdId,
|
id: newTdId,
|
||||||
rowspan: 1,
|
rowspan: 1,
|
||||||
colspan: curTd.colspan,
|
colspan: curTd.colspan,
|
||||||
value: [{
|
value: [
|
||||||
value: ZERO,
|
{
|
||||||
size: 16,
|
value: ZERO,
|
||||||
tableId,
|
size: 16,
|
||||||
trId: newTrId,
|
tableId,
|
||||||
tdId: newTdId
|
trId: newTrId,
|
||||||
}]
|
tdId: newTdId
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
curTrList.splice(trIndex! + 1, 0, newTr)
|
curTrList.splice(trIndex! + 1, 0, newTr)
|
||||||
@@ -711,13 +760,15 @@ export class CommandAdapt {
|
|||||||
id: tdId,
|
id: tdId,
|
||||||
rowspan: 1,
|
rowspan: 1,
|
||||||
colspan: 1,
|
colspan: 1,
|
||||||
value: [{
|
value: [
|
||||||
value: ZERO,
|
{
|
||||||
size: 16,
|
value: ZERO,
|
||||||
tableId,
|
size: 16,
|
||||||
trId: tr.id,
|
tableId,
|
||||||
tdId
|
trId: tr.id,
|
||||||
}]
|
tdId
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 重新计算宽度
|
// 重新计算宽度
|
||||||
@@ -768,13 +819,15 @@ export class CommandAdapt {
|
|||||||
id: tdId,
|
id: tdId,
|
||||||
rowspan: 1,
|
rowspan: 1,
|
||||||
colspan: 1,
|
colspan: 1,
|
||||||
value: [{
|
value: [
|
||||||
value: ZERO,
|
{
|
||||||
size: 16,
|
value: ZERO,
|
||||||
tableId,
|
size: 16,
|
||||||
trId: tr.id,
|
tableId,
|
||||||
tdId
|
trId: tr.id,
|
||||||
}]
|
tdId
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 重新计算宽度
|
// 重新计算宽度
|
||||||
@@ -834,13 +887,15 @@ export class CommandAdapt {
|
|||||||
id: tdId,
|
id: tdId,
|
||||||
rowspan: 1,
|
rowspan: 1,
|
||||||
colspan: 1,
|
colspan: 1,
|
||||||
value: [{
|
value: [
|
||||||
value: ZERO,
|
{
|
||||||
size: 16,
|
value: ZERO,
|
||||||
tableId: element.id,
|
size: 16,
|
||||||
trId: tr.id,
|
tableId: element.id,
|
||||||
tdId
|
trId: tr.id,
|
||||||
}]
|
tdId
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
start += 1
|
start += 1
|
||||||
}
|
}
|
||||||
@@ -885,7 +940,10 @@ export class CommandAdapt {
|
|||||||
if (td.colspan > 1) {
|
if (td.colspan > 1) {
|
||||||
const tdColIndex = td.colIndex!
|
const tdColIndex = td.colIndex!
|
||||||
// 交叉减去一列
|
// 交叉减去一列
|
||||||
if (tdColIndex <= curColIndex && tdColIndex + td.colspan - 1 >= curColIndex) {
|
if (
|
||||||
|
tdColIndex <= curColIndex &&
|
||||||
|
tdColIndex + td.colspan - 1 >= curColIndex
|
||||||
|
) {
|
||||||
td.colspan -= 1
|
td.colspan -= 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -940,7 +998,13 @@ export class CommandAdapt {
|
|||||||
if (isReadonly) return
|
if (isReadonly) return
|
||||||
const positionContext = this.position.getPositionContext()
|
const positionContext = this.position.getPositionContext()
|
||||||
if (!positionContext.isTable) return
|
if (!positionContext.isTable) return
|
||||||
const { isCrossRowCol, startTdIndex, endTdIndex, startTrIndex, endTrIndex } = this.range.getRange()
|
const {
|
||||||
|
isCrossRowCol,
|
||||||
|
startTdIndex,
|
||||||
|
endTdIndex,
|
||||||
|
startTrIndex,
|
||||||
|
endTrIndex
|
||||||
|
} = this.range.getRange()
|
||||||
if (!isCrossRowCol) return
|
if (!isCrossRowCol) return
|
||||||
const { index } = positionContext
|
const { index } = positionContext
|
||||||
const originalElementList = this.draw.getOriginalElementList()
|
const originalElementList = this.draw.getOriginalElementList()
|
||||||
@@ -966,8 +1030,10 @@ export class CommandAdapt {
|
|||||||
const tdColIndex = td.colIndex!
|
const tdColIndex = td.colIndex!
|
||||||
const tdRowIndex = td.rowIndex!
|
const tdRowIndex = td.rowIndex!
|
||||||
if (
|
if (
|
||||||
tdColIndex >= startColIndex && tdColIndex <= endColIndex
|
tdColIndex >= startColIndex &&
|
||||||
&& tdRowIndex >= startRowIndex && tdRowIndex <= endRowIndex
|
tdColIndex <= endColIndex &&
|
||||||
|
tdRowIndex >= startRowIndex &&
|
||||||
|
tdRowIndex <= endRowIndex
|
||||||
) {
|
) {
|
||||||
tdList.push(td)
|
tdList.push(td)
|
||||||
}
|
}
|
||||||
@@ -994,7 +1060,12 @@ export class CommandAdapt {
|
|||||||
const tdEndX = tdStartX + td.width!
|
const tdEndX = tdStartX + td.width!
|
||||||
const tdEndY = tdStartY + td.height!
|
const tdEndY = tdStartY + td.height!
|
||||||
// 存在不符合项
|
// 存在不符合项
|
||||||
if (startX > tdStartX || startY > tdStartY || endX < tdEndX || endY < tdEndY) {
|
if (
|
||||||
|
startX > tdStartX ||
|
||||||
|
startY > tdStartY ||
|
||||||
|
endX < tdEndX ||
|
||||||
|
endY < tdEndY
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1064,13 +1135,15 @@ export class CommandAdapt {
|
|||||||
id: tdId,
|
id: tdId,
|
||||||
rowspan: 1,
|
rowspan: 1,
|
||||||
colspan: 1,
|
colspan: 1,
|
||||||
value: [{
|
value: [
|
||||||
value: ZERO,
|
{
|
||||||
size: 16,
|
value: ZERO,
|
||||||
tableId: element.id,
|
size: 16,
|
||||||
trId: curTr.id,
|
tableId: element.id,
|
||||||
tdId
|
trId: curTr.id,
|
||||||
}]
|
tdId
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
curTd.colspan = 1
|
curTd.colspan = 1
|
||||||
@@ -1085,13 +1158,15 @@ export class CommandAdapt {
|
|||||||
id: tdId,
|
id: tdId,
|
||||||
rowspan: 1,
|
rowspan: 1,
|
||||||
colspan: 1,
|
colspan: 1,
|
||||||
value: [{
|
value: [
|
||||||
value: ZERO,
|
{
|
||||||
size: 16,
|
value: ZERO,
|
||||||
tableId: element.id,
|
size: 16,
|
||||||
trId: tr.id,
|
tableId: element.id,
|
||||||
tdId
|
trId: tr.id,
|
||||||
}]
|
tdId
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1241,7 +1316,11 @@ export class CommandAdapt {
|
|||||||
const elementList = this.draw.getElementList()
|
const elementList = this.draw.getElementList()
|
||||||
const [leftIndex, rightIndex] = hyperRange
|
const [leftIndex, rightIndex] = hyperRange
|
||||||
// 删除元素
|
// 删除元素
|
||||||
this.draw.spliceElementList(elementList, leftIndex, rightIndex - leftIndex + 1)
|
this.draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
leftIndex,
|
||||||
|
rightIndex - leftIndex + 1
|
||||||
|
)
|
||||||
this.draw.getHyperlinkParticle().clearHyperlinkPopup()
|
this.draw.getHyperlinkParticle().clearHyperlinkPopup()
|
||||||
// 重置画布
|
// 重置画布
|
||||||
const newIndex = leftIndex - 1
|
const newIndex = leftIndex - 1
|
||||||
@@ -1306,7 +1385,12 @@ export class CommandAdapt {
|
|||||||
// 光标存在分割线,则判断为修改线段逻辑
|
// 光标存在分割线,则判断为修改线段逻辑
|
||||||
const endElement = elementList[endIndex + 1]
|
const endElement = elementList[endIndex + 1]
|
||||||
if (endElement && endElement.type === ElementType.SEPARATOR) {
|
if (endElement && endElement.type === ElementType.SEPARATOR) {
|
||||||
if (endElement.dashArray && endElement.dashArray.join() === payload.join()) return
|
if (
|
||||||
|
endElement.dashArray &&
|
||||||
|
endElement.dashArray.join() === payload.join()
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
curIndex = endIndex
|
curIndex = endIndex
|
||||||
endElement.dashArray = payload
|
endElement.dashArray = payload
|
||||||
} else {
|
} else {
|
||||||
@@ -1334,10 +1418,12 @@ export class CommandAdapt {
|
|||||||
if (isReadonly) return
|
if (isReadonly) return
|
||||||
const activeControl = this.control.getActiveControl()
|
const activeControl = this.control.getActiveControl()
|
||||||
if (activeControl) return
|
if (activeControl) return
|
||||||
this.insertElementList([{
|
this.insertElementList([
|
||||||
type: ElementType.PAGE_BREAK,
|
{
|
||||||
value: WRAP
|
type: ElementType.PAGE_BREAK,
|
||||||
}])
|
value: WRAP
|
||||||
|
}
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
public addWatermark(payload: IWatermark) {
|
public addWatermark(payload: IWatermark) {
|
||||||
@@ -1458,7 +1544,8 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
curTdId = tdId!
|
curTdId = tdId!
|
||||||
const curTableIndex = tableIndex! + pageDiffCount
|
const curTableIndex = tableIndex! + pageDiffCount
|
||||||
const tableElementList = elementList[curTableIndex].trList![trIndex!].tdList[tdIndex!].value
|
const tableElementList =
|
||||||
|
elementList[curTableIndex].trList![trIndex!].tdList[tdIndex!].value
|
||||||
// 表格内元素
|
// 表格内元素
|
||||||
const curIndex = index + tableDiffCount
|
const curIndex = index + tableDiffCount
|
||||||
const tableElement = tableElementList[curIndex]
|
const tableElement = tableElementList[curIndex]
|
||||||
@@ -1483,8 +1570,8 @@ export class CommandAdapt {
|
|||||||
const curIndex = match.index + pageDiffCount
|
const curIndex = match.index + pageDiffCount
|
||||||
const element = elementList[curIndex]
|
const element = elementList[curIndex]
|
||||||
if (
|
if (
|
||||||
element.type === ElementType.CONTROL
|
element.type === ElementType.CONTROL &&
|
||||||
&& element.controlComponent !== ControlComponent.VALUE
|
element.controlComponent !== ControlComponent.VALUE
|
||||||
) {
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1517,7 +1604,8 @@ export class CommandAdapt {
|
|||||||
const firstIndex = firstMatch.index + (payload.length - 1)
|
const firstIndex = firstMatch.index + (payload.length - 1)
|
||||||
if (firstMatch.type === EditorContext.TABLE) {
|
if (firstMatch.type === EditorContext.TABLE) {
|
||||||
const { tableIndex, trIndex, tdIndex, index } = firstMatch
|
const { tableIndex, trIndex, tdIndex, index } = firstMatch
|
||||||
const element = elementList[tableIndex!].trList![trIndex!].tdList[tdIndex!].value[index]
|
const element =
|
||||||
|
elementList[tableIndex!].trList![trIndex!].tdList[tdIndex!].value[index]
|
||||||
this.position.setPositionContext({
|
this.position.setPositionContext({
|
||||||
isTable: true,
|
isTable: true,
|
||||||
index: tableIndex,
|
index: tableIndex,
|
||||||
@@ -1607,7 +1695,9 @@ export class CommandAdapt {
|
|||||||
const isCollapsed = startIndex === endIndex
|
const isCollapsed = startIndex === endIndex
|
||||||
// 元素信息
|
// 元素信息
|
||||||
const elementList = this.draw.getElementList()
|
const elementList = this.draw.getElementList()
|
||||||
const startElement = pickElementAttr(elementList[isCollapsed ? startIndex : startIndex + 1])
|
const startElement = pickElementAttr(
|
||||||
|
elementList[isCollapsed ? startIndex : startIndex + 1]
|
||||||
|
)
|
||||||
const endElement = pickElementAttr(elementList[endIndex])
|
const endElement = pickElementAttr(elementList[endIndex])
|
||||||
// 页码信息
|
// 页码信息
|
||||||
const positionList = this.position.getPositionList()
|
const positionList = this.position.getPositionList()
|
||||||
@@ -1676,7 +1766,10 @@ export class CommandAdapt {
|
|||||||
this.draw.insertElementList(payload)
|
this.draw.insertElementList(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
public appendElementList(elementList: IElement[], options?: IAppendElementListOption) {
|
public appendElementList(
|
||||||
|
elementList: IElement[],
|
||||||
|
options?: IAppendElementListOption
|
||||||
|
) {
|
||||||
if (!elementList.length) return
|
if (!elementList.length) return
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
if (isReadonly) return
|
if (isReadonly) return
|
||||||
@@ -1716,7 +1809,10 @@ export class CommandAdapt {
|
|||||||
let newIndex = -1
|
let newIndex = -1
|
||||||
for (let e = 0; e < elementList.length; e++) {
|
for (let e = 0; e < elementList.length; e++) {
|
||||||
const element = elementList[e]
|
const element = elementList[e]
|
||||||
if (element.titleId === titleId && elementList[e + 1]?.titleId !== titleId) {
|
if (
|
||||||
|
element.titleId === titleId &&
|
||||||
|
elementList[e + 1]?.titleId !== titleId
|
||||||
|
) {
|
||||||
newIndex = e
|
newIndex = e
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -1757,5 +1853,4 @@ export class CommandAdapt {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { NAME_PLACEHOLDER } from '../../dataset/constant/ContextMenu'
|
import { NAME_PLACEHOLDER } from '../../dataset/constant/ContextMenu'
|
||||||
import { EDITOR_COMPONENT, EDITOR_PREFIX } from '../../dataset/constant/Editor'
|
import { EDITOR_COMPONENT, EDITOR_PREFIX } from '../../dataset/constant/Editor'
|
||||||
import { EditorComponent } from '../../dataset/enum/Editor'
|
import { EditorComponent } from '../../dataset/enum/Editor'
|
||||||
import { IContextMenuContext, IRegisterContextMenu } from '../../interface/contextmenu/ContextMenu'
|
import {
|
||||||
|
IContextMenuContext,
|
||||||
|
IRegisterContextMenu
|
||||||
|
} from '../../interface/contextmenu/ContextMenu'
|
||||||
import { findParent } from '../../utils'
|
import { findParent } from '../../utils'
|
||||||
import { Command } from '../command/Command'
|
import { Command } from '../command/Command'
|
||||||
import { Draw } from '../draw/Draw'
|
import { Draw } from '../draw/Draw'
|
||||||
@@ -15,14 +18,13 @@ import { imageMenus } from './menus/imageMenus'
|
|||||||
import { tableMenus } from './menus/tableMenus'
|
import { tableMenus } from './menus/tableMenus'
|
||||||
|
|
||||||
interface IRenderPayload {
|
interface IRenderPayload {
|
||||||
contextMenuList: IRegisterContextMenu[];
|
contextMenuList: IRegisterContextMenu[]
|
||||||
left: number;
|
left: number
|
||||||
top: number;
|
top: number
|
||||||
parentMenuContainer?: HTMLDivElement;
|
parentMenuContainer?: HTMLDivElement
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ContextMenu {
|
export class ContextMenu {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private command: Command
|
private command: Command
|
||||||
private range: RangeManager
|
private range: RangeManager
|
||||||
@@ -63,7 +65,10 @@ export class ContextMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public removeEvent() {
|
public removeEvent() {
|
||||||
this.container.removeEventListener('contextmenu', this._proxyContextMenuEvent)
|
this.container.removeEventListener(
|
||||||
|
'contextmenu',
|
||||||
|
this._proxyContextMenuEvent
|
||||||
|
)
|
||||||
document.removeEventListener('mousedown', this._handleEffect)
|
document.removeEventListener('mousedown', this._handleEffect)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +93,7 @@ export class ContextMenu {
|
|||||||
this._render({
|
this._render({
|
||||||
contextMenuList: renderList,
|
contextMenuList: renderList,
|
||||||
left: evt.x,
|
left: evt.x,
|
||||||
top: evt.y,
|
top: evt.y
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
@@ -99,8 +104,10 @@ export class ContextMenu {
|
|||||||
// 点击非右键菜单内
|
// 点击非右键菜单内
|
||||||
const contextMenuDom = findParent(
|
const contextMenuDom = findParent(
|
||||||
evt.target as Element,
|
evt.target as Element,
|
||||||
(node: Node & Element) => !!node && node.nodeType === 1
|
(node: Node & Element) =>
|
||||||
&& node.getAttribute(EDITOR_COMPONENT) === EditorComponent.CONTEXTMENU,
|
!!node &&
|
||||||
|
node.nodeType === 1 &&
|
||||||
|
node.getAttribute(EDITOR_COMPONENT) === EditorComponent.CONTEXTMENU,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
if (!contextMenuDom) {
|
if (!contextMenuDom) {
|
||||||
@@ -112,7 +119,11 @@ export class ContextMenu {
|
|||||||
private _getContext(): IContextMenuContext {
|
private _getContext(): IContextMenuContext {
|
||||||
// 是否是只读模式
|
// 是否是只读模式
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
const { isCrossRowCol: crossRowCol, startIndex, endIndex } = this.range.getRange()
|
const {
|
||||||
|
isCrossRowCol: crossRowCol,
|
||||||
|
startIndex,
|
||||||
|
endIndex
|
||||||
|
} = this.range.getRange()
|
||||||
// 是否存在焦点
|
// 是否存在焦点
|
||||||
const editorTextFocus = !!(~startIndex || ~endIndex)
|
const editorTextFocus = !!(~startIndex || ~endIndex)
|
||||||
// 是否存在选区
|
// 是否存在选区
|
||||||
@@ -141,7 +152,10 @@ export class ContextMenu {
|
|||||||
private _createContextMenuContainer(): HTMLDivElement {
|
private _createContextMenuContainer(): HTMLDivElement {
|
||||||
const contextMenuContainer = document.createElement('div')
|
const contextMenuContainer = document.createElement('div')
|
||||||
contextMenuContainer.classList.add(`${EDITOR_PREFIX}-contextmenu-container`)
|
contextMenuContainer.classList.add(`${EDITOR_PREFIX}-contextmenu-container`)
|
||||||
contextMenuContainer.setAttribute(EDITOR_COMPONENT, EditorComponent.CONTEXTMENU)
|
contextMenuContainer.setAttribute(
|
||||||
|
EDITOR_COMPONENT,
|
||||||
|
EditorComponent.CONTEXTMENU
|
||||||
|
)
|
||||||
this.container.append(contextMenuContainer)
|
this.container.append(contextMenuContainer)
|
||||||
return contextMenuContainer
|
return contextMenuContainer
|
||||||
}
|
}
|
||||||
@@ -155,7 +169,10 @@ export class ContextMenu {
|
|||||||
let childMenuContainer: HTMLDivElement | null = null
|
let childMenuContainer: HTMLDivElement | null = null
|
||||||
// 父菜单添加子菜单映射关系
|
// 父菜单添加子菜单映射关系
|
||||||
if (parentMenuContainer) {
|
if (parentMenuContainer) {
|
||||||
this.contextMenuRelationShip.set(parentMenuContainer, contextMenuContainer)
|
this.contextMenuRelationShip.set(
|
||||||
|
parentMenuContainer,
|
||||||
|
contextMenuContainer
|
||||||
|
)
|
||||||
}
|
}
|
||||||
for (let c = 0; c < contextMenuList.length; c++) {
|
for (let c = 0; c < contextMenuList.length; c++) {
|
||||||
const menu = contextMenuList[c]
|
const menu = contextMenuList[c]
|
||||||
@@ -186,9 +203,12 @@ export class ContextMenu {
|
|||||||
parentMenuContainer: contextMenuContainer
|
parentMenuContainer: contextMenuContainer
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
menuItem.onmouseleave = (evt) => {
|
menuItem.onmouseleave = evt => {
|
||||||
// 移动到子菜单选项选中状态不变化
|
// 移动到子菜单选项选中状态不变化
|
||||||
if (!childMenuContainer || !childMenuContainer.contains(evt.relatedTarget as Node)) {
|
if (
|
||||||
|
!childMenuContainer ||
|
||||||
|
!childMenuContainer.contains(evt.relatedTarget as Node)
|
||||||
|
) {
|
||||||
this._setHoverStatus(menuItem, false)
|
this._setHoverStatus(menuItem, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,9 +255,8 @@ export class ContextMenu {
|
|||||||
const innerWidth = window.innerWidth
|
const innerWidth = window.innerWidth
|
||||||
const contextMenuWidth = contextMenuContainer.getBoundingClientRect().width
|
const contextMenuWidth = contextMenuContainer.getBoundingClientRect().width
|
||||||
// 右侧空间不足时,以菜单右上角作为起始点
|
// 右侧空间不足时,以菜单右上角作为起始点
|
||||||
const adjustLeft = left + contextMenuWidth > innerWidth
|
const adjustLeft =
|
||||||
? left - contextMenuWidth
|
left + contextMenuWidth > innerWidth ? left - contextMenuWidth : left
|
||||||
: left
|
|
||||||
contextMenuContainer.style.left = `${adjustLeft}px`
|
contextMenuContainer.style.left = `${adjustLeft}px`
|
||||||
contextMenuContainer.style.top = `${top}px`
|
contextMenuContainer.style.top = `${top}px`
|
||||||
this.contextMenuContainerList.push(contextMenuContainer)
|
this.contextMenuContainerList.push(contextMenuContainer)
|
||||||
@@ -255,7 +274,8 @@ export class ContextMenu {
|
|||||||
|
|
||||||
private _setHoverStatus(payload: HTMLDivElement, status: boolean) {
|
private _setHoverStatus(payload: HTMLDivElement, status: boolean) {
|
||||||
if (status) {
|
if (status) {
|
||||||
payload.parentNode?.querySelectorAll(`${EDITOR_PREFIX}-contextmenu-item`)
|
payload.parentNode
|
||||||
|
?.querySelectorAll(`${EDITOR_PREFIX}-contextmenu-item`)
|
||||||
.forEach(child => child.classList.remove('hover'))
|
.forEach(child => child.classList.remove('hover'))
|
||||||
payload.classList.add('hover')
|
payload.classList.add('hover')
|
||||||
} else {
|
} else {
|
||||||
@@ -287,5 +307,4 @@ export class ContextMenu {
|
|||||||
this.contextMenuContainerList = []
|
this.contextMenuContainerList = []
|
||||||
this.contextMenuRelationShip.clear()
|
this.contextMenuRelationShip.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,15 @@ import { Command } from '../../command/Command'
|
|||||||
export const controlMenus: IRegisterContextMenu[] = [
|
export const controlMenus: IRegisterContextMenu[] = [
|
||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.control.delete',
|
i18nPath: 'contextmenu.control.delete',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && !payload.editorHasSelection && payload.startElement?.type === ElementType.CONTROL
|
return (
|
||||||
|
!payload.isReadonly &&
|
||||||
|
!payload.editorHasSelection &&
|
||||||
|
payload.startElement?.type === ElementType.CONTROL
|
||||||
|
)
|
||||||
},
|
},
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
command.executeRemoveControl()
|
command.executeRemoveControl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const globalMenus: IRegisterContextMenu[] = [
|
|||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.global.cut',
|
i18nPath: 'contextmenu.global.cut',
|
||||||
shortCut: `${isApple ? '⌘' : 'Ctrl'} + X`,
|
shortCut: `${isApple ? '⌘' : 'Ctrl'} + X`,
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly
|
return !payload.isReadonly
|
||||||
},
|
},
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
@@ -16,7 +16,7 @@ export const globalMenus: IRegisterContextMenu[] = [
|
|||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.global.copy',
|
i18nPath: 'contextmenu.global.copy',
|
||||||
shortCut: `${isApple ? '⌘' : 'Ctrl'} + C`,
|
shortCut: `${isApple ? '⌘' : 'Ctrl'} + C`,
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return payload.editorHasSelection
|
return payload.editorHasSelection
|
||||||
},
|
},
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
@@ -26,7 +26,7 @@ export const globalMenus: IRegisterContextMenu[] = [
|
|||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.global.paste',
|
i18nPath: 'contextmenu.global.paste',
|
||||||
shortCut: `${isApple ? '⌘' : 'Ctrl'} + V`,
|
shortCut: `${isApple ? '⌘' : 'Ctrl'} + V`,
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && payload.editorTextFocus
|
return !payload.isReadonly && payload.editorTextFocus
|
||||||
},
|
},
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
@@ -36,7 +36,7 @@ export const globalMenus: IRegisterContextMenu[] = [
|
|||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.global.selectAll',
|
i18nPath: 'contextmenu.global.selectAll',
|
||||||
shortCut: `${isApple ? '⌘' : 'Ctrl'} + A`,
|
shortCut: `${isApple ? '⌘' : 'Ctrl'} + A`,
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return payload.editorTextFocus
|
return payload.editorTextFocus
|
||||||
},
|
},
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
@@ -54,4 +54,4 @@ export const globalMenus: IRegisterContextMenu[] = [
|
|||||||
command.executePrint()
|
command.executePrint()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
import { ElementType } from '../../../dataset/enum/Element'
|
import { ElementType } from '../../../dataset/enum/Element'
|
||||||
import { IContextMenuContext, IRegisterContextMenu } from '../../../interface/contextmenu/ContextMenu'
|
import {
|
||||||
|
IContextMenuContext,
|
||||||
|
IRegisterContextMenu
|
||||||
|
} from '../../../interface/contextmenu/ContextMenu'
|
||||||
import { Command } from '../../command/Command'
|
import { Command } from '../../command/Command'
|
||||||
|
|
||||||
export const hyperlinkMenus: IRegisterContextMenu[] = [
|
export const hyperlinkMenus: IRegisterContextMenu[] = [
|
||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.hyperlink.delete',
|
i18nPath: 'contextmenu.hyperlink.delete',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && payload.startElement?.type === ElementType.HYPERLINK
|
return (
|
||||||
|
!payload.isReadonly &&
|
||||||
|
payload.startElement?.type === ElementType.HYPERLINK
|
||||||
|
)
|
||||||
},
|
},
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
command.executeDeleteHyperlink()
|
command.executeDeleteHyperlink()
|
||||||
@@ -14,8 +20,11 @@ export const hyperlinkMenus: IRegisterContextMenu[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.hyperlink.cancel',
|
i18nPath: 'contextmenu.hyperlink.cancel',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && payload.startElement?.type === ElementType.HYPERLINK
|
return (
|
||||||
|
!payload.isReadonly &&
|
||||||
|
payload.startElement?.type === ElementType.HYPERLINK
|
||||||
|
)
|
||||||
},
|
},
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
command.executeCancelHyperlink()
|
command.executeCancelHyperlink()
|
||||||
@@ -23,8 +32,11 @@ export const hyperlinkMenus: IRegisterContextMenu[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.hyperlink.edit',
|
i18nPath: 'contextmenu.hyperlink.edit',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && payload.startElement?.type === ElementType.HYPERLINK
|
return (
|
||||||
|
!payload.isReadonly &&
|
||||||
|
payload.startElement?.type === ElementType.HYPERLINK
|
||||||
|
)
|
||||||
},
|
},
|
||||||
callback: (command: Command, context: IContextMenuContext) => {
|
callback: (command: Command, context: IContextMenuContext) => {
|
||||||
const url = window.prompt('编辑链接', context.startElement?.url)
|
const url = window.prompt('编辑链接', context.startElement?.url)
|
||||||
@@ -33,4 +45,4 @@ export const hyperlinkMenus: IRegisterContextMenu[] = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,14 +1,21 @@
|
|||||||
import { ImageDisplay } from '../../../dataset/enum/Control'
|
import { ImageDisplay } from '../../../dataset/enum/Control'
|
||||||
import { ElementType } from '../../../dataset/enum/Element'
|
import { ElementType } from '../../../dataset/enum/Element'
|
||||||
import { IContextMenuContext, IRegisterContextMenu } from '../../../interface/contextmenu/ContextMenu'
|
import {
|
||||||
|
IContextMenuContext,
|
||||||
|
IRegisterContextMenu
|
||||||
|
} from '../../../interface/contextmenu/ContextMenu'
|
||||||
import { Command } from '../../command/Command'
|
import { Command } from '../../command/Command'
|
||||||
|
|
||||||
export const imageMenus: IRegisterContextMenu[] = [
|
export const imageMenus: IRegisterContextMenu[] = [
|
||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.image.change',
|
i18nPath: 'contextmenu.image.change',
|
||||||
icon: 'image-change',
|
icon: 'image-change',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && !payload.editorHasSelection && payload.startElement?.type === ElementType.IMAGE
|
return (
|
||||||
|
!payload.isReadonly &&
|
||||||
|
!payload.editorHasSelection &&
|
||||||
|
payload.startElement?.type === ElementType.IMAGE
|
||||||
|
)
|
||||||
},
|
},
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
// 创建代理元素
|
// 创建代理元素
|
||||||
@@ -31,8 +38,11 @@ export const imageMenus: IRegisterContextMenu[] = [
|
|||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.image.saveAs',
|
i18nPath: 'contextmenu.image.saveAs',
|
||||||
icon: 'image',
|
icon: 'image',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.editorHasSelection && payload.startElement?.type === ElementType.IMAGE
|
return (
|
||||||
|
!payload.editorHasSelection &&
|
||||||
|
payload.startElement?.type === ElementType.IMAGE
|
||||||
|
)
|
||||||
},
|
},
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
command.executeSaveAsImageElement()
|
command.executeSaveAsImageElement()
|
||||||
@@ -40,25 +50,34 @@ export const imageMenus: IRegisterContextMenu[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.image.textWrap',
|
i18nPath: 'contextmenu.image.textWrap',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && !payload.editorHasSelection && payload.startElement?.type === ElementType.IMAGE
|
return (
|
||||||
|
!payload.isReadonly &&
|
||||||
|
!payload.editorHasSelection &&
|
||||||
|
payload.startElement?.type === ElementType.IMAGE
|
||||||
|
)
|
||||||
},
|
},
|
||||||
childMenus: [
|
childMenus: [
|
||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.image.textWrapType.embed',
|
i18nPath: 'contextmenu.image.textWrapType.embed',
|
||||||
when: () => true,
|
when: () => true,
|
||||||
callback: (command: Command, context: IContextMenuContext) => {
|
callback: (command: Command, context: IContextMenuContext) => {
|
||||||
command.executeChangeImageDisplay(context.startElement!, ImageDisplay.BLOCK)
|
command.executeChangeImageDisplay(
|
||||||
|
context.startElement!,
|
||||||
|
ImageDisplay.BLOCK
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.image.textWrapType.upDown',
|
i18nPath: 'contextmenu.image.textWrapType.upDown',
|
||||||
when: () => true,
|
when: () => true,
|
||||||
callback: (command: Command, context: IContextMenuContext) => {
|
callback: (command: Command, context: IContextMenuContext) => {
|
||||||
command.executeChangeImageDisplay(context.startElement!, ImageDisplay.INLINE)
|
command.executeChangeImageDisplay(
|
||||||
|
context.startElement!,
|
||||||
|
ImageDisplay.INLINE
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const tableMenus: IRegisterContextMenu[] = [
|
|||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.table.border',
|
i18nPath: 'contextmenu.table.border',
|
||||||
icon: 'border-all',
|
icon: 'border-all',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && payload.isInTable
|
return !payload.isReadonly && payload.isInTable
|
||||||
},
|
},
|
||||||
childMenus: [
|
childMenus: [
|
||||||
@@ -43,7 +43,7 @@ export const tableMenus: IRegisterContextMenu[] = [
|
|||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.table.verticalAlign',
|
i18nPath: 'contextmenu.table.verticalAlign',
|
||||||
icon: 'vertical-align',
|
icon: 'vertical-align',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && payload.isInTable
|
return !payload.isReadonly && payload.isInTable
|
||||||
},
|
},
|
||||||
childMenus: [
|
childMenus: [
|
||||||
@@ -76,7 +76,7 @@ export const tableMenus: IRegisterContextMenu[] = [
|
|||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.table.insertRowCol',
|
i18nPath: 'contextmenu.table.insertRowCol',
|
||||||
icon: 'insert-row-col',
|
icon: 'insert-row-col',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && payload.isInTable
|
return !payload.isReadonly && payload.isInTable
|
||||||
},
|
},
|
||||||
childMenus: [
|
childMenus: [
|
||||||
@@ -117,7 +117,7 @@ export const tableMenus: IRegisterContextMenu[] = [
|
|||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.table.deleteRowCol',
|
i18nPath: 'contextmenu.table.deleteRowCol',
|
||||||
icon: 'delete-row-col',
|
icon: 'delete-row-col',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && payload.isInTable
|
return !payload.isReadonly && payload.isInTable
|
||||||
},
|
},
|
||||||
childMenus: [
|
childMenus: [
|
||||||
@@ -150,7 +150,7 @@ export const tableMenus: IRegisterContextMenu[] = [
|
|||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.table.mergeCell',
|
i18nPath: 'contextmenu.table.mergeCell',
|
||||||
icon: 'merge-cell',
|
icon: 'merge-cell',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && payload.isCrossRowCol
|
return !payload.isReadonly && payload.isCrossRowCol
|
||||||
},
|
},
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
@@ -160,11 +160,11 @@ export const tableMenus: IRegisterContextMenu[] = [
|
|||||||
{
|
{
|
||||||
i18nPath: 'contextmenu.table.mergeCancelCell',
|
i18nPath: 'contextmenu.table.mergeCancelCell',
|
||||||
icon: 'merge-cancel-cell',
|
icon: 'merge-cancel-cell',
|
||||||
when: (payload) => {
|
when: payload => {
|
||||||
return !payload.isReadonly && payload.isInTable
|
return !payload.isReadonly && payload.isInTable
|
||||||
},
|
},
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
command.executeCancelMergeTableCell()
|
command.executeCancelMergeTableCell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,15 +8,13 @@ import { CanvasEvent } from '../event/CanvasEvent'
|
|||||||
import { Position } from '../position/Position'
|
import { Position } from '../position/Position'
|
||||||
import { CursorAgent } from './CursorAgent'
|
import { CursorAgent } from './CursorAgent'
|
||||||
|
|
||||||
export type IDrawCursorOption = ICursorOption &
|
export type IDrawCursorOption = ICursorOption & {
|
||||||
{
|
isShow?: boolean
|
||||||
isShow?: boolean;
|
isBlink?: boolean
|
||||||
isBlink?: boolean;
|
isFocus?: boolean
|
||||||
isFocus?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Cursor {
|
export class Cursor {
|
||||||
|
|
||||||
private readonly ANIMATION_CLASS = `${EDITOR_PREFIX}-cursor--animation`
|
private readonly ANIMATION_CLASS = `${EDITOR_PREFIX}-cursor--animation`
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
@@ -56,8 +54,8 @@ export class Cursor {
|
|||||||
return this.getAgentDom().value
|
return this.getAgentDom().value
|
||||||
}
|
}
|
||||||
|
|
||||||
public clearAgentDomValue(): string {
|
public clearAgentDomValue() {
|
||||||
return this.getAgentDom().value = ''
|
this.getAgentDom().value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
private _blinkStart() {
|
private _blinkStart() {
|
||||||
@@ -97,9 +95,16 @@ export class Cursor {
|
|||||||
// 设置光标代理
|
// 设置光标代理
|
||||||
const height = this.draw.getHeight()
|
const height = this.draw.getHeight()
|
||||||
const pageGap = this.draw.getPageGap()
|
const pageGap = this.draw.getPageGap()
|
||||||
const { metrics, coordinate: { leftTop, rightTop }, ascent, pageNo } = cursorPosition
|
const {
|
||||||
|
metrics,
|
||||||
|
coordinate: { leftTop, rightTop },
|
||||||
|
ascent,
|
||||||
|
pageNo
|
||||||
|
} = cursorPosition
|
||||||
const zoneManager = this.draw.getZone()
|
const zoneManager = this.draw.getZone()
|
||||||
const curPageNo = zoneManager.isMainActive() ? pageNo : this.draw.getPageNo()
|
const curPageNo = zoneManager.isMainActive()
|
||||||
|
? pageNo
|
||||||
|
: this.draw.getPageNo()
|
||||||
const preY = curPageNo * (height + pageGap)
|
const preY = curPageNo * (height + pageGap)
|
||||||
// 增加1/4字体大小
|
// 增加1/4字体大小
|
||||||
const offsetHeight = metrics.height / 4
|
const offsetHeight = metrics.height / 4
|
||||||
@@ -112,11 +117,15 @@ export class Cursor {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
// fillText位置 + 文字基线到底部距离 - 模拟光标偏移量
|
// fillText位置 + 文字基线到底部距离 - 模拟光标偏移量
|
||||||
const descent = metrics.boundingBoxDescent < 0 ? 0 : metrics.boundingBoxDescent
|
const descent =
|
||||||
const cursorTop = (leftTop[1] + ascent) + descent - (cursorHeight - offsetHeight) + preY
|
metrics.boundingBoxDescent < 0 ? 0 : metrics.boundingBoxDescent
|
||||||
|
const cursorTop =
|
||||||
|
leftTop[1] + ascent + descent - (cursorHeight - offsetHeight) + preY
|
||||||
const cursorLeft = rightTop[0]
|
const cursorLeft = rightTop[0]
|
||||||
agentCursorDom.style.left = `${cursorLeft}px`
|
agentCursorDom.style.left = `${cursorLeft}px`
|
||||||
agentCursorDom.style.top = `${cursorTop + cursorHeight - CURSOR_AGENT_HEIGHT * scale}px`
|
agentCursorDom.style.top = `${
|
||||||
|
cursorTop + cursorHeight - CURSOR_AGENT_HEIGHT * scale
|
||||||
|
}px`
|
||||||
// 模拟光标显示
|
// 模拟光标显示
|
||||||
if (!isShow) return
|
if (!isShow) return
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
@@ -137,5 +146,4 @@ export class Cursor {
|
|||||||
this.cursorDom.style.display = 'none'
|
this.cursorDom.style.display = 'none'
|
||||||
this._clearBlinkTimeout()
|
this._clearBlinkTimeout()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { Draw } from '../draw/Draw'
|
|||||||
import { CanvasEvent } from '../event/CanvasEvent'
|
import { CanvasEvent } from '../event/CanvasEvent'
|
||||||
|
|
||||||
export class CursorAgent {
|
export class CursorAgent {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private container: HTMLDivElement
|
private container: HTMLDivElement
|
||||||
private agentCursorDom: HTMLTextAreaElement
|
private agentCursorDom: HTMLTextAreaElement
|
||||||
@@ -31,8 +30,14 @@ export class CursorAgent {
|
|||||||
agentCursorDom.onkeydown = (evt: KeyboardEvent) => this._keyDown(evt)
|
agentCursorDom.onkeydown = (evt: KeyboardEvent) => this._keyDown(evt)
|
||||||
agentCursorDom.oninput = debounce(this._input.bind(this), 0)
|
agentCursorDom.oninput = debounce(this._input.bind(this), 0)
|
||||||
agentCursorDom.onpaste = (evt: ClipboardEvent) => this._paste(evt)
|
agentCursorDom.onpaste = (evt: ClipboardEvent) => this._paste(evt)
|
||||||
agentCursorDom.addEventListener('compositionstart', this._compositionstart.bind(this))
|
agentCursorDom.addEventListener(
|
||||||
agentCursorDom.addEventListener('compositionend', this._compositionend.bind(this))
|
'compositionstart',
|
||||||
|
this._compositionstart.bind(this)
|
||||||
|
)
|
||||||
|
agentCursorDom.addEventListener(
|
||||||
|
'compositionend',
|
||||||
|
this._compositionend.bind(this)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAgentCursorDom(): HTMLTextAreaElement {
|
public getAgentCursorDom(): HTMLTextAreaElement {
|
||||||
@@ -84,13 +89,17 @@ export class CursorAgent {
|
|||||||
let start = 0
|
let start = 0
|
||||||
while (start < pasteElementList.length) {
|
while (start < pasteElementList.length) {
|
||||||
const pasteElement = pasteElementList[start]
|
const pasteElement = pasteElementList[start]
|
||||||
if (anchorElement.titleId && /^\n/.test(pasteElement.value)) break
|
if (anchorElement.titleId && /^\n/.test(pasteElement.value)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
if (VIRTUAL_ELEMENT_TYPE.includes(pasteElement.type!)) {
|
if (VIRTUAL_ELEMENT_TYPE.includes(pasteElement.type!)) {
|
||||||
pasteElementList.splice(start, 1)
|
pasteElementList.splice(start, 1)
|
||||||
if (pasteElement.valueList) {
|
if (pasteElement.valueList) {
|
||||||
for (let v = 0; v < pasteElement.valueList.length; v++) {
|
for (let v = 0; v < pasteElement.valueList.length; v++) {
|
||||||
const element = pasteElement.valueList[v]
|
const element = pasteElement.valueList[v]
|
||||||
if (element.value === ZERO || element.value === '\n') continue
|
if (element.value === ZERO || element.value === '\n') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
pasteElementList.splice(start, 0, element)
|
pasteElementList.splice(start, 0, element)
|
||||||
start++
|
start++
|
||||||
}
|
}
|
||||||
@@ -145,5 +154,4 @@ export class CursorAgent {
|
|||||||
private _compositionend(evt: CompositionEvent) {
|
private _compositionend(evt: CompositionEvent) {
|
||||||
this.canvasEvent.compositionend(evt)
|
this.canvasEvent.compositionend(evt)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
+229
-71
@@ -1,9 +1,25 @@
|
|||||||
import { version } from '../../../../package.json'
|
import { version } from '../../../../package.json'
|
||||||
import { ZERO } from '../../dataset/constant/Common'
|
import { ZERO } from '../../dataset/constant/Common'
|
||||||
import { RowFlex } from '../../dataset/enum/Row'
|
import { RowFlex } from '../../dataset/enum/Row'
|
||||||
import { IAppendElementListOption, IDrawOption, IDrawPagePayload, IDrawRowPayload, IGetValueOption, IPainterOption } from '../../interface/Draw'
|
import {
|
||||||
import { IEditorData, IEditorOption, IEditorResult } from '../../interface/Editor'
|
IAppendElementListOption,
|
||||||
import { IElement, IElementMetrics, IElementFillRect, IElementStyle } from '../../interface/Element'
|
IDrawOption,
|
||||||
|
IDrawPagePayload,
|
||||||
|
IDrawRowPayload,
|
||||||
|
IGetValueOption,
|
||||||
|
IPainterOption
|
||||||
|
} from '../../interface/Draw'
|
||||||
|
import {
|
||||||
|
IEditorData,
|
||||||
|
IEditorOption,
|
||||||
|
IEditorResult
|
||||||
|
} from '../../interface/Editor'
|
||||||
|
import {
|
||||||
|
IElement,
|
||||||
|
IElementMetrics,
|
||||||
|
IElementFillRect,
|
||||||
|
IElementStyle
|
||||||
|
} from '../../interface/Element'
|
||||||
import { IRow, IRowElement } from '../../interface/Row'
|
import { IRow, IRowElement } from '../../interface/Row'
|
||||||
import { deepClone, getUUID, nextTick } from '../../utils'
|
import { deepClone, getUUID, nextTick } from '../../utils'
|
||||||
import { Cursor } from '../cursor/Cursor'
|
import { Cursor } from '../cursor/Cursor'
|
||||||
@@ -35,7 +51,14 @@ import { SubscriptParticle } from './particle/Subscript'
|
|||||||
import { SeparatorParticle } from './particle/Separator'
|
import { SeparatorParticle } from './particle/Separator'
|
||||||
import { PageBreakParticle } from './particle/PageBreak'
|
import { PageBreakParticle } from './particle/PageBreak'
|
||||||
import { Watermark } from './frame/Watermark'
|
import { Watermark } from './frame/Watermark'
|
||||||
import { EditorComponent, EditorMode, EditorZone, PageMode, PaperDirection, WordBreak } from '../../dataset/enum/Editor'
|
import {
|
||||||
|
EditorComponent,
|
||||||
|
EditorMode,
|
||||||
|
EditorZone,
|
||||||
|
PageMode,
|
||||||
|
PaperDirection,
|
||||||
|
WordBreak
|
||||||
|
} from '../../dataset/enum/Editor'
|
||||||
import { Control } from './control/Control'
|
import { Control } from './control/Control'
|
||||||
import { zipElementList } from '../../utils/element'
|
import { zipElementList } from '../../utils/element'
|
||||||
import { CheckboxParticle } from './particle/CheckboxParticle'
|
import { CheckboxParticle } from './particle/CheckboxParticle'
|
||||||
@@ -58,7 +81,6 @@ import { Placeholder } from './frame/Placeholder'
|
|||||||
import { WORD_LIKE_REG } from '../../dataset/constant/Regular'
|
import { WORD_LIKE_REG } from '../../dataset/constant/Regular'
|
||||||
|
|
||||||
export class Draw {
|
export class Draw {
|
||||||
|
|
||||||
private container: HTMLDivElement
|
private container: HTMLDivElement
|
||||||
private pageContainer: HTMLDivElement
|
private pageContainer: HTMLDivElement
|
||||||
private pageList: HTMLCanvasElement[]
|
private pageList: HTMLCanvasElement[]
|
||||||
@@ -276,7 +298,10 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getPageNumberBottom(): number {
|
public getPageNumberBottom(): number {
|
||||||
const { pageNumber: { bottom }, scale } = this.options
|
const {
|
||||||
|
pageNumber: { bottom },
|
||||||
|
scale
|
||||||
|
} = this.options
|
||||||
return bottom * scale
|
return bottom * scale
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,7 +469,8 @@ export class Draw {
|
|||||||
|
|
||||||
public insertElementList(payload: IElement[]) {
|
public insertElementList(payload: IElement[]) {
|
||||||
if (!payload.length) return
|
if (!payload.length) return
|
||||||
const isPartRangeInControlOutside = this.control.isPartRangeInControlOutside()
|
const isPartRangeInControlOutside =
|
||||||
|
this.control.isPartRangeInControlOutside()
|
||||||
if (isPartRangeInControlOutside) return
|
if (isPartRangeInControlOutside) return
|
||||||
const { startIndex, endIndex } = this.range.getRange()
|
const { startIndex, endIndex } = this.range.getRange()
|
||||||
if (!~startIndex && !~endIndex) return
|
if (!~startIndex && !~endIndex) return
|
||||||
@@ -475,7 +501,10 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public appendElementList(elementList: IElement[], options: IAppendElementListOption = {}) {
|
public appendElementList(
|
||||||
|
elementList: IElement[],
|
||||||
|
options: IAppendElementListOption = {}
|
||||||
|
) {
|
||||||
if (!elementList.length) return
|
if (!elementList.length) return
|
||||||
formatElementList(elementList, {
|
formatElementList(elementList, {
|
||||||
isHandleFirstElement: false,
|
isHandleFirstElement: false,
|
||||||
@@ -496,17 +525,30 @@ export class Draw {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public spliceElementList(elementList: IElement[], start: number, deleteCount: number, ...items: IElement[]) {
|
public spliceElementList(
|
||||||
|
elementList: IElement[],
|
||||||
|
start: number,
|
||||||
|
deleteCount: number,
|
||||||
|
...items: IElement[]
|
||||||
|
) {
|
||||||
if (deleteCount > 0) {
|
if (deleteCount > 0) {
|
||||||
// 当最后元素与开始元素列表信息不一致时:清除当前列表信息
|
// 当最后元素与开始元素列表信息不一致时:清除当前列表信息
|
||||||
const endIndex = start + deleteCount
|
const endIndex = start + deleteCount
|
||||||
const endElement = elementList[endIndex]
|
const endElement = elementList[endIndex]
|
||||||
const endElementListId = endElement?.listId
|
const endElementListId = endElement?.listId
|
||||||
if (endElementListId && elementList[start - 1]?.listId !== endElementListId) {
|
if (
|
||||||
|
endElementListId &&
|
||||||
|
elementList[start - 1]?.listId !== endElementListId
|
||||||
|
) {
|
||||||
let startIndex = endIndex
|
let startIndex = endIndex
|
||||||
while (startIndex < elementList.length) {
|
while (startIndex < elementList.length) {
|
||||||
const curElement = elementList[startIndex]
|
const curElement = elementList[startIndex]
|
||||||
if (curElement.listId !== endElementListId || curElement.value === ZERO) break
|
if (
|
||||||
|
curElement.listId !== endElementListId ||
|
||||||
|
curElement.value === ZERO
|
||||||
|
) {
|
||||||
|
break
|
||||||
|
}
|
||||||
delete curElement.listId
|
delete curElement.listId
|
||||||
delete curElement.listType
|
delete curElement.listType
|
||||||
delete curElement.listStyle
|
delete curElement.listStyle
|
||||||
@@ -597,18 +639,23 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getPainterStyle(): IElementStyle | null {
|
public getPainterStyle(): IElementStyle | null {
|
||||||
return this.painterStyle && Object.keys(this.painterStyle).length ? this.painterStyle : null
|
return this.painterStyle && Object.keys(this.painterStyle).length
|
||||||
|
? this.painterStyle
|
||||||
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPainterOptions(): IPainterOption | null {
|
public getPainterOptions(): IPainterOption | null {
|
||||||
return this.painterOptions
|
return this.painterOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
public setPainterStyle(payload: IElementStyle | null, options?: IPainterOption) {
|
public setPainterStyle(
|
||||||
|
payload: IElementStyle | null,
|
||||||
|
options?: IPainterOption
|
||||||
|
) {
|
||||||
this.painterStyle = payload
|
this.painterStyle = payload
|
||||||
this.painterOptions = options || null
|
this.painterOptions = options || null
|
||||||
if (this.getPainterStyle()) {
|
if (this.getPainterStyle()) {
|
||||||
this.pageList.forEach(c => c.style.cursor = 'copy')
|
this.pageList.forEach(c => (c.style.cursor = 'copy'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,8 +794,14 @@ export class Draw {
|
|||||||
// 数据
|
// 数据
|
||||||
const { pageNo } = options
|
const { pageNo } = options
|
||||||
let mainElementList = this.elementList
|
let mainElementList = this.elementList
|
||||||
if (Number.isInteger(pageNo) && pageNo! >= 0 && pageNo! < this.pageRowList.length) {
|
if (
|
||||||
mainElementList = this.pageRowList[pageNo!].flatMap(row => row.elementList)
|
Number.isInteger(pageNo) &&
|
||||||
|
pageNo! >= 0 &&
|
||||||
|
pageNo! < this.pageRowList.length
|
||||||
|
) {
|
||||||
|
mainElementList = this.pageRowList[pageNo!].flatMap(
|
||||||
|
row => row.elementList
|
||||||
|
)
|
||||||
}
|
}
|
||||||
const data: IEditorData = {
|
const data: IEditorData = {
|
||||||
header: zipElementList(this.headerElementList),
|
header: zipElementList(this.headerElementList),
|
||||||
@@ -850,11 +903,14 @@ export class Draw {
|
|||||||
const { defaultSize, defaultFont } = this.options
|
const { defaultSize, defaultFont } = this.options
|
||||||
const font = el.font || defaultFont
|
const font = el.font || defaultFont
|
||||||
const size = el.actualSize || el.size || defaultSize
|
const size = el.actualSize || el.size || defaultSize
|
||||||
return `${el.italic ? 'italic ' : ''}${el.bold ? 'bold ' : ''}${size * scale}px ${font}`
|
return `${el.italic ? 'italic ' : ''}${el.bold ? 'bold ' : ''}${
|
||||||
|
size * scale
|
||||||
|
}px ${font}`
|
||||||
}
|
}
|
||||||
|
|
||||||
public computeRowList(innerWidth: number, elementList: IElement[]) {
|
public computeRowList(innerWidth: number, elementList: IElement[]) {
|
||||||
const { defaultSize, defaultRowMargin, scale, tdPadding, defaultTabWidth } = this.options
|
const { defaultSize, defaultRowMargin, scale, tdPadding, defaultTabWidth } =
|
||||||
|
this.options
|
||||||
const defaultBasicRowMarginHeight = this.getDefaultBasicRowMarginHeight()
|
const defaultBasicRowMarginHeight = this.getDefaultBasicRowMarginHeight()
|
||||||
const canvas = document.createElement('canvas')
|
const canvas = document.createElement('canvas')
|
||||||
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
|
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
|
||||||
@@ -877,7 +933,8 @@ export class Draw {
|
|||||||
for (let i = 0; i < elementList.length; i++) {
|
for (let i = 0; i < elementList.length; i++) {
|
||||||
const curRow: IRow = rowList[rowList.length - 1]
|
const curRow: IRow = rowList[rowList.length - 1]
|
||||||
const element = elementList[i]
|
const element = elementList[i]
|
||||||
const rowMargin = defaultBasicRowMarginHeight * (element.rowMargin || defaultRowMargin)
|
const rowMargin =
|
||||||
|
defaultBasicRowMarginHeight * (element.rowMargin || defaultRowMargin)
|
||||||
const metrics: IElementMetrics = {
|
const metrics: IElementMetrics = {
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
@@ -887,17 +944,24 @@ export class Draw {
|
|||||||
// 实际可用宽度
|
// 实际可用宽度
|
||||||
const offsetX = element.listId ? listStyleMap.get(element.listId) || 0 : 0
|
const offsetX = element.listId ? listStyleMap.get(element.listId) || 0 : 0
|
||||||
const availableWidth = innerWidth - offsetX
|
const availableWidth = innerWidth - offsetX
|
||||||
if (element.type === ElementType.IMAGE || element.type === ElementType.LATEX) {
|
if (
|
||||||
|
element.type === ElementType.IMAGE ||
|
||||||
|
element.type === ElementType.LATEX
|
||||||
|
) {
|
||||||
const elementWidth = element.width! * scale
|
const elementWidth = element.width! * scale
|
||||||
const elementHeight = element.height! * scale
|
const elementHeight = element.height! * scale
|
||||||
// 图片超出尺寸后自适应
|
// 图片超出尺寸后自适应
|
||||||
const curRowWidth = element.imgDisplay === ImageDisplay.INLINE ? 0 : curRow.width
|
const curRowWidth =
|
||||||
|
element.imgDisplay === ImageDisplay.INLINE ? 0 : curRow.width
|
||||||
if (curRowWidth + elementWidth > availableWidth) {
|
if (curRowWidth + elementWidth > availableWidth) {
|
||||||
// 计算剩余大小
|
// 计算剩余大小
|
||||||
const surplusWidth = availableWidth - curRowWidth
|
const surplusWidth = availableWidth - curRowWidth
|
||||||
const adaptiveWidth = surplusWidth > 0 ? surplusWidth : Math.min(elementWidth, availableWidth)
|
const adaptiveWidth =
|
||||||
|
surplusWidth > 0
|
||||||
|
? surplusWidth
|
||||||
|
: Math.min(elementWidth, availableWidth)
|
||||||
element.width = adaptiveWidth
|
element.width = adaptiveWidth
|
||||||
element.height = elementHeight * adaptiveWidth / elementWidth
|
element.height = (elementHeight * adaptiveWidth) / elementWidth
|
||||||
metrics.width = element.width
|
metrics.width = element.width
|
||||||
metrics.height = element.height
|
metrics.height = element.height
|
||||||
metrics.boundingBoxDescent = element.height
|
metrics.boundingBoxDescent = element.height
|
||||||
@@ -917,7 +981,10 @@ export class Draw {
|
|||||||
const tr = trList[t]
|
const tr = trList[t]
|
||||||
for (let d = 0; d < tr.tdList.length; d++) {
|
for (let d = 0; d < tr.tdList.length; d++) {
|
||||||
const td = tr.tdList[d]
|
const td = tr.tdList[d]
|
||||||
const rowList = this.computeRowList((td.width! - tdGap) * scale, td.value)
|
const rowList = this.computeRowList(
|
||||||
|
(td.width! - tdGap) * scale,
|
||||||
|
td.value
|
||||||
|
)
|
||||||
const rowHeight = rowList.reduce((pre, cur) => pre + cur.height, 0)
|
const rowHeight = rowList.reduce((pre, cur) => pre + cur.height, 0)
|
||||||
td.rowList = rowList
|
td.rowList = rowList
|
||||||
// 移除缩放导致的行高变化-渲染时会进行缩放调整
|
// 移除缩放导致的行高变化-渲染时会进行缩放调整
|
||||||
@@ -957,9 +1024,10 @@ export class Draw {
|
|||||||
const curTdHeight = td.mainHeight!
|
const curTdHeight = td.mainHeight!
|
||||||
const curTdMinHeight = td.realMinHeight!
|
const curTdMinHeight = td.realMinHeight!
|
||||||
// 获取最大可减少高度
|
// 获取最大可减少高度
|
||||||
const curReduceHeight = curTdHeight < curTdMinHeight
|
const curReduceHeight =
|
||||||
? curTdRealHeight - curTdMinHeight
|
curTdHeight < curTdMinHeight
|
||||||
: curTdRealHeight - curTdHeight
|
? curTdRealHeight - curTdMinHeight
|
||||||
|
: curTdRealHeight - curTdHeight
|
||||||
if (!~reduceHeight || curReduceHeight < reduceHeight) {
|
if (!~reduceHeight || curReduceHeight < reduceHeight) {
|
||||||
reduceHeight = curReduceHeight
|
reduceHeight = curReduceHeight
|
||||||
}
|
}
|
||||||
@@ -976,7 +1044,10 @@ export class Draw {
|
|||||||
this.tableParticle.computeRowColInfo(element)
|
this.tableParticle.computeRowColInfo(element)
|
||||||
// 计算出表格高度
|
// 计算出表格高度
|
||||||
const tableHeight = trList.reduce((pre, cur) => pre + cur.height, 0)
|
const tableHeight = trList.reduce((pre, cur) => pre + cur.height, 0)
|
||||||
const tableWidth = element.colgroup!.reduce((pre, cur) => pre + cur.width, 0)
|
const tableWidth = element.colgroup!.reduce(
|
||||||
|
(pre, cur) => pre + cur.width,
|
||||||
|
0
|
||||||
|
)
|
||||||
element.width = tableWidth
|
element.width = tableWidth
|
||||||
element.height = tableHeight
|
element.height = tableHeight
|
||||||
const elementWidth = tableWidth * scale
|
const elementWidth = tableWidth * scale
|
||||||
@@ -991,7 +1062,10 @@ export class Draw {
|
|||||||
let curPagePreHeight = marginHeight
|
let curPagePreHeight = marginHeight
|
||||||
for (let r = 0; r < rowList.length; r++) {
|
for (let r = 0; r < rowList.length; r++) {
|
||||||
const row = rowList[r]
|
const row = rowList[r]
|
||||||
if (row.height + curPagePreHeight > height || rowList[r - 1]?.isPageBreak) {
|
if (
|
||||||
|
row.height + curPagePreHeight > height ||
|
||||||
|
rowList[r - 1]?.isPageBreak
|
||||||
|
) {
|
||||||
curPagePreHeight = marginHeight + row.height
|
curPagePreHeight = marginHeight + row.height
|
||||||
} else {
|
} else {
|
||||||
curPagePreHeight += row.height
|
curPagePreHeight += row.height
|
||||||
@@ -1009,7 +1083,10 @@ export class Draw {
|
|||||||
for (let r = 0; r < trList.length; r++) {
|
for (let r = 0; r < trList.length; r++) {
|
||||||
const tr = trList[r]
|
const tr = trList[r]
|
||||||
const trHeight = tr.height * scale
|
const trHeight = tr.height * scale
|
||||||
if (curPagePreHeight + rowMarginHeight + preTrHeight + trHeight > height) {
|
if (
|
||||||
|
curPagePreHeight + rowMarginHeight + preTrHeight + trHeight >
|
||||||
|
height
|
||||||
|
) {
|
||||||
// 是否跨列
|
// 是否跨列
|
||||||
if (element.colgroup?.length !== tr.tdList.length) {
|
if (element.colgroup?.length !== tr.tdList.length) {
|
||||||
deleteCount = 0
|
deleteCount = 0
|
||||||
@@ -1024,7 +1101,10 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
if (deleteCount) {
|
if (deleteCount) {
|
||||||
const cloneTrList = trList.splice(deleteStart, deleteCount)
|
const cloneTrList = trList.splice(deleteStart, deleteCount)
|
||||||
const cloneTrHeight = cloneTrList.reduce((pre, cur) => pre + cur.height, 0)
|
const cloneTrHeight = cloneTrList.reduce(
|
||||||
|
(pre, cur) => pre + cur.height,
|
||||||
|
0
|
||||||
|
)
|
||||||
element.height -= cloneTrHeight
|
element.height -= cloneTrHeight
|
||||||
metrics.height -= cloneTrHeight
|
metrics.height -= cloneTrHeight
|
||||||
metrics.boundingBoxDescent -= cloneTrHeight
|
metrics.boundingBoxDescent -= cloneTrHeight
|
||||||
@@ -1035,7 +1115,10 @@ export class Draw {
|
|||||||
this.spliceElementList(elementList, i + 1, 0, cloneElement)
|
this.spliceElementList(elementList, i + 1, 0, cloneElement)
|
||||||
// 换页的是当前行则改变上下文
|
// 换页的是当前行则改变上下文
|
||||||
const positionContext = this.position.getPositionContext()
|
const positionContext = this.position.getPositionContext()
|
||||||
if (positionContext.isTable && positionContext.trIndex === deleteStart) {
|
if (
|
||||||
|
positionContext.isTable &&
|
||||||
|
positionContext.trIndex === deleteStart
|
||||||
|
) {
|
||||||
positionContext.index! += 1
|
positionContext.index! += 1
|
||||||
positionContext.trIndex = 0
|
positionContext.trIndex = 0
|
||||||
this.position.setPositionContext(positionContext)
|
this.position.setPositionContext(positionContext)
|
||||||
@@ -1079,7 +1162,10 @@ export class Draw {
|
|||||||
} else {
|
} else {
|
||||||
// 设置上下标真实字体尺寸
|
// 设置上下标真实字体尺寸
|
||||||
const size = element.size || defaultSize
|
const size = element.size || defaultSize
|
||||||
if (element.type === ElementType.SUPERSCRIPT || element.type === ElementType.SUBSCRIPT) {
|
if (
|
||||||
|
element.type === ElementType.SUPERSCRIPT ||
|
||||||
|
element.type === ElementType.SUBSCRIPT
|
||||||
|
) {
|
||||||
element.actualSize = Math.ceil(size * 0.6)
|
element.actualSize = Math.ceil(size * 0.6)
|
||||||
}
|
}
|
||||||
metrics.height = (element.actualSize || size) * scale
|
metrics.height = (element.actualSize || size) * scale
|
||||||
@@ -1089,19 +1175,29 @@ export class Draw {
|
|||||||
if (element.letterSpacing) {
|
if (element.letterSpacing) {
|
||||||
metrics.width += element.letterSpacing * scale
|
metrics.width += element.letterSpacing * scale
|
||||||
}
|
}
|
||||||
metrics.boundingBoxAscent = (element.value === ZERO ? defaultSize : fontMetrics.actualBoundingBoxAscent) * scale
|
metrics.boundingBoxAscent =
|
||||||
metrics.boundingBoxDescent = fontMetrics.actualBoundingBoxDescent * scale
|
(element.value === ZERO
|
||||||
|
? defaultSize
|
||||||
|
: fontMetrics.actualBoundingBoxAscent) * scale
|
||||||
|
metrics.boundingBoxDescent =
|
||||||
|
fontMetrics.actualBoundingBoxDescent * scale
|
||||||
if (element.type === ElementType.SUPERSCRIPT) {
|
if (element.type === ElementType.SUPERSCRIPT) {
|
||||||
metrics.boundingBoxAscent += metrics.height / 2
|
metrics.boundingBoxAscent += metrics.height / 2
|
||||||
} else if (element.type === ElementType.SUBSCRIPT) {
|
} else if (element.type === ElementType.SUBSCRIPT) {
|
||||||
metrics.boundingBoxDescent += metrics.height / 2
|
metrics.boundingBoxDescent += metrics.height / 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const ascent = (element.imgDisplay !== ImageDisplay.INLINE && element.type === ElementType.IMAGE) ||
|
const ascent =
|
||||||
|
(element.imgDisplay !== ImageDisplay.INLINE &&
|
||||||
|
element.type === ElementType.IMAGE) ||
|
||||||
element.type === ElementType.LATEX
|
element.type === ElementType.LATEX
|
||||||
? metrics.height + rowMargin
|
? metrics.height + rowMargin
|
||||||
: metrics.boundingBoxAscent + rowMargin
|
: metrics.boundingBoxAscent + rowMargin
|
||||||
const height = rowMargin + metrics.boundingBoxAscent + metrics.boundingBoxDescent + rowMargin
|
const height =
|
||||||
|
rowMargin +
|
||||||
|
metrics.boundingBoxAscent +
|
||||||
|
metrics.boundingBoxDescent +
|
||||||
|
rowMargin
|
||||||
const rowElement: IRowElement = Object.assign(element, {
|
const rowElement: IRowElement = Object.assign(element, {
|
||||||
metrics,
|
metrics,
|
||||||
style: this._getFont(element, scale)
|
style: this._getFont(element, scale)
|
||||||
@@ -1119,12 +1215,19 @@ export class Draw {
|
|||||||
// 英文单词
|
// 英文单词
|
||||||
const word = `${preElement?.value || ''}${element.value}`
|
const word = `${preElement?.value || ''}${element.value}`
|
||||||
if (WORD_LIKE_REG.test(word)) {
|
if (WORD_LIKE_REG.test(word)) {
|
||||||
const { width, endElement } = this.textParticle.measureWord(ctx, elementList, i)
|
const { width, endElement } = this.textParticle.measureWord(
|
||||||
|
ctx,
|
||||||
|
elementList,
|
||||||
|
i
|
||||||
|
)
|
||||||
curRowWidth += width
|
curRowWidth += width
|
||||||
nextElement = endElement
|
nextElement = endElement
|
||||||
}
|
}
|
||||||
// 标点符号
|
// 标点符号
|
||||||
curRowWidth += this.textParticle.measurePunctuationWidth(ctx, nextElement)
|
curRowWidth += this.textParticle.measurePunctuationWidth(
|
||||||
|
ctx,
|
||||||
|
nextElement
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 列表信息
|
// 列表信息
|
||||||
@@ -1137,15 +1240,15 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
listId = element.listId
|
listId = element.listId
|
||||||
if (
|
if (
|
||||||
element.type === ElementType.TABLE
|
element.type === ElementType.TABLE ||
|
||||||
|| preElement?.type === ElementType.TABLE
|
preElement?.type === ElementType.TABLE ||
|
||||||
|| preElement?.type === ElementType.BLOCK
|
preElement?.type === ElementType.BLOCK ||
|
||||||
|| element.type === ElementType.BLOCK
|
element.type === ElementType.BLOCK ||
|
||||||
|| preElement?.imgDisplay === ImageDisplay.INLINE
|
preElement?.imgDisplay === ImageDisplay.INLINE ||
|
||||||
|| element.imgDisplay === ImageDisplay.INLINE
|
element.imgDisplay === ImageDisplay.INLINE ||
|
||||||
|| curRowWidth > availableWidth
|
curRowWidth > availableWidth ||
|
||||||
|| (i !== 0 && element.value === ZERO)
|
(i !== 0 && element.value === ZERO) ||
|
||||||
|| (preElement?.listId !== element.listId)
|
preElement?.listId !== element.listId
|
||||||
) {
|
) {
|
||||||
// 减小行元素前第一行空行行高
|
// 减小行元素前第一行空行行高
|
||||||
if (
|
if (
|
||||||
@@ -1156,8 +1259,12 @@ export class Draw {
|
|||||||
curRow.height = defaultBasicRowMarginHeight
|
curRow.height = defaultBasicRowMarginHeight
|
||||||
}
|
}
|
||||||
// 两端对齐
|
// 两端对齐
|
||||||
if (preElement?.rowFlex === RowFlex.ALIGNMENT && curRowWidth > availableWidth) {
|
if (
|
||||||
const gap = (availableWidth - curRow.width) / curRow.elementList.length
|
preElement?.rowFlex === RowFlex.ALIGNMENT &&
|
||||||
|
curRowWidth > availableWidth
|
||||||
|
) {
|
||||||
|
const gap =
|
||||||
|
(availableWidth - curRow.width) / curRow.elementList.length
|
||||||
for (let e = 0; e < curRow.elementList.length; e++) {
|
for (let e = 0; e < curRow.elementList.length; e++) {
|
||||||
const el = curRow.elementList[e]
|
const el = curRow.elementList[e]
|
||||||
el.metrics.width += gap
|
el.metrics.width += gap
|
||||||
@@ -1217,7 +1324,10 @@ export class Draw {
|
|||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < this.rowList.length; i++) {
|
for (let i = 0; i < this.rowList.length; i++) {
|
||||||
const row = this.rowList[i]
|
const row = this.rowList[i]
|
||||||
if (row.height + pageHeight > height || this.rowList[i - 1]?.isPageBreak) {
|
if (
|
||||||
|
row.height + pageHeight > height ||
|
||||||
|
this.rowList[i - 1]?.isPageBreak
|
||||||
|
) {
|
||||||
pageHeight = marginHeight + row.height
|
pageHeight = marginHeight + row.height
|
||||||
pageRowList.push([row])
|
pageRowList.push([row])
|
||||||
pageNo++
|
pageNo++
|
||||||
@@ -1238,7 +1348,8 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload) {
|
public drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload) {
|
||||||
const { rowList, pageNo, elementList, positionList, startIndex, zone } = payload
|
const { rowList, pageNo, elementList, positionList, startIndex, zone } =
|
||||||
|
payload
|
||||||
const { scale, tdPadding } = this.options
|
const { scale, tdPadding } = this.options
|
||||||
const { isCrossRowCol, tableId } = this.range.getRange()
|
const { isCrossRowCol, tableId } = this.range.getRange()
|
||||||
let index = startIndex
|
let index = startIndex
|
||||||
@@ -1266,10 +1377,21 @@ export class Draw {
|
|||||||
// 元素高亮记录
|
// 元素高亮记录
|
||||||
if (element.highlight) {
|
if (element.highlight) {
|
||||||
// 高亮元素相连需立即绘制,并记录下一元素坐标
|
// 高亮元素相连需立即绘制,并记录下一元素坐标
|
||||||
if (preElement && preElement.highlight && preElement.highlight !== element.highlight) {
|
if (
|
||||||
|
preElement &&
|
||||||
|
preElement.highlight &&
|
||||||
|
preElement.highlight !== element.highlight
|
||||||
|
) {
|
||||||
this.highlight.render(ctx)
|
this.highlight.render(ctx)
|
||||||
}
|
}
|
||||||
this.highlight.recordFillInfo(ctx, x, y, metrics.width, curRow.height, element.highlight)
|
this.highlight.recordFillInfo(
|
||||||
|
ctx,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
metrics.width,
|
||||||
|
curRow.height,
|
||||||
|
element.highlight
|
||||||
|
)
|
||||||
} else if (preElement?.highlight) {
|
} else if (preElement?.highlight) {
|
||||||
this.highlight.render(ctx)
|
this.highlight.render(ctx)
|
||||||
}
|
}
|
||||||
@@ -1325,19 +1447,40 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
// 下划线记录
|
// 下划线记录
|
||||||
if (element.underline) {
|
if (element.underline) {
|
||||||
this.underline.recordFillInfo(ctx, x, y + curRow.height, metrics.width, 0, element.color)
|
this.underline.recordFillInfo(
|
||||||
|
ctx,
|
||||||
|
x,
|
||||||
|
y + curRow.height,
|
||||||
|
metrics.width,
|
||||||
|
0,
|
||||||
|
element.color
|
||||||
|
)
|
||||||
} else if (preElement?.underline) {
|
} else if (preElement?.underline) {
|
||||||
this.underline.render(ctx)
|
this.underline.render(ctx)
|
||||||
}
|
}
|
||||||
// 删除线记录
|
// 删除线记录
|
||||||
if (element.strikeout) {
|
if (element.strikeout) {
|
||||||
this.strikeout.recordFillInfo(ctx, x, y + curRow.height / 2, metrics.width)
|
this.strikeout.recordFillInfo(
|
||||||
|
ctx,
|
||||||
|
x,
|
||||||
|
y + curRow.height / 2,
|
||||||
|
metrics.width
|
||||||
|
)
|
||||||
} else if (preElement?.strikeout) {
|
} else if (preElement?.strikeout) {
|
||||||
this.strikeout.render(ctx)
|
this.strikeout.render(ctx)
|
||||||
}
|
}
|
||||||
// 选区记录
|
// 选区记录
|
||||||
const { zone: currentZone, startIndex, endIndex } = this.range.getRange()
|
const {
|
||||||
if (currentZone === zone && startIndex !== endIndex && startIndex <= index && index <= endIndex) {
|
zone: currentZone,
|
||||||
|
startIndex,
|
||||||
|
endIndex
|
||||||
|
} = this.range.getRange()
|
||||||
|
if (
|
||||||
|
currentZone === zone &&
|
||||||
|
startIndex !== endIndex &&
|
||||||
|
startIndex <= index &&
|
||||||
|
index <= endIndex
|
||||||
|
) {
|
||||||
// 从行尾开始-绘制最小宽度
|
// 从行尾开始-绘制最小宽度
|
||||||
if (startIndex === index) {
|
if (startIndex === index) {
|
||||||
const nextElement = elementList[startIndex + 1]
|
const nextElement = elementList[startIndex + 1]
|
||||||
@@ -1351,8 +1494,8 @@ export class Draw {
|
|||||||
const positionContext = this.position.getPositionContext()
|
const positionContext = this.position.getPositionContext()
|
||||||
// 表格需限定上下文
|
// 表格需限定上下文
|
||||||
if (
|
if (
|
||||||
(!positionContext.isTable && !element.tdId)
|
(!positionContext.isTable && !element.tdId) ||
|
||||||
|| positionContext.tdId === element.tdId
|
positionContext.tdId === element.tdId
|
||||||
) {
|
) {
|
||||||
let rangeWidth = metrics.width
|
let rangeWidth = metrics.width
|
||||||
// 最小选区宽度
|
// 最小选区宽度
|
||||||
@@ -1392,7 +1535,11 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
// 绘制列表样式
|
// 绘制列表样式
|
||||||
if (curRow.isList) {
|
if (curRow.isList) {
|
||||||
this.listParticle.drawListStyle(ctx, curRow, positionList[curRow.startIndex])
|
this.listParticle.drawListStyle(
|
||||||
|
ctx,
|
||||||
|
curRow,
|
||||||
|
positionList[curRow.startIndex]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// 绘制富文本及文字
|
// 绘制富文本及文字
|
||||||
this._drawRichText(ctx)
|
this._drawRichText(ctx)
|
||||||
@@ -1401,8 +1548,16 @@ export class Draw {
|
|||||||
const { x, y, width, height } = rangeRecord
|
const { x, y, width, height } = rangeRecord
|
||||||
this.range.render(ctx, x, y, width, height)
|
this.range.render(ctx, x, y, width, height)
|
||||||
}
|
}
|
||||||
if (isCrossRowCol && tableRangeElement && tableRangeElement.id === tableId) {
|
if (
|
||||||
const { coordinate: { leftTop: [x, y] } } = positionList[curRow.startIndex]
|
isCrossRowCol &&
|
||||||
|
tableRangeElement &&
|
||||||
|
tableRangeElement.id === tableId
|
||||||
|
) {
|
||||||
|
const {
|
||||||
|
coordinate: {
|
||||||
|
leftTop: [x, y]
|
||||||
|
}
|
||||||
|
} = positionList[curRow.startIndex]
|
||||||
this.tableParticle.drawRange(ctx, tableRangeElement, x, y)
|
this.tableParticle.drawRange(ctx, tableRangeElement, x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1474,7 +1629,7 @@ export class Draw {
|
|||||||
const positionList = this.position.getOriginalMainPositionList()
|
const positionList = this.position.getOriginalMainPositionList()
|
||||||
const elementList = this.getOriginalMainElementList()
|
const elementList = this.getOriginalMainElementList()
|
||||||
this._disconnectLazyRender()
|
this._disconnectLazyRender()
|
||||||
this.lazyRenderIntersectionObserver = new IntersectionObserver((entries) => {
|
this.lazyRenderIntersectionObserver = new IntersectionObserver(entries => {
|
||||||
entries.forEach(entry => {
|
entries.forEach(entry => {
|
||||||
if (entry.isIntersecting) {
|
if (entry.isIntersecting) {
|
||||||
const index = Number((<HTMLCanvasElement>entry.target).dataset.index)
|
const index = Number((<HTMLCanvasElement>entry.target).dataset.index)
|
||||||
@@ -1555,7 +1710,8 @@ export class Draw {
|
|||||||
if (prePageCount > curPageCount) {
|
if (prePageCount > curPageCount) {
|
||||||
const deleteCount = prePageCount - curPageCount
|
const deleteCount = prePageCount - curPageCount
|
||||||
this.ctxList.splice(curPageCount, deleteCount)
|
this.ctxList.splice(curPageCount, deleteCount)
|
||||||
this.pageList.splice(curPageCount, deleteCount)
|
this.pageList
|
||||||
|
.splice(curPageCount, deleteCount)
|
||||||
.forEach(page => page.remove())
|
.forEach(page => page.remove())
|
||||||
}
|
}
|
||||||
// 绘制元素
|
// 绘制元素
|
||||||
@@ -1572,14 +1728,17 @@ export class Draw {
|
|||||||
if (positionContext.isTable) {
|
if (positionContext.isTable) {
|
||||||
const { index, trIndex, tdIndex } = positionContext
|
const { index, trIndex, tdIndex } = positionContext
|
||||||
const elementList = this.getOriginalElementList()
|
const elementList = this.getOriginalElementList()
|
||||||
const tablePositionList = elementList[index!].trList?.[trIndex!].tdList[tdIndex!].positionList
|
const tablePositionList =
|
||||||
|
elementList[index!].trList?.[trIndex!].tdList[tdIndex!].positionList
|
||||||
if (curIndex === undefined && tablePositionList) {
|
if (curIndex === undefined && tablePositionList) {
|
||||||
curIndex = tablePositionList.length - 1
|
curIndex = tablePositionList.length - 1
|
||||||
}
|
}
|
||||||
const tablePosition = tablePositionList?.[curIndex!]
|
const tablePosition = tablePositionList?.[curIndex!]
|
||||||
this.position.setCursorPosition(tablePosition || null)
|
this.position.setCursorPosition(tablePosition || null)
|
||||||
} else {
|
} else {
|
||||||
this.position.setCursorPosition(curIndex !== undefined ? positionList[curIndex] : null)
|
this.position.setCursorPosition(
|
||||||
|
curIndex !== undefined ? positionList[curIndex] : null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
this.cursor.drawCursor()
|
this.cursor.drawCursor()
|
||||||
}
|
}
|
||||||
@@ -1631,5 +1790,4 @@ export class Draw {
|
|||||||
this.scrollObserver.removeEvent()
|
this.scrollObserver.removeEvent()
|
||||||
this.selectionObserver.removeEvent()
|
this.selectionObserver.removeEvent()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
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 { IControl, IControlInitOption, IControlInstance, IControlOption } from '../../../interface/Control'
|
import {
|
||||||
|
IControl,
|
||||||
|
IControlInitOption,
|
||||||
|
IControlInstance,
|
||||||
|
IControlOption
|
||||||
|
} from '../../../interface/Control'
|
||||||
import { IElement, IElementPosition } from '../../../interface/Element'
|
import { IElement, IElementPosition } from '../../../interface/Element'
|
||||||
import { IRange } from '../../../interface/Range'
|
import { IRange } from '../../../interface/Range'
|
||||||
import { deepClone, splitText } from '../../../utils'
|
import { deepClone, splitText } from '../../../utils'
|
||||||
import { formatElementContext, pickElementAttr, zipElementList } from '../../../utils/element'
|
import {
|
||||||
|
formatElementContext,
|
||||||
|
pickElementAttr,
|
||||||
|
zipElementList
|
||||||
|
} from '../../../utils/element'
|
||||||
import { Listener } from '../../listener/Listener'
|
import { Listener } from '../../listener/Listener'
|
||||||
import { RangeManager } from '../../range/RangeManager'
|
import { RangeManager } from '../../range/RangeManager'
|
||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
@@ -13,11 +22,10 @@ import { SelectControl } from './select/SelectControl'
|
|||||||
import { TextControl } from './text/TextControl'
|
import { TextControl } from './text/TextControl'
|
||||||
|
|
||||||
interface IMoveCursorResult {
|
interface IMoveCursorResult {
|
||||||
newIndex: number;
|
newIndex: number
|
||||||
newElement: IElement;
|
newElement: IElement
|
||||||
}
|
}
|
||||||
export class Control {
|
export class Control {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private range: RangeManager
|
private range: RangeManager
|
||||||
private listener: Listener
|
private listener: Listener
|
||||||
@@ -44,8 +52,9 @@ export class Control {
|
|||||||
const startElement = elementList[startIndex]
|
const startElement = elementList[startIndex]
|
||||||
const endElement = elementList[endIndex]
|
const endElement = elementList[endIndex]
|
||||||
if (
|
if (
|
||||||
(startElement.type === ElementType.CONTROL || endElement.type === ElementType.CONTROL)
|
(startElement.type === ElementType.CONTROL ||
|
||||||
&& startElement.controlId !== endElement.controlId
|
endElement.type === ElementType.CONTROL) &&
|
||||||
|
startElement.controlId !== endElement.controlId
|
||||||
) {
|
) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -195,8 +204,8 @@ export class Control {
|
|||||||
while (startIndex < elementList.length) {
|
while (startIndex < elementList.length) {
|
||||||
const nextElement = elementList[startIndex]
|
const nextElement = elementList[startIndex]
|
||||||
if (
|
if (
|
||||||
nextElement.controlId !== element.controlId
|
nextElement.controlId !== element.controlId ||
|
||||||
|| nextElement.controlComponent !== ControlComponent.PREFIX
|
nextElement.controlComponent !== ControlComponent.PREFIX
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
newIndex: startIndex - 1,
|
newIndex: startIndex - 1,
|
||||||
@@ -211,8 +220,8 @@ export class Control {
|
|||||||
while (startIndex > 0) {
|
while (startIndex > 0) {
|
||||||
const preElement = elementList[startIndex]
|
const preElement = elementList[startIndex]
|
||||||
if (
|
if (
|
||||||
preElement.controlId !== element.controlId
|
preElement.controlId !== element.controlId ||
|
||||||
|| preElement.controlComponent === ControlComponent.PREFIX
|
preElement.controlComponent === ControlComponent.PREFIX
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
newIndex: startIndex,
|
newIndex: startIndex,
|
||||||
@@ -260,7 +269,11 @@ export class Control {
|
|||||||
if (!~leftIndex && !~rightIndex) return startIndex
|
if (!~leftIndex && !~rightIndex) return startIndex
|
||||||
leftIndex = ~leftIndex ? leftIndex : 0
|
leftIndex = ~leftIndex ? leftIndex : 0
|
||||||
// 删除元素
|
// 删除元素
|
||||||
this.draw.spliceElementList(elementList, leftIndex + 1, rightIndex - leftIndex)
|
this.draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
leftIndex + 1,
|
||||||
|
rightIndex - leftIndex
|
||||||
|
)
|
||||||
return leftIndex
|
return leftIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +315,12 @@ export class Control {
|
|||||||
color: this.options.placeholderColor
|
color: this.options.placeholderColor
|
||||||
}
|
}
|
||||||
formatElementContext(elementList, [newElement], startIndex)
|
formatElementContext(elementList, [newElement], startIndex)
|
||||||
this.draw.spliceElementList(elementList, startIndex + p + 1, 0, newElement)
|
this.draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
startIndex + p + 1,
|
||||||
|
0,
|
||||||
|
newElement
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,5 +344,4 @@ export class Control {
|
|||||||
}
|
}
|
||||||
return this.activeControl.cut()
|
return this.activeControl.cut()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { IElement } from '../../../../interface/Element'
|
|||||||
import { Control } from '../Control'
|
import { Control } from '../Control'
|
||||||
|
|
||||||
export class CheckboxControl implements IControlInstance {
|
export class CheckboxControl implements IControlInstance {
|
||||||
|
|
||||||
private element: IElement
|
private element: IElement
|
||||||
private control: Control
|
private control: Control
|
||||||
|
|
||||||
@@ -124,5 +123,4 @@ export class CheckboxControl implements IControlInstance {
|
|||||||
public cut(): number {
|
public cut(): number {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { EDITOR_COMPONENT, EDITOR_PREFIX } from '../../../../dataset/constant/Editor'
|
import {
|
||||||
|
EDITOR_COMPONENT,
|
||||||
|
EDITOR_PREFIX
|
||||||
|
} from '../../../../dataset/constant/Editor'
|
||||||
import { ControlComponent } from '../../../../dataset/enum/Control'
|
import { ControlComponent } from '../../../../dataset/enum/Control'
|
||||||
import { EditorComponent } from '../../../../dataset/enum/Editor'
|
import { EditorComponent } from '../../../../dataset/enum/Editor'
|
||||||
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
||||||
@@ -9,7 +12,6 @@ import { formatElementContext } from '../../../../utils/element'
|
|||||||
import { Control } from '../Control'
|
import { Control } from '../Control'
|
||||||
|
|
||||||
export class SelectControl implements IControlInstance {
|
export class SelectControl implements IControlInstance {
|
||||||
|
|
||||||
private element: IElement
|
private element: IElement
|
||||||
private control: Control
|
private control: Control
|
||||||
private isPopup: boolean
|
private isPopup: boolean
|
||||||
@@ -105,8 +107,9 @@ export class SelectControl implements IControlInstance {
|
|||||||
return this.clearSelect()
|
return this.clearSelect()
|
||||||
} else {
|
} else {
|
||||||
const endNextElement = elementList[endIndex + 1]
|
const endNextElement = elementList[endIndex + 1]
|
||||||
if ((startElement.controlComponent === ControlComponent.PREFIX &&
|
if (
|
||||||
endNextElement.controlComponent === ControlComponent.PLACEHOLDER) ||
|
(startElement.controlComponent === ControlComponent.PREFIX &&
|
||||||
|
endNextElement.controlComponent === ControlComponent.PLACEHOLDER) ||
|
||||||
endNextElement.controlComponent === ControlComponent.POSTFIX ||
|
endNextElement.controlComponent === ControlComponent.POSTFIX ||
|
||||||
startElement.controlComponent === ControlComponent.PLACEHOLDER
|
startElement.controlComponent === ControlComponent.PLACEHOLDER
|
||||||
) {
|
) {
|
||||||
@@ -232,7 +235,12 @@ export class SelectControl implements IControlInstance {
|
|||||||
}
|
}
|
||||||
selectPopupContainer.append(ul)
|
selectPopupContainer.append(ul)
|
||||||
// 定位
|
// 定位
|
||||||
const { coordinate: { leftTop: [left, top] }, lineHeight } = position
|
const {
|
||||||
|
coordinate: {
|
||||||
|
leftTop: [left, top]
|
||||||
|
},
|
||||||
|
lineHeight
|
||||||
|
} = position
|
||||||
const preY = this.control.getPreY()
|
const preY = this.control.getPreY()
|
||||||
selectPopupContainer.style.left = `${left}px`
|
selectPopupContainer.style.left = `${left}px`
|
||||||
selectPopupContainer.style.top = `${top + preY + lineHeight}px`
|
selectPopupContainer.style.top = `${top + preY + lineHeight}px`
|
||||||
@@ -246,7 +254,9 @@ export class SelectControl implements IControlInstance {
|
|||||||
if (this.isPopup) return
|
if (this.isPopup) return
|
||||||
const { startIndex } = this.control.getRange()
|
const { startIndex } = this.control.getRange()
|
||||||
const elementList = this.control.getElementList()
|
const elementList = this.control.getElementList()
|
||||||
if (elementList[startIndex + 1]?.controlId !== this.element.controlId) return
|
if (elementList[startIndex + 1]?.controlId !== this.element.controlId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
this._createSelectPopupDom()
|
this._createSelectPopupDom()
|
||||||
this.isPopup = true
|
this.isPopup = true
|
||||||
}
|
}
|
||||||
@@ -256,5 +266,4 @@ export class SelectControl implements IControlInstance {
|
|||||||
this.selectDom?.remove()
|
this.selectDom?.remove()
|
||||||
this.isPopup = false
|
this.isPopup = false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { formatElementContext } from '../../../../utils/element'
|
|||||||
import { Control } from '../Control'
|
import { Control } from '../Control'
|
||||||
|
|
||||||
export class TextControl implements IControlInstance {
|
export class TextControl implements IControlInstance {
|
||||||
|
|
||||||
private element: IElement
|
private element: IElement
|
||||||
private control: Control
|
private control: Control
|
||||||
|
|
||||||
@@ -99,7 +98,11 @@ export class TextControl implements IControlInstance {
|
|||||||
if (evt.key === KeyMap.Backspace) {
|
if (evt.key === KeyMap.Backspace) {
|
||||||
// 移除选区元素
|
// 移除选区元素
|
||||||
if (startIndex !== endIndex) {
|
if (startIndex !== endIndex) {
|
||||||
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
startIndex + 1,
|
||||||
|
endIndex - startIndex
|
||||||
|
)
|
||||||
const value = this.getValue()
|
const value = this.getValue()
|
||||||
if (!value.length) {
|
if (!value.length) {
|
||||||
this.control.addPlaceholder(startIndex)
|
this.control.addPlaceholder(startIndex)
|
||||||
@@ -126,7 +129,11 @@ export class TextControl implements IControlInstance {
|
|||||||
} else if (evt.key === KeyMap.Delete) {
|
} else if (evt.key === KeyMap.Delete) {
|
||||||
// 移除选区元素
|
// 移除选区元素
|
||||||
if (startIndex !== endIndex) {
|
if (startIndex !== endIndex) {
|
||||||
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
startIndex + 1,
|
||||||
|
endIndex - startIndex
|
||||||
|
)
|
||||||
const value = this.getValue()
|
const value = this.getValue()
|
||||||
if (!value.length) {
|
if (!value.length) {
|
||||||
this.control.addPlaceholder(startIndex)
|
this.control.addPlaceholder(startIndex)
|
||||||
@@ -134,8 +141,9 @@ export class TextControl implements IControlInstance {
|
|||||||
return startIndex
|
return startIndex
|
||||||
} else {
|
} else {
|
||||||
const endNextElement = elementList[endIndex + 1]
|
const endNextElement = elementList[endIndex + 1]
|
||||||
if ((startElement.controlComponent === ControlComponent.PREFIX &&
|
if (
|
||||||
endNextElement.controlComponent === ControlComponent.PLACEHOLDER) ||
|
(startElement.controlComponent === ControlComponent.PREFIX &&
|
||||||
|
endNextElement.controlComponent === ControlComponent.PLACEHOLDER) ||
|
||||||
endNextElement.controlComponent === ControlComponent.POSTFIX ||
|
endNextElement.controlComponent === ControlComponent.POSTFIX ||
|
||||||
startElement.controlComponent === ControlComponent.PLACEHOLDER
|
startElement.controlComponent === ControlComponent.PLACEHOLDER
|
||||||
) {
|
) {
|
||||||
@@ -170,5 +178,4 @@ export class TextControl implements IControlInstance {
|
|||||||
}
|
}
|
||||||
return startIndex
|
return startIndex
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class Background {
|
export class Background {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
@@ -16,5 +15,4 @@ export class Background {
|
|||||||
ctx.fillRect(0, 0, width, height)
|
ctx.fillRect(0, 0, width, height)
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { Position } from '../../position/Position'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class Footer {
|
export class Footer {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private position: Position
|
private position: Position
|
||||||
private options: DeepRequired<IEditorOption>
|
private options: DeepRequired<IEditorOption>
|
||||||
@@ -81,13 +80,18 @@ export class Footer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getFooterBottom(): number {
|
public getFooterBottom(): number {
|
||||||
const { footer: { bottom, disabled }, scale } = this.options
|
const {
|
||||||
|
footer: { bottom, disabled },
|
||||||
|
scale
|
||||||
|
} = this.options
|
||||||
if (disabled) return 0
|
if (disabled) return 0
|
||||||
return Math.floor(bottom * scale)
|
return Math.floor(bottom * scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMaxHeight(): number {
|
public getMaxHeight(): number {
|
||||||
const { footer: { maxHeightRadio } } = this.options
|
const {
|
||||||
|
footer: { maxHeightRadio }
|
||||||
|
} = this.options
|
||||||
const height = this.draw.getHeight()
|
const height = this.draw.getHeight()
|
||||||
return Math.floor(height * maxHeightRadioMapping[maxHeightRadio])
|
return Math.floor(height * maxHeightRadioMapping[maxHeightRadio])
|
||||||
}
|
}
|
||||||
@@ -136,5 +140,4 @@ export class Footer {
|
|||||||
zone: EditorZone.FOOTER
|
zone: EditorZone.FOOTER
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { Position } from '../../position/Position'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class Header {
|
export class Header {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private position: Position
|
private position: Position
|
||||||
private options: DeepRequired<IEditorOption>
|
private options: DeepRequired<IEditorOption>
|
||||||
@@ -78,13 +77,18 @@ export class Header {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getHeaderTop(): number {
|
public getHeaderTop(): number {
|
||||||
const { header: { top, disabled }, scale } = this.options
|
const {
|
||||||
|
header: { top, disabled },
|
||||||
|
scale
|
||||||
|
} = this.options
|
||||||
if (disabled) return 0
|
if (disabled) return 0
|
||||||
return Math.floor(top * scale)
|
return Math.floor(top * scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMaxHeight(): number {
|
public getMaxHeight(): number {
|
||||||
const { header: { maxHeightRadio } } = this.options
|
const {
|
||||||
|
header: { maxHeightRadio }
|
||||||
|
} = this.options
|
||||||
const height = this.draw.getHeight()
|
const height = this.draw.getHeight()
|
||||||
return Math.floor(height * maxHeightRadioMapping[maxHeightRadio])
|
return Math.floor(height * maxHeightRadioMapping[maxHeightRadio])
|
||||||
}
|
}
|
||||||
@@ -133,5 +137,4 @@ export class Header {
|
|||||||
zone: EditorZone.HEADER
|
zone: EditorZone.HEADER
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { IEditorOption } from '../../../interface/Editor'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class Margin {
|
export class Margin {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
|
|
||||||
@@ -15,9 +14,10 @@ export class Margin {
|
|||||||
public render(ctx: CanvasRenderingContext2D, pageNo: number) {
|
public render(ctx: CanvasRenderingContext2D, pageNo: number) {
|
||||||
const { marginIndicatorColor, pageMode } = this.options
|
const { marginIndicatorColor, pageMode } = this.options
|
||||||
const width = this.draw.getWidth()
|
const width = this.draw.getWidth()
|
||||||
const height = pageMode === PageMode.CONTINUITY
|
const height =
|
||||||
? this.draw.getCanvasHeight(pageNo)
|
pageMode === PageMode.CONTINUITY
|
||||||
: this.draw.getHeight()
|
? this.draw.getCanvasHeight(pageNo)
|
||||||
|
: this.draw.getHeight()
|
||||||
const margins = this.draw.getMargins()
|
const margins = this.draw.getMargins()
|
||||||
const marginIndicatorSize = this.draw.getMarginIndicatorSize()
|
const marginIndicatorSize = this.draw.getMarginIndicatorSize()
|
||||||
ctx.save()
|
ctx.save()
|
||||||
@@ -27,7 +27,10 @@ export class Margin {
|
|||||||
const leftTopPoint: [number, number] = [margins[3], margins[0]]
|
const leftTopPoint: [number, number] = [margins[3], margins[0]]
|
||||||
const rightTopPoint: [number, number] = [width - margins[1], margins[0]]
|
const rightTopPoint: [number, number] = [width - margins[1], margins[0]]
|
||||||
const leftBottomPoint: [number, number] = [margins[3], height - margins[2]]
|
const leftBottomPoint: [number, number] = [margins[3], height - margins[2]]
|
||||||
const rightBottomPoint: [number, number] = [width - margins[1], height - margins[2]]
|
const rightBottomPoint: [number, number] = [
|
||||||
|
width - margins[1],
|
||||||
|
height - margins[2]
|
||||||
|
]
|
||||||
// 上左
|
// 上左
|
||||||
ctx.moveTo(leftTopPoint[0] - marginIndicatorSize, leftTopPoint[1])
|
ctx.moveTo(leftTopPoint[0] - marginIndicatorSize, leftTopPoint[1])
|
||||||
ctx.lineTo(...leftTopPoint)
|
ctx.lineTo(...leftTopPoint)
|
||||||
@@ -47,5 +50,4 @@ export class Margin {
|
|||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { convertNumberToChinese } from '../../../utils'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class PageNumber {
|
export class PageNumber {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private options: DeepRequired<IEditorOption>
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
@@ -21,7 +20,16 @@ export class PageNumber {
|
|||||||
const {
|
const {
|
||||||
scale,
|
scale,
|
||||||
pageMode,
|
pageMode,
|
||||||
pageNumber: { size, font, color, rowFlex, numberType, format, startPageNo, fromPageNo }
|
pageNumber: {
|
||||||
|
size,
|
||||||
|
font,
|
||||||
|
color,
|
||||||
|
rowFlex,
|
||||||
|
numberType,
|
||||||
|
format,
|
||||||
|
startPageNo,
|
||||||
|
fromPageNo
|
||||||
|
}
|
||||||
} = this.options
|
} = this.options
|
||||||
if (pageNo < fromPageNo) return
|
if (pageNo < fromPageNo) return
|
||||||
// 处理页码格式
|
// 处理页码格式
|
||||||
@@ -29,20 +37,27 @@ export class PageNumber {
|
|||||||
const pageNoReg = new RegExp(FORMAT_PLACEHOLDER.PAGE_NO)
|
const pageNoReg = new RegExp(FORMAT_PLACEHOLDER.PAGE_NO)
|
||||||
if (pageNoReg.test(text)) {
|
if (pageNoReg.test(text)) {
|
||||||
const realPageNo = pageNo + startPageNo - fromPageNo
|
const realPageNo = pageNo + startPageNo - fromPageNo
|
||||||
const pageNoText = numberType === NumberType.CHINESE ? convertNumberToChinese(realPageNo) : `${realPageNo}`
|
const pageNoText =
|
||||||
|
numberType === NumberType.CHINESE
|
||||||
|
? convertNumberToChinese(realPageNo)
|
||||||
|
: `${realPageNo}`
|
||||||
text = text.replace(pageNoReg, pageNoText)
|
text = text.replace(pageNoReg, pageNoText)
|
||||||
}
|
}
|
||||||
const pageCountReg = new RegExp(FORMAT_PLACEHOLDER.PAGE_COUNT)
|
const pageCountReg = new RegExp(FORMAT_PLACEHOLDER.PAGE_COUNT)
|
||||||
if (pageCountReg.test(text)) {
|
if (pageCountReg.test(text)) {
|
||||||
const pageCount = this.draw.getPageCount() - fromPageNo
|
const pageCount = this.draw.getPageCount() - fromPageNo
|
||||||
const pageCountText = numberType === NumberType.CHINESE ? convertNumberToChinese(pageCount) : `${pageCount}`
|
const pageCountText =
|
||||||
|
numberType === NumberType.CHINESE
|
||||||
|
? convertNumberToChinese(pageCount)
|
||||||
|
: `${pageCount}`
|
||||||
text = text.replace(pageCountReg, pageCountText)
|
text = text.replace(pageCountReg, pageCountText)
|
||||||
}
|
}
|
||||||
const width = this.draw.getWidth()
|
const width = this.draw.getWidth()
|
||||||
// 计算y位置
|
// 计算y位置
|
||||||
const height = pageMode === PageMode.CONTINUITY
|
const height =
|
||||||
? this.draw.getCanvasHeight(pageNo)
|
pageMode === PageMode.CONTINUITY
|
||||||
: this.draw.getHeight()
|
? this.draw.getCanvasHeight(pageNo)
|
||||||
|
: this.draw.getHeight()
|
||||||
const pageNumberBottom = this.draw.getPageNumberBottom()
|
const pageNumberBottom = this.draw.getPageNumberBottom()
|
||||||
const y = height - pageNumberBottom
|
const y = height - pageNumberBottom
|
||||||
ctx.save()
|
ctx.save()
|
||||||
@@ -62,5 +77,4 @@ export class PageNumber {
|
|||||||
ctx.fillText(text, x, y)
|
ctx.fillText(text, x, y)
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { Position } from '../../position/Position'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class Placeholder {
|
export class Placeholder {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private position: Position
|
private position: Position
|
||||||
private options: DeepRequired<IEditorOption>
|
private options: DeepRequired<IEditorOption>
|
||||||
@@ -61,16 +60,20 @@ export class Placeholder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D) {
|
public render(ctx: CanvasRenderingContext2D) {
|
||||||
const { placeholder: { data, font, size, color, opacity } } = this.options
|
const {
|
||||||
|
placeholder: { data, font, size, color, opacity }
|
||||||
|
} = this.options
|
||||||
if (!data) return
|
if (!data) return
|
||||||
this._recovery()
|
this._recovery()
|
||||||
// 构建元素列表并格式化
|
// 构建元素列表并格式化
|
||||||
this.elementList = [{
|
this.elementList = [
|
||||||
value: data,
|
{
|
||||||
font,
|
value: data,
|
||||||
size,
|
font,
|
||||||
color
|
size,
|
||||||
}]
|
color
|
||||||
|
}
|
||||||
|
]
|
||||||
formatElementList(this.elementList, {
|
formatElementList(this.elementList, {
|
||||||
editorOptions: this.options
|
editorOptions: this.options
|
||||||
})
|
})
|
||||||
@@ -90,5 +93,4 @@ export class Placeholder {
|
|||||||
})
|
})
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { DeepRequired } from '../../../interface/Common'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class Watermark {
|
export class Watermark {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private options: DeepRequired<IEditorOption>
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
@@ -13,7 +12,10 @@ export class Watermark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D) {
|
public render(ctx: CanvasRenderingContext2D) {
|
||||||
const { watermark: { data, opacity, font, size, color }, scale } = this.options
|
const {
|
||||||
|
watermark: { data, opacity, font, size, color },
|
||||||
|
scale
|
||||||
|
} = this.options
|
||||||
const width = this.draw.getWidth()
|
const width = this.draw.getWidth()
|
||||||
const height = this.draw.getHeight()
|
const height = this.draw.getHeight()
|
||||||
const x = width / 2
|
const x = width / 2
|
||||||
@@ -25,9 +27,12 @@ export class Watermark {
|
|||||||
// 移动到中心位置再旋转
|
// 移动到中心位置再旋转
|
||||||
const measureText = ctx.measureText(data)
|
const measureText = ctx.measureText(data)
|
||||||
ctx.translate(x, y)
|
ctx.translate(x, y)
|
||||||
ctx.rotate(-45 * Math.PI / 180)
|
ctx.rotate((-45 * Math.PI) / 180)
|
||||||
ctx.fillText(data, - measureText.width / 2, measureText.actualBoundingBoxAscent - size / 2)
|
ctx.fillText(
|
||||||
|
data,
|
||||||
|
-measureText.width / 2,
|
||||||
|
measureText.actualBoundingBoxAscent - size / 2
|
||||||
|
)
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -11,12 +11,11 @@ import { Position } from '../../position/Position'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export interface INavigateInfo {
|
export interface INavigateInfo {
|
||||||
index: number;
|
index: number
|
||||||
count: number;
|
count: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Search {
|
export class Search {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
private position: Position
|
private position: Position
|
||||||
@@ -49,7 +48,8 @@ export class Search {
|
|||||||
} else {
|
} else {
|
||||||
let index = this.searchNavigateIndex - 1
|
let index = this.searchNavigateIndex - 1
|
||||||
let isExistPre = false
|
let isExistPre = false
|
||||||
const searchNavigateId = this.searchMatchList[this.searchNavigateIndex].groupId
|
const searchNavigateId =
|
||||||
|
this.searchMatchList[this.searchNavigateIndex].groupId
|
||||||
while (index >= 0) {
|
while (index >= 0) {
|
||||||
const match = this.searchMatchList[index]
|
const match = this.searchMatchList[index]
|
||||||
if (searchNavigateId !== match.groupId) {
|
if (searchNavigateId !== match.groupId) {
|
||||||
@@ -60,9 +60,11 @@ export class Search {
|
|||||||
index--
|
index--
|
||||||
}
|
}
|
||||||
if (!isExistPre) {
|
if (!isExistPre) {
|
||||||
const lastSearchMatch = this.searchMatchList[this.searchMatchList.length - 1]
|
const lastSearchMatch =
|
||||||
|
this.searchMatchList[this.searchMatchList.length - 1]
|
||||||
if (lastSearchMatch.groupId === searchNavigateId) return null
|
if (lastSearchMatch.groupId === searchNavigateId) return null
|
||||||
this.searchNavigateIndex = this.searchMatchList.length - 1 - (this.searchKeyword.length - 1)
|
this.searchNavigateIndex =
|
||||||
|
this.searchMatchList.length - 1 - (this.searchKeyword.length - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.searchNavigateIndex
|
return this.searchNavigateIndex
|
||||||
@@ -75,7 +77,8 @@ export class Search {
|
|||||||
} else {
|
} else {
|
||||||
let index = this.searchNavigateIndex + 1
|
let index = this.searchNavigateIndex + 1
|
||||||
let isExistNext = false
|
let isExistNext = false
|
||||||
const searchNavigateId = this.searchMatchList[this.searchNavigateIndex].groupId
|
const searchNavigateId =
|
||||||
|
this.searchMatchList[this.searchNavigateIndex].groupId
|
||||||
while (index < this.searchMatchList.length) {
|
while (index < this.searchMatchList.length) {
|
||||||
const match = this.searchMatchList[index]
|
const match = this.searchMatchList[index]
|
||||||
if (searchNavigateId !== match.groupId) {
|
if (searchNavigateId !== match.groupId) {
|
||||||
@@ -95,7 +98,10 @@ export class Search {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public searchNavigateScrollIntoView(position: IElementPosition) {
|
public searchNavigateScrollIntoView(position: IElementPosition) {
|
||||||
const { coordinate: { leftTop, leftBottom, rightTop }, pageNo } = position
|
const {
|
||||||
|
coordinate: { leftTop, leftBottom, rightTop },
|
||||||
|
pageNo
|
||||||
|
} = position
|
||||||
const height = this.draw.getHeight()
|
const height = this.draw.getHeight()
|
||||||
const pageGap = this.draw.getPageGap()
|
const pageGap = this.draw.getPageGap()
|
||||||
const preY = pageNo * (height + pageGap)
|
const preY = pageNo * (height + pageGap)
|
||||||
@@ -105,7 +111,9 @@ export class Search {
|
|||||||
// 扩大搜索词尺寸,使可视范围更广
|
// 扩大搜索词尺寸,使可视范围更广
|
||||||
const ANCHOR_OVERFLOW_SIZE = 50
|
const ANCHOR_OVERFLOW_SIZE = 50
|
||||||
anchor.style.width = `${rightTop[0] - leftTop[0] + ANCHOR_OVERFLOW_SIZE}px`
|
anchor.style.width = `${rightTop[0] - leftTop[0] + ANCHOR_OVERFLOW_SIZE}px`
|
||||||
anchor.style.height = `${leftBottom[1] - leftTop[1] + ANCHOR_OVERFLOW_SIZE}px`
|
anchor.style.height = `${
|
||||||
|
leftBottom[1] - leftTop[1] + ANCHOR_OVERFLOW_SIZE
|
||||||
|
}px`
|
||||||
anchor.style.left = `${leftTop[0]}px`
|
anchor.style.left = `${leftTop[0]}px`
|
||||||
anchor.style.top = `${leftTop[1] + preY}px`
|
anchor.style.top = `${leftTop[1] + preY}px`
|
||||||
this.draw.getContainer().append(anchor)
|
this.draw.getContainer().append(anchor)
|
||||||
@@ -127,9 +135,10 @@ export class Search {
|
|||||||
|
|
||||||
public getSearchNavigateInfo(): null | INavigateInfo {
|
public getSearchNavigateInfo(): null | INavigateInfo {
|
||||||
if (!this.searchKeyword || !this.searchMatchList.length) return null
|
if (!this.searchKeyword || !this.searchMatchList.length) return null
|
||||||
const index = this.searchNavigateIndex !== null
|
const index =
|
||||||
? (this.searchNavigateIndex / this.searchKeyword.length) + 1
|
this.searchNavigateIndex !== null
|
||||||
: 0
|
? this.searchNavigateIndex / this.searchKeyword.length + 1
|
||||||
|
: 0
|
||||||
let count = 0
|
let count = 0
|
||||||
let groupId = null
|
let groupId = null
|
||||||
for (let s = 0; s < this.searchMatchList.length; s++) {
|
for (let s = 0; s < this.searchMatchList.length; s++) {
|
||||||
@@ -148,7 +157,11 @@ export class Search {
|
|||||||
const keyword = payload.toLocaleLowerCase()
|
const keyword = payload.toLocaleLowerCase()
|
||||||
const searchMatchList: ISearchResult[] = []
|
const searchMatchList: ISearchResult[] = []
|
||||||
// 分组
|
// 分组
|
||||||
const elementListGroup: { type: EditorContext, elementList: IElement[], index: number }[] = []
|
const elementListGroup: {
|
||||||
|
type: EditorContext
|
||||||
|
elementList: IElement[]
|
||||||
|
index: number
|
||||||
|
}[] = []
|
||||||
const originalElementList = this.draw.getOriginalElementList()
|
const originalElementList = this.draw.getOriginalElementList()
|
||||||
const originalElementListLength = originalElementList.length
|
const originalElementListLength = originalElementList.length
|
||||||
// 查找表格所在位置
|
// 查找表格所在位置
|
||||||
@@ -162,7 +175,9 @@ export class Search {
|
|||||||
let i = 0
|
let i = 0
|
||||||
let elementIndex = 0
|
let elementIndex = 0
|
||||||
while (elementIndex < originalElementListLength - 1) {
|
while (elementIndex < originalElementListLength - 1) {
|
||||||
const endIndex = tableIndexList.length ? tableIndexList[i] : originalElementListLength
|
const endIndex = tableIndexList.length
|
||||||
|
? tableIndexList[i]
|
||||||
|
: originalElementListLength
|
||||||
const pageElement = originalElementList.slice(elementIndex, endIndex)
|
const pageElement = originalElementList.slice(elementIndex, endIndex)
|
||||||
if (pageElement.length) {
|
if (pageElement.length) {
|
||||||
elementListGroup.push({
|
elementListGroup.push({
|
||||||
@@ -183,12 +198,21 @@ export class Search {
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
// 搜索文本
|
// 搜索文本
|
||||||
function searchClosure(payload: string | null, type: EditorContext, elementList: IElement[], restArgs?: ISearchResultRestArgs) {
|
function searchClosure(
|
||||||
|
payload: string | null,
|
||||||
|
type: EditorContext,
|
||||||
|
elementList: IElement[],
|
||||||
|
restArgs?: ISearchResultRestArgs
|
||||||
|
) {
|
||||||
if (!payload) return
|
if (!payload) return
|
||||||
const text = elementList
|
const text = elementList
|
||||||
.map(e => !e.type || (TEXTLIKE_ELEMENT_TYPE.includes(e.type) && e.controlComponent !== ControlComponent.CHECKBOX)
|
.map(e =>
|
||||||
? e.value
|
!e.type ||
|
||||||
: ZERO)
|
(TEXTLIKE_ELEMENT_TYPE.includes(e.type) &&
|
||||||
|
e.controlComponent !== ControlComponent.CHECKBOX)
|
||||||
|
? e.value
|
||||||
|
: ZERO
|
||||||
|
)
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join('')
|
.join('')
|
||||||
.toLocaleLowerCase()
|
.toLocaleLowerCase()
|
||||||
@@ -239,8 +263,15 @@ export class Search {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, pageIndex: number) {
|
public render(ctx: CanvasRenderingContext2D, pageIndex: number) {
|
||||||
if (!this.searchMatchList || !this.searchMatchList.length || !this.searchKeyword) return
|
if (
|
||||||
const { searchMatchAlpha, searchMatchColor, searchNavigateMatchColor } = this.options
|
!this.searchMatchList ||
|
||||||
|
!this.searchMatchList.length ||
|
||||||
|
!this.searchKeyword
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { searchMatchAlpha, searchMatchColor, searchNavigateMatchColor } =
|
||||||
|
this.options
|
||||||
const positionList = this.position.getOriginalPositionList()
|
const positionList = this.position.getOriginalPositionList()
|
||||||
const elementList = this.draw.getOriginalElementList()
|
const elementList = this.draw.getOriginalElementList()
|
||||||
ctx.save()
|
ctx.save()
|
||||||
@@ -250,12 +281,17 @@ export class Search {
|
|||||||
let position: IElementPosition | null = null
|
let position: IElementPosition | null = null
|
||||||
if (searchMatch.type === EditorContext.TABLE) {
|
if (searchMatch.type === EditorContext.TABLE) {
|
||||||
const { tableIndex, trIndex, tdIndex, index } = searchMatch
|
const { tableIndex, trIndex, tdIndex, index } = searchMatch
|
||||||
position = elementList[tableIndex!]?.trList![trIndex!].tdList[tdIndex!]?.positionList![index]
|
position =
|
||||||
|
elementList[tableIndex!]?.trList![trIndex!].tdList[tdIndex!]
|
||||||
|
?.positionList![index]
|
||||||
} else {
|
} else {
|
||||||
position = positionList[searchMatch.index]
|
position = positionList[searchMatch.index]
|
||||||
}
|
}
|
||||||
if (!position) continue
|
if (!position) continue
|
||||||
const { coordinate: { leftTop, leftBottom, rightTop }, pageNo } = position
|
const {
|
||||||
|
coordinate: { leftTop, leftBottom, rightTop },
|
||||||
|
pageNo
|
||||||
|
} = position
|
||||||
if (pageNo !== pageIndex) continue
|
if (pageNo !== pageIndex) continue
|
||||||
// 高亮并定位当前搜索词
|
// 高亮并定位当前搜索词
|
||||||
const searchMatchIndexList = this.getSearchNavigateIndexList()
|
const searchMatchIndexList = this.getSearchNavigateIndexList()
|
||||||
@@ -277,5 +313,4 @@ export class Search {
|
|||||||
}
|
}
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,15 +4,22 @@ import { IRowElement } from '../../../interface/Row'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class CheckboxParticle {
|
export class CheckboxParticle {
|
||||||
|
|
||||||
private options: DeepRequired<IEditorOption>
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) {
|
public render(
|
||||||
const { checkbox: { gap, lineWidth, fillStyle, fontStyle }, scale } = this.options
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IRowElement,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
|
const {
|
||||||
|
checkbox: { gap, lineWidth, fillStyle, fontStyle },
|
||||||
|
scale
|
||||||
|
} = this.options
|
||||||
const { metrics, checkbox } = element
|
const { metrics, checkbox } = element
|
||||||
// left top 四舍五入避免1像素问题
|
// left top 四舍五入避免1像素问题
|
||||||
const left = Math.round(x + gap)
|
const left = Math.round(x + gap)
|
||||||
@@ -50,5 +57,4 @@ export class CheckboxParticle {
|
|||||||
ctx.closePath()
|
ctx.closePath()
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { IRowElement } from '../../../interface/Row'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class HyperlinkParticle {
|
export class HyperlinkParticle {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
private container: HTMLDivElement
|
private container: HTMLDivElement
|
||||||
@@ -17,7 +16,8 @@ export class HyperlinkParticle {
|
|||||||
this.draw = draw
|
this.draw = draw
|
||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
this.container = draw.getContainer()
|
this.container = draw.getContainer()
|
||||||
const { hyperlinkPopupContainer, hyperlinkDom } = this._createHyperlinkPopupDom()
|
const { hyperlinkPopupContainer, hyperlinkDom } =
|
||||||
|
this._createHyperlinkPopupDom()
|
||||||
this.hyperlinkDom = hyperlinkDom
|
this.hyperlinkDom = hyperlinkDom
|
||||||
this.hyperlinkPopupContainer = hyperlinkPopupContainer
|
this.hyperlinkPopupContainer = hyperlinkPopupContainer
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,12 @@ export class HyperlinkParticle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public drawHyperlinkPopup(element: IElement, position: IElementPosition) {
|
public drawHyperlinkPopup(element: IElement, position: IElementPosition) {
|
||||||
const { coordinate: { leftTop: [left, top] }, lineHeight } = position
|
const {
|
||||||
|
coordinate: {
|
||||||
|
leftTop: [left, top]
|
||||||
|
},
|
||||||
|
lineHeight
|
||||||
|
} = position
|
||||||
const height = this.draw.getHeight()
|
const height = this.draw.getHeight()
|
||||||
const pageGap = this.draw.getPageGap()
|
const pageGap = this.draw.getPageGap()
|
||||||
const preY = this.draw.getPageNo() * (height + pageGap)
|
const preY = this.draw.getPageNo() * (height + pageGap)
|
||||||
@@ -60,7 +65,12 @@ export class HyperlinkParticle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) {
|
public render(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IRowElement,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.font = element.style
|
ctx.font = element.style
|
||||||
if (!element.color) {
|
if (!element.color) {
|
||||||
@@ -73,5 +83,4 @@ export class HyperlinkParticle {
|
|||||||
ctx.fillText(element.value, x, y)
|
ctx.fillText(element.value, x, y)
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { convertStringToBase64 } from '../../../utils'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class ImageParticle {
|
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>
|
||||||
@@ -26,18 +25,27 @@ export class ImageParticle {
|
|||||||
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
||||||
<rect width="${width}" height="${height}" fill="url(#mosaic)" />
|
<rect width="${width}" height="${height}" fill="url(#mosaic)" />
|
||||||
<defs>
|
<defs>
|
||||||
<pattern id="mosaic" x="${x}" y="${y}" width="${tileSize * 2}" height="${tileSize * 2}" patternUnits="userSpaceOnUse">
|
<pattern id="mosaic" x="${x}" y="${y}" width="${
|
||||||
|
tileSize * 2
|
||||||
|
}" height="${tileSize * 2}" patternUnits="userSpaceOnUse">
|
||||||
<rect width="${tileSize}" height="${tileSize}" fill="#cccccc" />
|
<rect width="${tileSize}" height="${tileSize}" fill="#cccccc" />
|
||||||
<rect width="${tileSize}" height="${tileSize}" fill="#cccccc" transform="translate(${tileSize}, ${tileSize})" />
|
<rect width="${tileSize}" height="${tileSize}" fill="#cccccc" transform="translate(${tileSize}, ${tileSize})" />
|
||||||
</pattern>
|
</pattern>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>`
|
</svg>`
|
||||||
const fallbackImage = new Image()
|
const fallbackImage = new Image()
|
||||||
fallbackImage.src = `data:image/svg+xml;base64,${convertStringToBase64(svg)}`
|
fallbackImage.src = `data:image/svg+xml;base64,${convertStringToBase64(
|
||||||
|
svg
|
||||||
|
)}`
|
||||||
return fallbackImage
|
return fallbackImage
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IElement, x: number, y: number) {
|
public render(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IElement,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
const { scale } = this.options
|
const { scale } = this.options
|
||||||
const width = element.width! * scale
|
const width = element.width! * scale
|
||||||
const height = element.height! * scale
|
const height = element.height! * scale
|
||||||
@@ -54,7 +62,7 @@ export class ImageParticle {
|
|||||||
this.imageCache.set(element.id!, img)
|
this.imageCache.set(element.id!, img)
|
||||||
resolve(element)
|
resolve(element)
|
||||||
}
|
}
|
||||||
img.onerror = (error) => {
|
img.onerror = error => {
|
||||||
const fallbackImage = this.getFallbackImage(width, height)
|
const fallbackImage = this.getFallbackImage(width, height)
|
||||||
fallbackImage.onload = () => {
|
fallbackImage.onload = () => {
|
||||||
ctx.drawImage(fallbackImage, x, y, width, height)
|
ctx.drawImage(fallbackImage, x, y, width, height)
|
||||||
@@ -66,5 +74,4 @@ export class ImageParticle {
|
|||||||
this.addImageObserver(imageLoadPromise)
|
this.addImageObserver(imageLoadPromise)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import { IRow } from '../../../interface/Row'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class ListParticle {
|
export class ListParticle {
|
||||||
|
|
||||||
private options: DeepRequired<IEditorOption>
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
// 非递增样式直接返回默认值
|
// 非递增样式直接返回默认值
|
||||||
@@ -21,7 +20,10 @@ export class ListParticle {
|
|||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
public computeListStyle(ctx: CanvasRenderingContext2D, elementList: IElement[]): Map<string, number> {
|
public computeListStyle(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
elementList: IElement[]
|
||||||
|
): Map<string, number> {
|
||||||
const listStyleMap = new Map<string, number>()
|
const listStyleMap = new Map<string, number>()
|
||||||
let start = 0
|
let start = 0
|
||||||
let curListId = elementList[start].listId
|
let curListId = elementList[start].listId
|
||||||
@@ -51,11 +53,17 @@ export class ListParticle {
|
|||||||
return listStyleMap
|
return listStyleMap
|
||||||
}
|
}
|
||||||
|
|
||||||
public getListStyleWidth(ctx: CanvasRenderingContext2D, listElementList: IElement[]): number {
|
public getListStyleWidth(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
listElementList: IElement[]
|
||||||
|
): number {
|
||||||
const { scale } = this.options
|
const { scale } = this.options
|
||||||
const startElement = listElementList[0]
|
const startElement = listElementList[0]
|
||||||
// 非递增样式返回固定值
|
// 非递增样式返回固定值
|
||||||
if (startElement.listStyle && startElement.listStyle !== ListStyle.DECIMAL) {
|
if (
|
||||||
|
startElement.listStyle &&
|
||||||
|
startElement.listStyle !== ListStyle.DECIMAL
|
||||||
|
) {
|
||||||
return this.UN_COUNT_STYLE_WIDTH * scale
|
return this.UN_COUNT_STYLE_WIDTH * scale
|
||||||
}
|
}
|
||||||
// 计算列表数量
|
// 计算列表数量
|
||||||
@@ -67,23 +75,35 @@ export class ListParticle {
|
|||||||
}, 0)
|
}, 0)
|
||||||
if (!count) return 0
|
if (!count) return 0
|
||||||
// 以递增样式最大宽度为准
|
// 以递增样式最大宽度为准
|
||||||
const text = `${this.MEASURE_BASE_TEXT.repeat(String(count).length)}${KeyMap.PERIOD}`
|
const text = `${this.MEASURE_BASE_TEXT.repeat(String(count).length)}${
|
||||||
|
KeyMap.PERIOD
|
||||||
|
}`
|
||||||
const textMetrics = ctx.measureText(text)
|
const textMetrics = ctx.measureText(text)
|
||||||
return Math.ceil((textMetrics.width + this.LIST_GAP) * scale)
|
return Math.ceil((textMetrics.width + this.LIST_GAP) * scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
public drawListStyle(ctx: CanvasRenderingContext2D, row: IRow, position: IElementPosition) {
|
public drawListStyle(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
row: IRow,
|
||||||
|
position: IElementPosition
|
||||||
|
) {
|
||||||
const { elementList, offsetX, listIndex, ascent } = row
|
const { elementList, offsetX, listIndex, ascent } = row
|
||||||
const startElement = elementList[0]
|
const startElement = elementList[0]
|
||||||
if (startElement.value !== ZERO || startElement.listWrap) return
|
if (startElement.value !== ZERO || startElement.listWrap) return
|
||||||
let text = ''
|
let text = ''
|
||||||
if (startElement.listType === ListType.UL) {
|
if (startElement.listType === ListType.UL) {
|
||||||
text = ulStyleMapping[<UlStyle><unknown>startElement.listStyle] || ulStyleMapping[UlStyle.DISC]
|
text =
|
||||||
|
ulStyleMapping[<UlStyle>(<unknown>startElement.listStyle)] ||
|
||||||
|
ulStyleMapping[UlStyle.DISC]
|
||||||
} else {
|
} else {
|
||||||
text = `${listIndex! + 1}${KeyMap.PERIOD}`
|
text = `${listIndex! + 1}${KeyMap.PERIOD}`
|
||||||
}
|
}
|
||||||
if (!text) return
|
if (!text) return
|
||||||
const { coordinate: { leftTop: [startX, startY] } } = position
|
const {
|
||||||
|
coordinate: {
|
||||||
|
leftTop: [startX, startY]
|
||||||
|
}
|
||||||
|
} = position
|
||||||
const x = startX - offsetX!
|
const x = startX - offsetX!
|
||||||
const y = startY + ascent
|
const y = startY + ascent
|
||||||
const { defaultFont, defaultSize, scale } = this.options
|
const { defaultFont, defaultSize, scale } = this.options
|
||||||
@@ -92,5 +112,4 @@ export class ListParticle {
|
|||||||
ctx.fillText(text, x, y)
|
ctx.fillText(text, x, y)
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { IRowElement } from '../../../interface/Row'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class PageBreakParticle {
|
export class PageBreakParticle {
|
||||||
|
|
||||||
static readonly font: string = 'Yahei'
|
static readonly font: string = 'Yahei'
|
||||||
static readonly fontSize: number = 12
|
static readonly fontSize: number = 12
|
||||||
static readonly displayName: string = '分页符'
|
static readonly displayName: string = '分页符'
|
||||||
@@ -17,12 +16,18 @@ export class PageBreakParticle {
|
|||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) {
|
public render(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IRowElement,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
const { font, fontSize, displayName, lineDash } = PageBreakParticle
|
const { font, fontSize, displayName, lineDash } = PageBreakParticle
|
||||||
const { scale, defaultRowMargin } = this.options
|
const { scale, defaultRowMargin } = this.options
|
||||||
const size = fontSize * scale
|
const size = fontSize * scale
|
||||||
const elementWidth = element.width!
|
const elementWidth = element.width!
|
||||||
const offsetY = this.draw.getDefaultBasicRowMarginHeight() * defaultRowMargin
|
const offsetY =
|
||||||
|
this.draw.getDefaultBasicRowMarginHeight() * defaultRowMargin
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.font = `${size}px ${font}`
|
ctx.font = `${size}px ${font}`
|
||||||
const textMeasure = ctx.measureText(displayName)
|
const textMeasure = ctx.measureText(displayName)
|
||||||
@@ -37,8 +42,11 @@ export class PageBreakParticle {
|
|||||||
ctx.lineTo(x + elementWidth, y)
|
ctx.lineTo(x + elementWidth, y)
|
||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
// 文字
|
// 文字
|
||||||
ctx.fillText(displayName, x + halfX, y + textMeasure.actualBoundingBoxAscent - size / 2)
|
ctx.fillText(
|
||||||
|
displayName,
|
||||||
|
x + halfX,
|
||||||
|
y + textMeasure.actualBoundingBoxAscent - size / 2
|
||||||
|
)
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import { IRowElement } from '../../../interface/Row'
|
import { IRowElement } from '../../../interface/Row'
|
||||||
export class SeparatorParticle {
|
export class SeparatorParticle {
|
||||||
|
public render(
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) {
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IRowElement,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
ctx.save()
|
ctx.save()
|
||||||
if (element.color) {
|
if (element.color) {
|
||||||
ctx.strokeStyle = element.color
|
ctx.strokeStyle = element.color
|
||||||
@@ -16,5 +20,4 @@ export class SeparatorParticle {
|
|||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import { IRowElement } from '../../../interface/Row'
|
import { IRowElement } from '../../../interface/Row'
|
||||||
|
|
||||||
export class SubscriptParticle {
|
export class SubscriptParticle {
|
||||||
|
public render(
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) {
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IRowElement,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.font = element.style
|
ctx.font = element.style
|
||||||
if (element.color) {
|
if (element.color) {
|
||||||
@@ -11,5 +15,4 @@ export class SubscriptParticle {
|
|||||||
ctx.fillText(element.value, x, y + element.metrics.height / 2)
|
ctx.fillText(element.value, x, y + element.metrics.height / 2)
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import { IRowElement } from '../../../interface/Row'
|
import { IRowElement } from '../../../interface/Row'
|
||||||
|
|
||||||
export class SuperscriptParticle {
|
export class SuperscriptParticle {
|
||||||
|
public render(
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) {
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IRowElement,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.font = element.style
|
ctx.font = element.style
|
||||||
if (element.color) {
|
if (element.color) {
|
||||||
@@ -11,5 +15,4 @@ export class SuperscriptParticle {
|
|||||||
ctx.fillText(element.value, x, y - element.metrics.height / 2)
|
ctx.fillText(element.value, x, y - element.metrics.height / 2)
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,12 +5,11 @@ import { IRowElement } from '../../../interface/Row'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export interface IMeasureWordResult {
|
export interface IMeasureWordResult {
|
||||||
width: number;
|
width: number
|
||||||
endElement: IElement;
|
endElement: IElement
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TextParticle {
|
export class TextParticle {
|
||||||
|
|
||||||
private ctx: CanvasRenderingContext2D
|
private ctx: CanvasRenderingContext2D
|
||||||
private curX: number
|
private curX: number
|
||||||
private curY: number
|
private curY: number
|
||||||
@@ -28,7 +27,11 @@ export class TextParticle {
|
|||||||
this.cacheMeasureText = new Map()
|
this.cacheMeasureText = new Map()
|
||||||
}
|
}
|
||||||
|
|
||||||
public measureWord(ctx: CanvasRenderingContext2D, elementList: IElement[], curIndex: number): IMeasureWordResult {
|
public measureWord(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
elementList: IElement[],
|
||||||
|
curIndex: number
|
||||||
|
): IMeasureWordResult {
|
||||||
let width = 0
|
let width = 0
|
||||||
let endElement: IElement = elementList[curIndex]
|
let endElement: IElement = elementList[curIndex]
|
||||||
let i = curIndex
|
let i = curIndex
|
||||||
@@ -47,12 +50,18 @@ export class TextParticle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public measurePunctuationWidth(ctx: CanvasRenderingContext2D, element: IElement): number {
|
public measurePunctuationWidth(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IElement
|
||||||
|
): number {
|
||||||
if (!element || !PUNCTUATION_LIST.includes(element.value)) return 0
|
if (!element || !PUNCTUATION_LIST.includes(element.value)) return 0
|
||||||
return this.measureText(ctx, element).width
|
return this.measureText(ctx, element).width
|
||||||
}
|
}
|
||||||
|
|
||||||
public measureText(ctx: CanvasRenderingContext2D, element: IElement): TextMetrics {
|
public measureText(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IElement
|
||||||
|
): TextMetrics {
|
||||||
const id = `${element.value}${ctx.font}`
|
const id = `${element.value}${ctx.font}`
|
||||||
const cacheTextMetrics = this.cacheMeasureText.get(id)
|
const cacheTextMetrics = this.cacheMeasureText.get(id)
|
||||||
if (cacheTextMetrics) {
|
if (cacheTextMetrics) {
|
||||||
@@ -68,7 +77,12 @@ export class TextParticle {
|
|||||||
this.text = ''
|
this.text = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
public record(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) {
|
public record(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IRowElement,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
this.ctx = ctx
|
this.ctx = ctx
|
||||||
// 主动完成的重设起始点
|
// 主动完成的重设起始点
|
||||||
if (!this.text) {
|
if (!this.text) {
|
||||||
@@ -77,7 +91,7 @@ export class TextParticle {
|
|||||||
// 样式发生改变
|
// 样式发生改变
|
||||||
if (
|
if (
|
||||||
(this.curStyle && element.style !== this.curStyle) ||
|
(this.curStyle && element.style !== this.curStyle) ||
|
||||||
(element.color !== this.curColor)
|
element.color !== this.curColor
|
||||||
) {
|
) {
|
||||||
this.complete()
|
this.complete()
|
||||||
this._setCurXY(x, y)
|
this._setCurXY(x, y)
|
||||||
@@ -102,5 +116,4 @@ export class TextParticle {
|
|||||||
this.ctx.fillText(this.text, this.curX, this.curY)
|
this.ctx.fillText(this.text, this.curX, this.curY)
|
||||||
this.ctx.restore()
|
this.ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { Draw } from '../../Draw'
|
|||||||
import { BaseBlock } from './modules/BaseBlock'
|
import { BaseBlock } from './modules/BaseBlock'
|
||||||
|
|
||||||
export class BlockParticle {
|
export class BlockParticle {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private container: HTMLDivElement
|
private container: HTMLDivElement
|
||||||
private blockContainer: HTMLDivElement
|
private blockContainer: HTMLDivElement
|
||||||
@@ -64,5 +63,4 @@ export class BlockParticle {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { IFrameBlock } from './IFrameBlock'
|
|||||||
import { VideoBlock } from './VideoBlock'
|
import { VideoBlock } from './VideoBlock'
|
||||||
|
|
||||||
export class BaseBlock {
|
export class BaseBlock {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private element: IRowElement
|
private element: IRowElement
|
||||||
private block: IFrameBlock | VideoBlock | null
|
private block: IFrameBlock | VideoBlock | null
|
||||||
@@ -60,5 +59,4 @@ export class BaseBlock {
|
|||||||
public remove() {
|
public remove() {
|
||||||
this.blockItem.remove()
|
this.blockItem.remove()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { IRowElement } from '../../../../../interface/Row'
|
import { IRowElement } from '../../../../../interface/Row'
|
||||||
|
|
||||||
export class IFrameBlock {
|
export class IFrameBlock {
|
||||||
|
|
||||||
private static readonly sandbox = [
|
private static readonly sandbox = [
|
||||||
'allow-forms',
|
'allow-forms',
|
||||||
'allow-scripts',
|
'allow-scripts',
|
||||||
@@ -24,5 +23,4 @@ export class IFrameBlock {
|
|||||||
iframe.src = block.iframeBlock?.src || ''
|
iframe.src = block.iframeBlock?.src || ''
|
||||||
blockItemContainer.append(iframe)
|
blockItemContainer.append(iframe)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { IRowElement } from '../../../../../interface/Row'
|
import { IRowElement } from '../../../../../interface/Row'
|
||||||
|
|
||||||
export class VideoBlock {
|
export class VideoBlock {
|
||||||
|
|
||||||
private element: IRowElement
|
private element: IRowElement
|
||||||
|
|
||||||
constructor(element: IRowElement) {
|
constructor(element: IRowElement) {
|
||||||
@@ -19,5 +18,4 @@ export class VideoBlock {
|
|||||||
video.crossOrigin = 'anonymous'
|
video.crossOrigin = 'anonymous'
|
||||||
blockItemContainer.append(video)
|
blockItemContainer.append(video)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { Draw } from '../../Draw'
|
|||||||
import { DatePicker } from './DatePicker'
|
import { DatePicker } from './DatePicker'
|
||||||
|
|
||||||
export class DateParticle {
|
export class DateParticle {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private range: RangeManager
|
private range: RangeManager
|
||||||
private datePicker: DatePicker
|
private datePicker: DatePicker
|
||||||
@@ -32,7 +31,7 @@ export class DateParticle {
|
|||||||
wed: t('datePicker.weeks.wed'),
|
wed: t('datePicker.weeks.wed'),
|
||||||
thu: t('datePicker.weeks.thu'),
|
thu: t('datePicker.weeks.thu'),
|
||||||
fri: t('datePicker.weeks.fri'),
|
fri: t('datePicker.weeks.fri'),
|
||||||
sat: t('datePicker.weeks.sat'),
|
sat: t('datePicker.weeks.sat')
|
||||||
},
|
},
|
||||||
year: t('datePicker.year'),
|
year: t('datePicker.year'),
|
||||||
month: t('datePicker.month'),
|
month: t('datePicker.month'),
|
||||||
@@ -51,16 +50,22 @@ export class DateParticle {
|
|||||||
const elementList = this.draw.getElementList()
|
const elementList = this.draw.getElementList()
|
||||||
const startElement = elementList[leftIndex + 1]
|
const startElement = elementList[leftIndex + 1]
|
||||||
// 删除旧时间
|
// 删除旧时间
|
||||||
this.draw.spliceElementList(elementList, leftIndex + 1, rightIndex - leftIndex)
|
this.draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
leftIndex + 1,
|
||||||
|
rightIndex - leftIndex
|
||||||
|
)
|
||||||
this.range.setRange(leftIndex, leftIndex)
|
this.range.setRange(leftIndex, leftIndex)
|
||||||
// 插入新时间
|
// 插入新时间
|
||||||
const dateElement: IElement = {
|
const dateElement: IElement = {
|
||||||
type: ElementType.DATE,
|
type: ElementType.DATE,
|
||||||
value: '',
|
value: '',
|
||||||
dateFormat: startElement.dateFormat,
|
dateFormat: startElement.dateFormat,
|
||||||
valueList: [{
|
valueList: [
|
||||||
value: date
|
{
|
||||||
}]
|
value: date
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
formatElementContext(elementList, [dateElement], leftIndex)
|
formatElementContext(elementList, [dateElement], leftIndex)
|
||||||
this.draw.insertElementList([dateElement])
|
this.draw.insertElementList([dateElement])
|
||||||
@@ -113,7 +118,10 @@ export class DateParticle {
|
|||||||
const elementList = this.draw.getElementList()
|
const elementList = this.draw.getElementList()
|
||||||
const range = this.getDateElementRange()
|
const range = this.getDateElementRange()
|
||||||
const value = range
|
const value = range
|
||||||
? elementList.slice(range[0] + 1, range[1] + 1).map(el => el.value).join('')
|
? elementList
|
||||||
|
.slice(range[0] + 1, range[1] + 1)
|
||||||
|
.map(el => el.value)
|
||||||
|
.join('')
|
||||||
: ''
|
: ''
|
||||||
this.datePicker.render({
|
this.datePicker.render({
|
||||||
value,
|
value,
|
||||||
@@ -123,7 +131,12 @@ export class DateParticle {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) {
|
public render(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IRowElement,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.font = element.style
|
ctx.font = element.style
|
||||||
if (element.color) {
|
if (element.color) {
|
||||||
@@ -132,5 +145,4 @@ export class DateParticle {
|
|||||||
ctx.fillText(element.value, x, y)
|
ctx.fillText(element.value, x, y)
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,66 +3,65 @@ import { IElement, IElementPosition } from '../../../../interface/Element'
|
|||||||
import { datePicker } from '../../../i18n/lang/zh-CN.json'
|
import { datePicker } from '../../../i18n/lang/zh-CN.json'
|
||||||
|
|
||||||
export interface IDatePickerLang {
|
export interface IDatePickerLang {
|
||||||
now: string;
|
now: string
|
||||||
confirm: string;
|
confirm: string
|
||||||
return: string;
|
return: string
|
||||||
timeSelect: string;
|
timeSelect: string
|
||||||
weeks: {
|
weeks: {
|
||||||
sun: string;
|
sun: string
|
||||||
mon: string;
|
mon: string
|
||||||
tue: string;
|
tue: string
|
||||||
wed: string;
|
wed: string
|
||||||
thu: string;
|
thu: string
|
||||||
fri: string;
|
fri: string
|
||||||
sat: string;
|
sat: string
|
||||||
};
|
}
|
||||||
year: string;
|
year: string
|
||||||
month: string;
|
month: string
|
||||||
hour: string;
|
hour: string
|
||||||
minute: string;
|
minute: string
|
||||||
second: string;
|
second: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDatePickerOption {
|
export interface IDatePickerOption {
|
||||||
mountDom?: HTMLElement;
|
mountDom?: HTMLElement
|
||||||
onSubmit?: (date: string) => any;
|
onSubmit?: (date: string) => any
|
||||||
getLang?: () => IDatePickerLang
|
getLang?: () => IDatePickerLang
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IDatePickerDom {
|
interface IDatePickerDom {
|
||||||
container: HTMLDivElement;
|
container: HTMLDivElement
|
||||||
dateWrap: HTMLDivElement;
|
dateWrap: HTMLDivElement
|
||||||
datePickerWeek: HTMLDivElement;
|
datePickerWeek: HTMLDivElement
|
||||||
timeWrap: HTMLUListElement;
|
timeWrap: HTMLUListElement
|
||||||
title: {
|
title: {
|
||||||
preYear: HTMLSpanElement;
|
preYear: HTMLSpanElement
|
||||||
preMonth: HTMLSpanElement;
|
preMonth: HTMLSpanElement
|
||||||
now: HTMLSpanElement;
|
now: HTMLSpanElement
|
||||||
nextMonth: HTMLSpanElement;
|
nextMonth: HTMLSpanElement
|
||||||
nextYear: HTMLSpanElement;
|
nextYear: HTMLSpanElement
|
||||||
};
|
}
|
||||||
day: HTMLDivElement;
|
day: HTMLDivElement
|
||||||
time: {
|
time: {
|
||||||
hour: HTMLOListElement;
|
hour: HTMLOListElement
|
||||||
minute: HTMLOListElement;
|
minute: HTMLOListElement
|
||||||
second: HTMLOListElement;
|
second: HTMLOListElement
|
||||||
};
|
}
|
||||||
menu: {
|
menu: {
|
||||||
time: HTMLButtonElement;
|
time: HTMLButtonElement
|
||||||
now: HTMLButtonElement;
|
now: HTMLButtonElement
|
||||||
submit: HTMLButtonElement;
|
submit: HTMLButtonElement
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IRenderOption {
|
interface IRenderOption {
|
||||||
value: string;
|
value: string
|
||||||
element: IElement;
|
element: IElement
|
||||||
position: IElementPosition;
|
position: IElementPosition
|
||||||
startTop?: number;
|
startTop?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DatePicker {
|
export class DatePicker {
|
||||||
|
|
||||||
private options: IDatePickerOption
|
private options: IDatePickerOption
|
||||||
private now: Date
|
private now: Date
|
||||||
private dom: IDatePickerDom
|
private dom: IDatePickerDom
|
||||||
@@ -115,7 +114,9 @@ export class DatePicker {
|
|||||||
// week-星期显示
|
// week-星期显示
|
||||||
const datePickerWeek = document.createElement('div')
|
const datePickerWeek = document.createElement('div')
|
||||||
datePickerWeek.classList.add(`${EDITOR_PREFIX}-date-week`)
|
datePickerWeek.classList.add(`${EDITOR_PREFIX}-date-week`)
|
||||||
const { weeks: { sun, mon, tue, wed, thu, fri, sat } } = this.lang
|
const {
|
||||||
|
weeks: { sun, mon, tue, wed, thu, fri, sat }
|
||||||
|
} = this.lang
|
||||||
const weekList = [sun, mon, tue, wed, thu, fri, sat]
|
const weekList = [sun, mon, tue, wed, thu, fri, sat]
|
||||||
weekList.forEach(week => {
|
weekList.forEach(week => {
|
||||||
const weekDom = document.createElement('span')
|
const weekDom = document.createElement('span')
|
||||||
@@ -232,7 +233,7 @@ export class DatePicker {
|
|||||||
this.dispose()
|
this.dispose()
|
||||||
this._submit()
|
this._submit()
|
||||||
}
|
}
|
||||||
this.dom.time.hour.onclick = (evt) => {
|
this.dom.time.hour.onclick = evt => {
|
||||||
if (!this.pickDate) return
|
if (!this.pickDate) return
|
||||||
const li = <HTMLLIElement>evt.target
|
const li = <HTMLLIElement>evt.target
|
||||||
const id = li.dataset.id
|
const id = li.dataset.id
|
||||||
@@ -240,7 +241,7 @@ export class DatePicker {
|
|||||||
this.pickDate.setHours(Number(id))
|
this.pickDate.setHours(Number(id))
|
||||||
this._setTimePick(false)
|
this._setTimePick(false)
|
||||||
}
|
}
|
||||||
this.dom.time.minute.onclick = (evt) => {
|
this.dom.time.minute.onclick = evt => {
|
||||||
if (!this.pickDate) return
|
if (!this.pickDate) return
|
||||||
const li = <HTMLLIElement>evt.target
|
const li = <HTMLLIElement>evt.target
|
||||||
const id = li.dataset.id
|
const id = li.dataset.id
|
||||||
@@ -248,7 +249,7 @@ export class DatePicker {
|
|||||||
this.pickDate.setMinutes(Number(id))
|
this.pickDate.setMinutes(Number(id))
|
||||||
this._setTimePick(false)
|
this._setTimePick(false)
|
||||||
}
|
}
|
||||||
this.dom.time.second.onclick = (evt) => {
|
this.dom.time.second.onclick = evt => {
|
||||||
if (!this.pickDate) return
|
if (!this.pickDate) return
|
||||||
const li = <HTMLLIElement>evt.target
|
const li = <HTMLLIElement>evt.target
|
||||||
const id = li.dataset.id
|
const id = li.dataset.id
|
||||||
@@ -293,16 +294,23 @@ export class DatePicker {
|
|||||||
this.dom.menu.time.innerText = this.lang.timeSelect
|
this.dom.menu.time.innerText = this.lang.timeSelect
|
||||||
this.dom.menu.now.innerText = this.lang.now
|
this.dom.menu.now.innerText = this.lang.now
|
||||||
this.dom.menu.submit.innerText = this.lang.confirm
|
this.dom.menu.submit.innerText = this.lang.confirm
|
||||||
const { weeks: { sun, mon, tue, wed, thu, fri, sat } } = this.lang
|
const {
|
||||||
|
weeks: { sun, mon, tue, wed, thu, fri, sat }
|
||||||
|
} = this.lang
|
||||||
const weekList = [sun, mon, tue, wed, thu, fri, sat]
|
const weekList = [sun, mon, tue, wed, thu, fri, sat]
|
||||||
this.dom.datePickerWeek.childNodes.forEach((child, i) => {
|
this.dom.datePickerWeek.childNodes.forEach((child, i) => {
|
||||||
(<HTMLSpanElement>child).innerText = weekList[i]
|
const childElement = <HTMLSpanElement>child
|
||||||
|
childElement.innerText = weekList[i]
|
||||||
})
|
})
|
||||||
const hourTitle = (<HTMLSpanElement>this.dom.time.hour.previousElementSibling)
|
const hourTitle = <HTMLSpanElement>this.dom.time.hour.previousElementSibling
|
||||||
hourTitle.innerText = this.lang.hour
|
hourTitle.innerText = this.lang.hour
|
||||||
const minuteTitle = (<HTMLSpanElement>this.dom.time.minute.previousElementSibling)
|
const minuteTitle = <HTMLSpanElement>(
|
||||||
|
this.dom.time.minute.previousElementSibling
|
||||||
|
)
|
||||||
minuteTitle.innerText = this.lang.minute
|
minuteTitle.innerText = this.lang.minute
|
||||||
const secondTitle = (<HTMLSpanElement>this.dom.time.second.previousElementSibling)
|
const secondTitle = <HTMLSpanElement>(
|
||||||
|
this.dom.time.second.previousElementSibling
|
||||||
|
)
|
||||||
secondTitle.innerText = this.lang.second
|
secondTitle.innerText = this.lang.second
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +332,9 @@ export class DatePicker {
|
|||||||
// 当前年月日
|
// 当前年月日
|
||||||
const year = this.now.getFullYear()
|
const year = this.now.getFullYear()
|
||||||
const month = this.now.getMonth() + 1
|
const month = this.now.getMonth() + 1
|
||||||
this.dom.title.now.innerText = `${year}${this.lang.year} ${String(month).padStart(2, '0')}${this.lang.month}`
|
this.dom.title.now.innerText = `${year}${this.lang.year} ${String(
|
||||||
|
month
|
||||||
|
).padStart(2, '0')}${this.lang.month}`
|
||||||
// 日期补差
|
// 日期补差
|
||||||
const curDate = new Date(year, month, 0) // 当月日期
|
const curDate = new Date(year, month, 0) // 当月日期
|
||||||
const curDay = curDate.getDate() // 当月总天数
|
const curDay = curDate.getDate() // 当月总天数
|
||||||
@@ -353,11 +363,16 @@ export class DatePicker {
|
|||||||
if (localYear === year && localMonth === month && localDay === i) {
|
if (localYear === year && localMonth === month && localDay === i) {
|
||||||
dayDom.classList.add('active')
|
dayDom.classList.add('active')
|
||||||
}
|
}
|
||||||
if (this.pickDate && pickYear === year && pickMonth === month && pickDay === i) {
|
if (
|
||||||
|
this.pickDate &&
|
||||||
|
pickYear === year &&
|
||||||
|
pickMonth === month &&
|
||||||
|
pickDay === i
|
||||||
|
) {
|
||||||
dayDom.classList.add('select')
|
dayDom.classList.add('select')
|
||||||
}
|
}
|
||||||
dayDom.innerText = `${i}`
|
dayDom.innerText = `${i}`
|
||||||
dayDom.onclick = (evt) => {
|
dayDom.onclick = evt => {
|
||||||
const newMonth = month - 1
|
const newMonth = month - 1
|
||||||
this.now = new Date(year, newMonth, i)
|
this.now = new Date(year, newMonth, i)
|
||||||
this._setDatePick(year, newMonth, i)
|
this._setDatePick(year, newMonth, i)
|
||||||
@@ -405,14 +420,23 @@ export class DatePicker {
|
|||||||
const hour = this.pickDate?.getHours() || 0
|
const hour = this.pickDate?.getHours() || 0
|
||||||
const minute = this.pickDate?.getMinutes() || 0
|
const minute = this.pickDate?.getMinutes() || 0
|
||||||
const second = this.pickDate?.getSeconds() || 0
|
const second = this.pickDate?.getSeconds() || 0
|
||||||
const { hour: hourDom, minute: minuteDom, second: secondDom } = this.dom.time
|
const {
|
||||||
|
hour: hourDom,
|
||||||
|
minute: minuteDom,
|
||||||
|
second: secondDom
|
||||||
|
} = this.dom.time
|
||||||
const timeDomList = [hourDom, minuteDom, secondDom]
|
const timeDomList = [hourDom, minuteDom, secondDom]
|
||||||
// 清空
|
// 清空
|
||||||
timeDomList.forEach(timeDom => {
|
timeDomList.forEach(timeDom => {
|
||||||
timeDom.querySelectorAll('li')
|
timeDom
|
||||||
|
.querySelectorAll('li')
|
||||||
.forEach(li => li.classList.remove('active'))
|
.forEach(li => li.classList.remove('active'))
|
||||||
})
|
})
|
||||||
const pickList: [HTMLOListElement, number][] = [[hourDom, hour], [minuteDom, minute], [secondDom, second]]
|
const pickList: [HTMLOListElement, number][] = [
|
||||||
|
[hourDom, hour],
|
||||||
|
[minuteDom, minute],
|
||||||
|
[secondDom, second]
|
||||||
|
]
|
||||||
pickList.forEach(([dom, time]) => {
|
pickList.forEach(([dom, time]) => {
|
||||||
const pickDom = dom.querySelector<HTMLLIElement>(`[data-id='${time}']`)!
|
const pickDom = dom.querySelector<HTMLLIElement>(`[data-id='${time}']`)!
|
||||||
pickDom.classList.add('active')
|
pickDom.classList.add('active')
|
||||||
@@ -433,7 +457,9 @@ export class DatePicker {
|
|||||||
offsetParents.push(pointer)
|
offsetParents.push(pointer)
|
||||||
pointer = <HTMLElement>pointer.offsetParent
|
pointer = <HTMLElement>pointer.offsetParent
|
||||||
}
|
}
|
||||||
const top = selected.offsetTop + offsetParents.reduce((prev, curr) => (prev + curr.offsetTop), 0)
|
const top =
|
||||||
|
selected.offsetTop +
|
||||||
|
offsetParents.reduce((prev, curr) => prev + curr.offsetTop, 0)
|
||||||
const bottom = top + selected.offsetHeight
|
const bottom = top + selected.offsetHeight
|
||||||
const viewRectTop = container.scrollTop
|
const viewRectTop = container.scrollTop
|
||||||
const viewRectBottom = viewRectTop + container.clientHeight
|
const viewRectBottom = viewRectTop + container.clientHeight
|
||||||
@@ -502,8 +528,8 @@ export class DatePicker {
|
|||||||
dateString = dateString.replace(
|
dateString = dateString.replace(
|
||||||
reg[1],
|
reg[1],
|
||||||
reg[1].length === 1
|
reg[1].length === 1
|
||||||
? (dateOption[key])
|
? dateOption[key]
|
||||||
: (dateOption[key].padStart(reg[1].length, '0'))
|
: dateOption[key].padStart(reg[1].length, '0')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -527,5 +553,4 @@ export class DatePicker {
|
|||||||
public dispose() {
|
public dispose() {
|
||||||
this._toggleVisible(false)
|
this._toggleVisible(false)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { ImageParticle } from '../ImageParticle'
|
|||||||
import { LaTexSVG, LaTexUtils } from './utils/LaTexUtils'
|
import { LaTexSVG, LaTexUtils } from './utils/LaTexUtils'
|
||||||
|
|
||||||
export class LaTexParticle extends ImageParticle {
|
export class LaTexParticle extends ImageParticle {
|
||||||
|
|
||||||
public static convertLaTextToSVG(laTex: string): LaTexSVG {
|
public static convertLaTextToSVG(laTex: string): LaTexSVG {
|
||||||
return new LaTexUtils(laTex).svg({
|
return new LaTexUtils(laTex).svg({
|
||||||
SCALE_X: 10,
|
SCALE_X: 10,
|
||||||
@@ -13,7 +12,12 @@ export class LaTexParticle extends ImageParticle {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IElement, x: number, y: number) {
|
public render(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IElement,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
const { scale } = this.options
|
const { scale } = this.options
|
||||||
const width = element.width! * scale
|
const width = element.width! * scale
|
||||||
const height = element.height! * scale
|
const height = element.height! * scale
|
||||||
@@ -29,13 +33,11 @@ export class LaTexParticle extends ImageParticle {
|
|||||||
this.imageCache.set(element.value, img)
|
this.imageCache.set(element.value, img)
|
||||||
resolve(element)
|
resolve(element)
|
||||||
}
|
}
|
||||||
img.onerror = (error) => {
|
img.onerror = error => {
|
||||||
reject(error)
|
reject(error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.addImageObserver(laTexLoadPromise)
|
this.addImageObserver(laTexLoadPromise)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const CONFIG: Record<string, number> = {
|
|||||||
SQRT_MAG_SCALE: 0.5,
|
SQRT_MAG_SCALE: 0.5,
|
||||||
FRAC_SCALE: 0.85,
|
FRAC_SCALE: 0.85,
|
||||||
LINE_SPACING: 0.5,
|
LINE_SPACING: 0.5,
|
||||||
FRAC_SPACING: 0.4,
|
FRAC_SPACING: 0.4
|
||||||
}
|
}
|
||||||
|
|
||||||
function tokenize(str: string): string[] {
|
function tokenize(str: string): string[] {
|
||||||
@@ -49,27 +49,40 @@ function tokenize(str: string): string[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Bbox {
|
interface Bbox {
|
||||||
x: number, y: number, w: number, h: number
|
x: number
|
||||||
|
y: number
|
||||||
|
w: number
|
||||||
|
h: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Expr {
|
interface Expr {
|
||||||
type: string;
|
type: string
|
||||||
text: string;
|
text: string
|
||||||
mode: string;
|
mode: string
|
||||||
chld: Expr[];
|
chld: Expr[]
|
||||||
bbox: Bbox;
|
bbox: Bbox
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseAtom(x: string): Expr {
|
function parseAtom(x: string): Expr {
|
||||||
// @ts-ignore
|
return {
|
||||||
return { type: SYMB[x] ? 'symb' : 'char', mode: 'math', text: x, chld: [], bbox: null }
|
type: SYMB[x] ? 'symb' : 'char',
|
||||||
|
mode: 'math',
|
||||||
|
text: x,
|
||||||
|
chld: [],
|
||||||
|
// @ts-ignore
|
||||||
|
bbox: null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parse(tokens: string[]): Expr {
|
function parse(tokens: string[]): Expr {
|
||||||
let i = 0
|
let i = 0
|
||||||
let expr: Expr = {
|
let expr: Expr = {
|
||||||
|
type: 'node',
|
||||||
|
text: '',
|
||||||
|
mode: 'math',
|
||||||
|
chld: [],
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
type: 'node', text: '', mode: 'math', chld: [], bbox: null
|
bbox: null
|
||||||
}
|
}
|
||||||
|
|
||||||
function takeOpt(): Expr | null {
|
function takeOpt(): Expr | null {
|
||||||
@@ -133,8 +146,12 @@ function parse(tokens: string[]): Expr {
|
|||||||
for (i = 0; i < tokens.length; i++) {
|
for (i = 0; i < tokens.length; i++) {
|
||||||
const s: Symb = SYMB[tokens[i]]
|
const s: Symb = SYMB[tokens[i]]
|
||||||
const e: Expr = {
|
const e: Expr = {
|
||||||
|
type: '',
|
||||||
|
text: tokens[i],
|
||||||
|
mode: 'math',
|
||||||
|
chld: [],
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
type: '', text: tokens[i], mode: 'math', chld: [], bbox: null
|
bbox: null
|
||||||
}
|
}
|
||||||
if (s) {
|
if (s) {
|
||||||
if (s.arity) {
|
if (s.arity) {
|
||||||
@@ -190,7 +207,14 @@ function environments(exprs: Expr[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function transform(expr: Expr, sclx: number, scly: number, x: number, y: number, notFirst?: boolean) {
|
function transform(
|
||||||
|
expr: Expr,
|
||||||
|
sclx: number,
|
||||||
|
scly: number,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
notFirst?: boolean
|
||||||
|
) {
|
||||||
if (scly == null) {
|
if (scly == null) {
|
||||||
scly = sclx
|
scly = sclx
|
||||||
}
|
}
|
||||||
@@ -209,8 +233,10 @@ function transform(expr: Expr, sclx: number, scly: number, x: number, y: number,
|
|||||||
}
|
}
|
||||||
|
|
||||||
function computeBbox(exprs: Expr[]): Bbox {
|
function computeBbox(exprs: Expr[]): Bbox {
|
||||||
let xmin = Infinity; let xmax = -Infinity
|
let xmin = Infinity
|
||||||
let ymin = Infinity; let ymax = -Infinity
|
let xmax = -Infinity
|
||||||
|
let ymin = Infinity
|
||||||
|
let ymax = -Infinity
|
||||||
for (let i = 0; i < exprs.length; i++) {
|
for (let i = 0; i < exprs.length; i++) {
|
||||||
if (!exprs[i].bbox) {
|
if (!exprs[i].bbox) {
|
||||||
continue
|
continue
|
||||||
@@ -238,8 +264,11 @@ function group(exprs: Expr[]): Expr {
|
|||||||
exprs[i].bbox.y -= bbox.y
|
exprs[i].bbox.y -= bbox.y
|
||||||
}
|
}
|
||||||
const expr: Expr = {
|
const expr: Expr = {
|
||||||
type: 'node', text: '', mode: 'math',
|
type: 'node',
|
||||||
chld: exprs, bbox
|
text: '',
|
||||||
|
mode: 'math',
|
||||||
|
chld: exprs,
|
||||||
|
bbox
|
||||||
}
|
}
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
@@ -249,7 +278,10 @@ function align(exprs: Expr[], alignment = 'center'): void {
|
|||||||
if (exprs[i].text == '^' || exprs[i].text == '\'') {
|
if (exprs[i].text == '^' || exprs[i].text == '\'') {
|
||||||
let h = 0
|
let h = 0
|
||||||
let j = i
|
let j = i
|
||||||
while (j > 0 && (exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\'')) {
|
while (
|
||||||
|
j > 0 &&
|
||||||
|
(exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\'')
|
||||||
|
) {
|
||||||
j--
|
j--
|
||||||
}
|
}
|
||||||
h = exprs[j].bbox.y
|
h = exprs[j].bbox.y
|
||||||
@@ -269,7 +301,10 @@ function align(exprs: Expr[], alignment = 'center'): void {
|
|||||||
} else if (exprs[i].text == '_') {
|
} else if (exprs[i].text == '_') {
|
||||||
let h = 1
|
let h = 1
|
||||||
let j = i
|
let j = i
|
||||||
while (j > 0 && (exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\'')) {
|
while (
|
||||||
|
j > 0 &&
|
||||||
|
(exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\'')
|
||||||
|
) {
|
||||||
j--
|
j--
|
||||||
}
|
}
|
||||||
h = exprs[j].bbox.y + exprs[j].bbox.h
|
h = exprs[j].bbox.y + exprs[j].bbox.h
|
||||||
@@ -284,12 +319,18 @@ function align(exprs: Expr[], alignment = 'center'): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function searchHigh(i: number, l: string, r: string, dir: number, lvl0: number): number[] {
|
function searchHigh(
|
||||||
|
i: number,
|
||||||
|
l: string,
|
||||||
|
r: string,
|
||||||
|
dir: number,
|
||||||
|
lvl0: number
|
||||||
|
): number[] {
|
||||||
let j = i
|
let j = i
|
||||||
let lvl = lvl0
|
let lvl = lvl0
|
||||||
let ymin = Infinity
|
let ymin = Infinity
|
||||||
let ymax = -Infinity
|
let ymax = -Infinity
|
||||||
while ((dir > 0) ? (j < exprs.length) : (j >= 0)) {
|
while (dir > 0 ? j < exprs.length : j >= 0) {
|
||||||
if (exprs[j].text == l) {
|
if (exprs[j].text == l) {
|
||||||
lvl++
|
lvl++
|
||||||
} else if (exprs[j].text == r) {
|
} else if (exprs[j].text == r) {
|
||||||
@@ -312,13 +353,13 @@ function align(exprs: Expr[], alignment = 'center'): void {
|
|||||||
const [ymin, ymax] = searchHigh(i, '\\left', '\\right', 1, 0)
|
const [ymin, ymax] = searchHigh(i, '\\left', '\\right', 1, 0)
|
||||||
if (ymin != Infinity && ymax != -Infinity) {
|
if (ymin != Infinity && ymax != -Infinity) {
|
||||||
exprs[i].bbox.y = ymin
|
exprs[i].bbox.y = ymin
|
||||||
transform(exprs[i], 1, ((ymax - ymin) / exprs[i].bbox.h), 0, 0)
|
transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0)
|
||||||
}
|
}
|
||||||
} else if (exprs[i].text == '\\right') {
|
} else if (exprs[i].text == '\\right') {
|
||||||
const [ymin, ymax] = searchHigh(i, '\\right', '\\left', -1, 0)
|
const [ymin, ymax] = searchHigh(i, '\\right', '\\left', -1, 0)
|
||||||
if (ymin != Infinity && ymax != -Infinity) {
|
if (ymin != Infinity && ymax != -Infinity) {
|
||||||
exprs[i].bbox.y = ymin
|
exprs[i].bbox.y = ymin
|
||||||
transform(exprs[i], 1, ((ymax - ymin) / exprs[i].bbox.h), 0, 0)
|
transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0)
|
||||||
}
|
}
|
||||||
} else if (exprs[i].text == '\\middle') {
|
} else if (exprs[i].text == '\\middle') {
|
||||||
const [lmin, lmax] = searchHigh(i, '\\right', '\\left', -1, 1)
|
const [lmin, lmax] = searchHigh(i, '\\right', '\\left', -1, 1)
|
||||||
@@ -327,12 +368,12 @@ function align(exprs: Expr[], alignment = 'center'): void {
|
|||||||
const ymax = Math.max(lmax, rmax)
|
const ymax = Math.max(lmax, rmax)
|
||||||
if (ymin != Infinity && ymax != -Infinity) {
|
if (ymin != Infinity && ymax != -Infinity) {
|
||||||
exprs[i].bbox.y = ymin
|
exprs[i].bbox.y = ymin
|
||||||
transform(exprs[i], 1, ((ymax - ymin) / exprs[i].bbox.h), 0, 0)
|
transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!exprs.some((x) => (x.text == '&' || x.text == '\\\\'))) {
|
if (!exprs.some(x => x.text == '&' || x.text == '\\\\')) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,28 +449,27 @@ function align(exprs: Expr[], alignment = 'center'): void {
|
|||||||
ybds[i][1] += shft
|
ybds[i][1] += shft
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
exprs.splice(0, exprs.length)
|
exprs.splice(0, exprs.length)
|
||||||
for (let i = 0; i < erows.length; i++) {
|
for (let i = 0; i < erows.length; i++) {
|
||||||
let dx = 0
|
let dx = 0
|
||||||
for (let j = 0; j < erows[i].length; j++) {
|
for (let j = 0; j < erows[i].length; j++) {
|
||||||
const e: Expr = erows[i][j]
|
const e: Expr = erows[i][j]
|
||||||
if (!e) {
|
if (!e) {
|
||||||
dx += (colws[j])
|
dx += colws[j]
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
e.bbox.x += dx
|
e.bbox.x += dx
|
||||||
dx += (colws[j] - e.bbox.w)
|
dx += colws[j] - e.bbox.w
|
||||||
// e.bbox.w = colws[j];
|
// e.bbox.w = colws[j];
|
||||||
if (alignment == 'center') {
|
if (alignment == 'center') {
|
||||||
e.bbox.x += (colws[j] - e.bbox.w) / 2
|
e.bbox.x += (colws[j] - e.bbox.w) / 2
|
||||||
} else if (alignment == 'left') {
|
} else if (alignment == 'left') {
|
||||||
//ok
|
//ok
|
||||||
} else if (alignment == 'right') {
|
} else if (alignment == 'right') {
|
||||||
e.bbox.x += (colws[j] - e.bbox.w)
|
e.bbox.x += colws[j] - e.bbox.w
|
||||||
} else if (alignment == 'equation') {
|
} else if (alignment == 'equation') {
|
||||||
if (j != erows[i].length - 1) {
|
if (j != erows[i].length - 1) {
|
||||||
e.bbox.x += (colws[j] - e.bbox.w)
|
e.bbox.x += colws[j] - e.bbox.w
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exprs.push(e)
|
exprs.push(e)
|
||||||
@@ -438,28 +478,29 @@ function align(exprs: Expr[], alignment = 'center'): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function plan(expr: Expr, mode = 'math'): void {
|
function plan(expr: Expr, mode = 'math'): void {
|
||||||
const tmd: string = {
|
const tmd: string =
|
||||||
'\\text': 'text',
|
{
|
||||||
'\\mathnormal': 'math',
|
'\\text': 'text',
|
||||||
'\\mathrm': 'rm',
|
'\\mathnormal': 'math',
|
||||||
'\\mathit': 'it',
|
'\\mathrm': 'rm',
|
||||||
'\\mathbf': 'bf',
|
'\\mathit': 'it',
|
||||||
'\\mathsf': 'sf',
|
'\\mathbf': 'bf',
|
||||||
'\\mathtt': 'tt',
|
'\\mathsf': 'sf',
|
||||||
'\\mathfrak': 'frak',
|
'\\mathtt': 'tt',
|
||||||
'\\mathcal': 'cal',
|
'\\mathfrak': 'frak',
|
||||||
'\\mathbb': 'bb',
|
'\\mathcal': 'cal',
|
||||||
'\\mathscr': 'scr',
|
'\\mathbb': 'bb',
|
||||||
'\\rm': 'rm',
|
'\\mathscr': 'scr',
|
||||||
'\\it': 'it',
|
'\\rm': 'rm',
|
||||||
'\\bf': 'bf',
|
'\\it': 'it',
|
||||||
'\\sf': 'tt',
|
'\\bf': 'bf',
|
||||||
'\\tt': 'tt',
|
'\\sf': 'tt',
|
||||||
'\\frak': 'frak',
|
'\\tt': 'tt',
|
||||||
'\\cal': 'cal',
|
'\\frak': 'frak',
|
||||||
'\\bb': 'bb',
|
'\\cal': 'cal',
|
||||||
'\\scr': 'scr',
|
'\\bb': 'bb',
|
||||||
}[expr.text] ?? mode
|
'\\scr': 'scr'
|
||||||
|
}[expr.text] ?? mode
|
||||||
if (!expr.chld.length) {
|
if (!expr.chld.length) {
|
||||||
if (SYMB[expr.text]) {
|
if (SYMB[expr.text]) {
|
||||||
if (SYMB[expr.text].flags.big) {
|
if (SYMB[expr.text].flags.big) {
|
||||||
@@ -517,9 +558,20 @@ function plan(expr: Expr, mode = 'math'): void {
|
|||||||
const mw: number = Math.max(a.bbox.w, b.bbox.w) * s
|
const mw: number = Math.max(a.bbox.w, b.bbox.w) * s
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
transform(a, s, null, (mw - a.bbox.w * s) / 2, 0)
|
transform(a, s, null, (mw - a.bbox.w * s) / 2, 0)
|
||||||
// @ts-ignore
|
transform(
|
||||||
transform(b, s, null, (mw - b.bbox.w * s) / 2, a.bbox.h + CONFIG.FRAC_SPACING)
|
b,
|
||||||
expr.bbox = { x: 0, y: -a.bbox.h + 1 - CONFIG.FRAC_SPACING / 2, w: mw, h: a.bbox.h + b.bbox.h + CONFIG.FRAC_SPACING }
|
s,
|
||||||
|
// @ts-ignore
|
||||||
|
null,
|
||||||
|
(mw - b.bbox.w * s) / 2,
|
||||||
|
a.bbox.h + CONFIG.FRAC_SPACING
|
||||||
|
)
|
||||||
|
expr.bbox = {
|
||||||
|
x: 0,
|
||||||
|
y: -a.bbox.h + 1 - CONFIG.FRAC_SPACING / 2,
|
||||||
|
w: mw,
|
||||||
|
h: a.bbox.h + b.bbox.h + CONFIG.FRAC_SPACING
|
||||||
|
}
|
||||||
} else if (expr.text == '\\binom') {
|
} else if (expr.text == '\\binom') {
|
||||||
const a: Expr = expr.chld[0]
|
const a: Expr = expr.chld[0]
|
||||||
const b: Expr = expr.chld[1]
|
const b: Expr = expr.chld[1]
|
||||||
@@ -548,20 +600,22 @@ function plan(expr: Expr, mode = 'math'): void {
|
|||||||
}
|
}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
transform(e, 1, null, 1 + pl, 0.5)
|
transform(e, 1, null, 1 + pl, 0.5)
|
||||||
expr.bbox = { x: 0, y: 2 - e.bbox.h - 0.5, w: e.bbox.w + 1 + pl, h: e.bbox.h + 0.5 }
|
expr.bbox = {
|
||||||
|
x: 0,
|
||||||
|
y: 2 - e.bbox.h - 0.5,
|
||||||
|
w: e.bbox.w + 1 + pl,
|
||||||
|
h: e.bbox.h + 0.5
|
||||||
|
}
|
||||||
} else if (SYMB[expr.text] && SYMB[expr.text].flags.hat) {
|
} else if (SYMB[expr.text] && SYMB[expr.text].flags.hat) {
|
||||||
const e: Expr = expr.chld[0]
|
const e: Expr = expr.chld[0]
|
||||||
plan(e)
|
plan(e)
|
||||||
const y0 = e.bbox.y - 0.5
|
const y0 = e.bbox.y - 0.5
|
||||||
e.bbox.y = 0.5
|
e.bbox.y = 0.5
|
||||||
expr.bbox = { x: 0, y: y0, w: e.bbox.w, h: e.bbox.h + 0.5 }
|
expr.bbox = { x: 0, y: y0, w: e.bbox.w, h: e.bbox.h + 0.5 }
|
||||||
|
|
||||||
} else if (SYMB[expr.text] && SYMB[expr.text].flags.mat) {
|
} else if (SYMB[expr.text] && SYMB[expr.text].flags.mat) {
|
||||||
const e: Expr = expr.chld[0]
|
const e: Expr = expr.chld[0]
|
||||||
plan(e)
|
plan(e)
|
||||||
expr.bbox = { x: 0, y: 0, w: e.bbox.w, h: e.bbox.h + 0.5 }
|
expr.bbox = { x: 0, y: 0, w: e.bbox.w, h: e.bbox.h + 0.5 }
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
let dx = 0
|
let dx = 0
|
||||||
let dy = 0
|
let dy = 0
|
||||||
@@ -569,13 +623,14 @@ function plan(expr: Expr, mode = 'math'): void {
|
|||||||
for (let i = 0; i < expr.chld.length; i++) {
|
for (let i = 0; i < expr.chld.length; i++) {
|
||||||
const c: Expr = expr.chld[i]
|
const c: Expr = expr.chld[i]
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const spac: number = {
|
const spac: number =
|
||||||
'\\quad': 2,
|
{
|
||||||
'\\,': 2 * 3 / 18,
|
'\\quad': 2,
|
||||||
'\\:': 2 * 4 / 18,
|
'\\,': (2 * 3) / 18,
|
||||||
'\\;': 2 * 5 / 18,
|
'\\:': (2 * 4) / 18,
|
||||||
'\\!': 2 * (-3) / 18,
|
'\\;': (2 * 5) / 18,
|
||||||
}[c.text] ?? null
|
'\\!': (2 * -3) / 18
|
||||||
|
}[c.text] ?? null
|
||||||
|
|
||||||
if (c.text == '\\\\') {
|
if (c.text == '\\\\') {
|
||||||
dy += mh
|
dy += mh
|
||||||
@@ -593,10 +648,16 @@ function plan(expr: Expr, mode = 'math'): void {
|
|||||||
transform(c, 1, null, dx, dy)
|
transform(c, 1, null, dx, dy)
|
||||||
if (c.text == '^' || c.text == '_' || c.text == '\'') {
|
if (c.text == '^' || c.text == '_' || c.text == '\'') {
|
||||||
let j: number = i
|
let j: number = i
|
||||||
while (j > 0 && (expr.chld[j].text == '^' || expr.chld[j].text == '_' || expr.chld[j].text == '\'')) {
|
while (
|
||||||
|
j > 0 &&
|
||||||
|
(expr.chld[j].text == '^' ||
|
||||||
|
expr.chld[j].text == '_' ||
|
||||||
|
expr.chld[j].text == '\'')
|
||||||
|
) {
|
||||||
j--
|
j--
|
||||||
}
|
}
|
||||||
const wasBig = SYMB[expr.chld[j].text] && SYMB[expr.chld[j].text].flags.big
|
const wasBig =
|
||||||
|
SYMB[expr.chld[j].text] && SYMB[expr.chld[j].text].flags.big
|
||||||
if (c.text == '\'') {
|
if (c.text == '\'') {
|
||||||
let k = j + 1
|
let k = j + 1
|
||||||
let nth = 0
|
let nth = 0
|
||||||
@@ -606,13 +667,21 @@ function plan(expr: Expr, mode = 'math'): void {
|
|||||||
}
|
}
|
||||||
k++
|
k++
|
||||||
}
|
}
|
||||||
c.bbox.x = expr.chld[j].bbox.x + expr.chld[j].bbox.w + c.bbox.w * nth
|
c.bbox.x =
|
||||||
|
expr.chld[j].bbox.x + expr.chld[j].bbox.w + c.bbox.w * nth
|
||||||
dx = Math.max(dx, c.bbox.x + c.bbox.w)
|
dx = Math.max(dx, c.bbox.x + c.bbox.w)
|
||||||
} else {
|
} else {
|
||||||
if (wasBig) {
|
if (wasBig) {
|
||||||
const ex = expr.chld[j].bbox.x + (expr.chld[j].bbox.w - c.bbox.w * CONFIG.SUB_SUP_SCALE) / 2
|
const ex =
|
||||||
|
expr.chld[j].bbox.x +
|
||||||
|
(expr.chld[j].bbox.w - c.bbox.w * CONFIG.SUB_SUP_SCALE) / 2
|
||||||
c.bbox.x = ex
|
c.bbox.x = ex
|
||||||
dx = Math.max(dx, expr.chld[j].bbox.x + expr.chld[j].bbox.w + (c.bbox.w * CONFIG.SUB_SUP_SCALE - expr.chld[j].bbox.w) / 2)
|
dx = Math.max(
|
||||||
|
dx,
|
||||||
|
expr.chld[j].bbox.x +
|
||||||
|
expr.chld[j].bbox.w +
|
||||||
|
(c.bbox.w * CONFIG.SUB_SUP_SCALE - expr.chld[j].bbox.w) / 2
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
c.bbox.x = expr.chld[j].bbox.x + expr.chld[j].bbox.w
|
c.bbox.x = expr.chld[j].bbox.x + expr.chld[j].bbox.w
|
||||||
dx = Math.max(dx, c.bbox.x + c.bbox.w * CONFIG.SUB_SUP_SCALE)
|
dx = Math.max(dx, c.bbox.x + c.bbox.w * CONFIG.SUB_SUP_SCALE)
|
||||||
@@ -629,19 +698,20 @@ function plan(expr: Expr, mode = 'math'): void {
|
|||||||
}
|
}
|
||||||
dy += mh
|
dy += mh
|
||||||
const m2s: Record<string, string[]> = {
|
const m2s: Record<string, string[]> = {
|
||||||
'bmatrix': ['[', ']'],
|
bmatrix: ['[', ']'],
|
||||||
'pmatrix': ['(', ')'],
|
pmatrix: ['(', ')'],
|
||||||
'Bmatrix': ['\\{', '\\}'],
|
Bmatrix: ['\\{', '\\}'],
|
||||||
'cases': ['\\{']
|
cases: ['\\{']
|
||||||
}
|
}
|
||||||
const alt: string = {
|
const alt: string =
|
||||||
'bmatrix': 'center',
|
{
|
||||||
'pmatrix': 'center',
|
bmatrix: 'center',
|
||||||
'Bmatrix': 'center',
|
pmatrix: 'center',
|
||||||
'cases': 'left',
|
Bmatrix: 'center',
|
||||||
'matrix': 'center',
|
cases: 'left',
|
||||||
'aligned': 'equation',
|
matrix: 'center',
|
||||||
}[expr.text] ?? 'left'
|
aligned: 'equation'
|
||||||
|
}[expr.text] ?? 'left'
|
||||||
|
|
||||||
const hasLp = !!m2s[expr.text]
|
const hasLp = !!m2s[expr.text]
|
||||||
const hasRp = !!m2s[expr.text] && m2s[expr.text].length > 1
|
const hasRp = !!m2s[expr.text] && m2s[expr.text].length > 1
|
||||||
@@ -657,16 +727,29 @@ function plan(expr: Expr, mode = 'math'): void {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
transform(expr.chld[i], 1, null, -bb.x + (hasLp ? 1.5 : 0), -bb.y)
|
transform(expr.chld[i], 1, null, -bb.x + (hasLp ? 1.5 : 0), -bb.y)
|
||||||
}
|
}
|
||||||
expr.bbox = { x: 0, y: 0, w: bb.w + 1.5 * Number(hasLp) + 1.5 * Number(hasRp), h: bb.h }
|
expr.bbox = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
w: bb.w + 1.5 * Number(hasLp) + 1.5 * Number(hasRp),
|
||||||
|
h: bb.h
|
||||||
|
}
|
||||||
|
|
||||||
if (hasLp) {
|
if (hasLp) {
|
||||||
expr.chld.unshift({
|
expr.chld.unshift({
|
||||||
type: 'symb', text: m2s[expr.text][0], mode: expr.mode, chld: [], bbox: { x: 0, y: 0, w: 1, h: bb.h }
|
type: 'symb',
|
||||||
|
text: m2s[expr.text][0],
|
||||||
|
mode: expr.mode,
|
||||||
|
chld: [],
|
||||||
|
bbox: { x: 0, y: 0, w: 1, h: bb.h }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (hasRp) {
|
if (hasRp) {
|
||||||
expr.chld.push({
|
expr.chld.push({
|
||||||
type: 'symb', text: m2s[expr.text][1], mode: expr.mode, chld: [], bbox: { x: bb.w + 2, y: 0, w: 1, h: bb.h }
|
type: 'symb',
|
||||||
|
text: m2s[expr.text][1],
|
||||||
|
mode: expr.mode,
|
||||||
|
chld: [],
|
||||||
|
bbox: { x: bb.w + 2, y: 0, w: 1, h: bb.h }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (hasLp || hasRp || expr.text == 'matrix') {
|
if (hasLp || hasRp || expr.text == 'matrix') {
|
||||||
@@ -684,7 +767,8 @@ function flatten(expr: Expr) {
|
|||||||
dx += expr.bbox.x
|
dx += expr.bbox.x
|
||||||
dy += expr.bbox.y
|
dy += expr.bbox.y
|
||||||
if (expr.text == '\\frac') {
|
if (expr.text == '\\frac') {
|
||||||
const h: number = expr.chld[1].bbox.y - (expr.chld[0].bbox.y + expr.chld[0].bbox.h)
|
const h: number =
|
||||||
|
expr.chld[1].bbox.y - (expr.chld[0].bbox.y + expr.chld[0].bbox.h)
|
||||||
const e: Expr = {
|
const e: Expr = {
|
||||||
type: 'symb',
|
type: 'symb',
|
||||||
mode: expr.mode,
|
mode: expr.mode,
|
||||||
@@ -693,13 +777,17 @@ function flatten(expr: Expr) {
|
|||||||
x: dx,
|
x: dx,
|
||||||
y: dy + (expr.chld[1].bbox.y - h / 2) - h / 2,
|
y: dy + (expr.chld[1].bbox.y - h / 2) - h / 2,
|
||||||
w: expr.bbox.w,
|
w: expr.bbox.w,
|
||||||
h: h,
|
h: h
|
||||||
}, chld: [],
|
},
|
||||||
|
chld: []
|
||||||
}
|
}
|
||||||
ff.push(e)
|
ff.push(e)
|
||||||
} else if (expr.text == '\\sqrt') {
|
} else if (expr.text == '\\sqrt') {
|
||||||
const h: number = expr.chld[0].bbox.y
|
const h: number = expr.chld[0].bbox.y
|
||||||
const xx: number = Math.max(0, expr.chld[0].bbox.x - expr.chld[0].bbox.h / 2)
|
const xx: number = Math.max(
|
||||||
|
0,
|
||||||
|
expr.chld[0].bbox.x - expr.chld[0].bbox.h / 2
|
||||||
|
)
|
||||||
const e: Expr = {
|
const e: Expr = {
|
||||||
type: 'symb',
|
type: 'symb',
|
||||||
mode: expr.mode,
|
mode: expr.mode,
|
||||||
@@ -708,8 +796,9 @@ function flatten(expr: Expr) {
|
|||||||
x: dx + xx,
|
x: dx + xx,
|
||||||
y: dy + h / 2,
|
y: dy + h / 2,
|
||||||
w: expr.chld[0].bbox.x - xx,
|
w: expr.chld[0].bbox.x - xx,
|
||||||
h: expr.bbox.h - h / 2,
|
h: expr.bbox.h - h / 2
|
||||||
}, chld: [],
|
},
|
||||||
|
chld: []
|
||||||
}
|
}
|
||||||
ff.push(e)
|
ff.push(e)
|
||||||
ff.push({
|
ff.push({
|
||||||
@@ -720,8 +809,9 @@ function flatten(expr: Expr) {
|
|||||||
x: dx + expr.chld[0].bbox.x,
|
x: dx + expr.chld[0].bbox.x,
|
||||||
y: dy,
|
y: dy,
|
||||||
w: expr.bbox.w - expr.chld[0].bbox.x,
|
w: expr.bbox.w - expr.chld[0].bbox.x,
|
||||||
h: h,
|
h: h
|
||||||
}, chld: [],
|
},
|
||||||
|
chld: []
|
||||||
})
|
})
|
||||||
} else if (expr.text == '\\binom') {
|
} else if (expr.text == '\\binom') {
|
||||||
const w = Math.min(expr.chld[0].bbox.x, expr.chld[1].bbox.x)
|
const w = Math.min(expr.chld[0].bbox.x, expr.chld[1].bbox.x)
|
||||||
@@ -733,8 +823,9 @@ function flatten(expr: Expr) {
|
|||||||
x: dx,
|
x: dx,
|
||||||
y: dy,
|
y: dy,
|
||||||
w: w,
|
w: w,
|
||||||
h: expr.bbox.h,
|
h: expr.bbox.h
|
||||||
}, chld: [],
|
},
|
||||||
|
chld: []
|
||||||
}
|
}
|
||||||
ff.push(e)
|
ff.push(e)
|
||||||
ff.push({
|
ff.push({
|
||||||
@@ -745,8 +836,9 @@ function flatten(expr: Expr) {
|
|||||||
x: dx + expr.bbox.w - w,
|
x: dx + expr.bbox.w - w,
|
||||||
y: dy,
|
y: dy,
|
||||||
w: w,
|
w: w,
|
||||||
h: expr.bbox.h,
|
h: expr.bbox.h
|
||||||
}, chld: [],
|
},
|
||||||
|
chld: []
|
||||||
})
|
})
|
||||||
} else if (SYMB[expr.text] && SYMB[expr.text].flags.hat) {
|
} else if (SYMB[expr.text] && SYMB[expr.text].flags.hat) {
|
||||||
const h: number = expr.chld[0].bbox.y
|
const h: number = expr.chld[0].bbox.y
|
||||||
@@ -758,8 +850,9 @@ function flatten(expr: Expr) {
|
|||||||
x: dx,
|
x: dx,
|
||||||
y: dy,
|
y: dy,
|
||||||
w: expr.bbox.w,
|
w: expr.bbox.w,
|
||||||
h: h,
|
h: h
|
||||||
}, chld: [],
|
},
|
||||||
|
chld: []
|
||||||
}
|
}
|
||||||
ff.push(e)
|
ff.push(e)
|
||||||
} else if (SYMB[expr.text] && SYMB[expr.text].flags.mat) {
|
} else if (SYMB[expr.text] && SYMB[expr.text].flags.mat) {
|
||||||
@@ -772,21 +865,23 @@ function flatten(expr: Expr) {
|
|||||||
x: dx,
|
x: dx,
|
||||||
y: dy + h,
|
y: dy + h,
|
||||||
w: expr.bbox.w,
|
w: expr.bbox.w,
|
||||||
h: expr.bbox.h - h,
|
h: expr.bbox.h - h
|
||||||
}, chld: [],
|
},
|
||||||
|
chld: []
|
||||||
}
|
}
|
||||||
ff.push(e)
|
ff.push(e)
|
||||||
} else if (expr.type != 'node'
|
} else if (expr.type != 'node' && expr.text != '^' && expr.text != '_') {
|
||||||
&& expr.text != '^'
|
|
||||||
&& expr.text != '_'
|
|
||||||
) {
|
|
||||||
const e: Expr = {
|
const e: Expr = {
|
||||||
type: expr.type == 'func' ? 'symb' : expr.type, text: expr.text, mode: expr.mode, bbox: {
|
type: expr.type == 'func' ? 'symb' : expr.type,
|
||||||
|
text: expr.text,
|
||||||
|
mode: expr.mode,
|
||||||
|
bbox: {
|
||||||
x: dx,
|
x: dx,
|
||||||
y: dy,
|
y: dy,
|
||||||
w: expr.bbox.w,
|
w: expr.bbox.w,
|
||||||
h: expr.bbox.h
|
h: expr.bbox.h
|
||||||
}, chld: [],
|
},
|
||||||
|
chld: []
|
||||||
}
|
}
|
||||||
ff.push(e)
|
ff.push(e)
|
||||||
}
|
}
|
||||||
@@ -809,8 +904,12 @@ function render(expr: Expr): number[][][] {
|
|||||||
const e: Expr = expr.chld[i]
|
const e: Expr = expr.chld[i]
|
||||||
let s = e.bbox.h / 2
|
let s = e.bbox.h / 2
|
||||||
let isSmallHat = false
|
let isSmallHat = false
|
||||||
if (SYMB[e.text] && SYMB[e.text].flags.hat &&
|
if (
|
||||||
!SYMB[e.text].flags.xfl && !SYMB[e.text].flags.yfl) {
|
SYMB[e.text] &&
|
||||||
|
SYMB[e.text].flags.hat &&
|
||||||
|
!SYMB[e.text].flags.xfl &&
|
||||||
|
!SYMB[e.text].flags.yfl
|
||||||
|
) {
|
||||||
s *= 4
|
s *= 4
|
||||||
isSmallHat = true
|
isSmallHat = true
|
||||||
}
|
}
|
||||||
@@ -824,25 +923,24 @@ function render(expr: Expr): number[][][] {
|
|||||||
let y = d.polylines[j][k][1]
|
let y = d.polylines[j][k][1]
|
||||||
|
|
||||||
if (SYMB[e.text].flags.xfl) {
|
if (SYMB[e.text].flags.xfl) {
|
||||||
x = (x - d.xmin) / Math.max(d.xmax - d.xmin, 1) * e.bbox.w
|
x = ((x - d.xmin) / Math.max(d.xmax - d.xmin, 1)) * e.bbox.w
|
||||||
x += e.bbox.x
|
x += e.bbox.x
|
||||||
} else if (d.w / 16 * s > e.bbox.w) {
|
} else if ((d.w / 16) * s > e.bbox.w) {
|
||||||
x = x / Math.max(d.w, 1) * e.bbox.w
|
x = (x / Math.max(d.w, 1)) * e.bbox.w
|
||||||
x += e.bbox.x
|
x += e.bbox.x
|
||||||
} else {
|
} else {
|
||||||
|
x = (x / 16) * s
|
||||||
x = x / 16 * s
|
const p = (e.bbox.w - (d.w / 16) * s) / 2
|
||||||
const p = (e.bbox.w - d.w / 16 * s) / 2
|
|
||||||
x += e.bbox.x + p
|
x += e.bbox.x + p
|
||||||
}
|
}
|
||||||
if (SYMB[e.text].flags.yfl) {
|
if (SYMB[e.text].flags.yfl) {
|
||||||
y = (y - d.ymin) / Math.max(d.ymax - d.ymin, 1) * e.bbox.h
|
y = ((y - d.ymin) / Math.max(d.ymax - d.ymin, 1)) * e.bbox.h
|
||||||
y += e.bbox.y
|
y += e.bbox.y
|
||||||
} else {
|
} else {
|
||||||
y = y / 16 * s
|
y = (y / 16) * s
|
||||||
if (isSmallHat) {
|
if (isSmallHat) {
|
||||||
const p = (d.ymax + d.ymin) / 2
|
const p = (d.ymax + d.ymin) / 2
|
||||||
y -= p / 16 * s
|
y -= (p / 16) * s
|
||||||
}
|
}
|
||||||
y += e.bbox.y + e.bbox.h / 2
|
y += e.bbox.y + e.bbox.h / 2
|
||||||
}
|
}
|
||||||
@@ -850,7 +948,7 @@ function render(expr: Expr): number[][][] {
|
|||||||
}
|
}
|
||||||
o.push(l)
|
o.push(l)
|
||||||
}
|
}
|
||||||
} else if ((SYMB[e.text] && SYMB[e.text].flags.txt) || (e.type == 'char')) {
|
} else if ((SYMB[e.text] && SYMB[e.text].flags.txt) || e.type == 'char') {
|
||||||
let x0 = e.bbox.x
|
let x0 = e.bbox.x
|
||||||
const isVerb = !!(SYMB[e.text] && SYMB[e.text].flags.txt)
|
const isVerb = !!(SYMB[e.text] && SYMB[e.text].flags.txt)
|
||||||
for (let n = Number(isVerb); n < e.text.length; n++) {
|
for (let n = Number(isVerb); n < e.text.length; n++) {
|
||||||
@@ -874,7 +972,6 @@ function render(expr: Expr): number[][][] {
|
|||||||
} else {
|
} else {
|
||||||
x += (16 - d.w) / 2 / 16
|
x += (16 - d.w) / 2 / 16
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
x += x0
|
x += x0
|
||||||
y += e.bbox.y + e.bbox.h / 2
|
y += e.bbox.y + e.bbox.h / 2
|
||||||
@@ -885,7 +982,7 @@ function render(expr: Expr): number[][][] {
|
|||||||
if (e.mode == 'tt') {
|
if (e.mode == 'tt') {
|
||||||
x0 += s
|
x0 += s
|
||||||
} else {
|
} else {
|
||||||
x0 += d.w / 16 * s
|
x0 += (d.w / 16) * s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -894,16 +991,16 @@ function render(expr: Expr): number[][][] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ExportOpt {
|
interface ExportOpt {
|
||||||
MIN_CHAR_H?: number;
|
MIN_CHAR_H?: number
|
||||||
MAX_W?: number;
|
MAX_W?: number
|
||||||
MAX_H?: number;
|
MAX_H?: number
|
||||||
MARGIN_X?: number;
|
MARGIN_X?: number
|
||||||
MARGIN_Y?: number;
|
MARGIN_Y?: number
|
||||||
SCALE_X?: number;
|
SCALE_X?: number
|
||||||
SCALE_Y?: number;
|
SCALE_Y?: number
|
||||||
STROKE_W?: number;
|
STROKE_W?: number
|
||||||
FG_COLOR?: string;
|
FG_COLOR?: string
|
||||||
BG_COLOR?: string;
|
BG_COLOR?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function nf(x: number): number {
|
function nf(x: number): number {
|
||||||
@@ -911,16 +1008,16 @@ function nf(x: number): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LaTexSVG {
|
export interface LaTexSVG {
|
||||||
svg: string;
|
svg: string
|
||||||
width: number;
|
width: number
|
||||||
height: number;
|
height: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LaTexUtils {
|
export class LaTexUtils {
|
||||||
_latex: string;
|
_latex: string
|
||||||
_tree: Expr;
|
_tree: Expr
|
||||||
_tokens: string[];
|
_tokens: string[]
|
||||||
_polylines: number[][][];
|
_polylines: number[][][]
|
||||||
|
|
||||||
constructor(latex: string) {
|
constructor(latex: string) {
|
||||||
this._latex = latex
|
this._latex = latex
|
||||||
@@ -943,9 +1040,11 @@ export class LaTexUtils {
|
|||||||
let mh = 0
|
let mh = 0
|
||||||
for (let i = 0; i < this._tree.chld.length; i++) {
|
for (let i = 0; i < this._tree.chld.length; i++) {
|
||||||
const c: Expr = this._tree.chld[i]
|
const c: Expr = this._tree.chld[i]
|
||||||
if (c.type == 'char' ||
|
if (
|
||||||
|
c.type == 'char' ||
|
||||||
(SYMB[c.text] &&
|
(SYMB[c.text] &&
|
||||||
(SYMB[c.text].flags.txt || !Object.keys(SYMB[c.text].flags).length))) {
|
(SYMB[c.text].flags.txt || !Object.keys(SYMB[c.text].flags).length))
|
||||||
|
) {
|
||||||
mh = Math.min(c.bbox.h, mh)
|
mh = Math.min(c.bbox.h, mh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -956,12 +1055,12 @@ export class LaTexUtils {
|
|||||||
if (opt.MAX_W != undefined) {
|
if (opt.MAX_W != undefined) {
|
||||||
const s0 = sclx
|
const s0 = sclx
|
||||||
sclx = Math.min(sclx, opt.MAX_W / this._tree.bbox.w)
|
sclx = Math.min(sclx, opt.MAX_W / this._tree.bbox.w)
|
||||||
scly *= (sclx / s0)
|
scly *= sclx / s0
|
||||||
}
|
}
|
||||||
if (opt.MAX_H != undefined) {
|
if (opt.MAX_H != undefined) {
|
||||||
const s0 = scly
|
const s0 = scly
|
||||||
scly = Math.min(scly, opt.MAX_H / this._tree.bbox.h)
|
scly = Math.min(scly, opt.MAX_H / this._tree.bbox.h)
|
||||||
sclx *= (scly / s0)
|
sclx *= scly / s0
|
||||||
}
|
}
|
||||||
const px: number = opt.MARGIN_X ?? sclx
|
const px: number = opt.MARGIN_X ?? sclx
|
||||||
const py: number = opt.MARGIN_Y ?? scly
|
const py: number = opt.MARGIN_Y ?? scly
|
||||||
@@ -989,7 +1088,7 @@ export class LaTexUtils {
|
|||||||
for (let i = 0; i < this._polylines.length; i++) {
|
for (let i = 0; i < this._polylines.length; i++) {
|
||||||
for (let j = 0; j < this._polylines[i].length; j++) {
|
for (let j = 0; j < this._polylines[i].length; j++) {
|
||||||
const [x, y] = this._polylines[i][j]
|
const [x, y] = this._polylines[i][j]
|
||||||
d += (!j) ? 'M' : 'L'
|
d += !j ? 'M' : 'L'
|
||||||
d += `${nf(px + x * sclx)} ${nf(py + y * scly)}`
|
d += `${nf(px + x * sclx)} ${nf(py + y * scly)}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1004,18 +1103,22 @@ export class LaTexUtils {
|
|||||||
let o = `<svg
|
let o = `<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="${w}" height="${h}"
|
width="${w}" height="${h}"
|
||||||
fill="none" stroke="${opt.FG_COLOR ?? 'black'}" stroke-width="${opt.STROKE_W ?? 1}"
|
fill="none" stroke="${opt.FG_COLOR ?? 'black'}" stroke-width="${
|
||||||
|
opt.STROKE_W ?? 1
|
||||||
|
}"
|
||||||
stroke-linecap="round" stroke-linejoin="round"
|
stroke-linecap="round" stroke-linejoin="round"
|
||||||
>`
|
>`
|
||||||
if (opt.BG_COLOR) {
|
if (opt.BG_COLOR) {
|
||||||
o += `<rect x="${0}" y="${0}" width="${w}" height="${h}" fill="${opt.BG_COLOR}" stroke="none"></rect>`
|
o += `<rect x="${0}" y="${0}" width="${w}" height="${h}" fill="${
|
||||||
|
opt.BG_COLOR
|
||||||
|
}" stroke="none"></rect>`
|
||||||
}
|
}
|
||||||
o += `<path d="`
|
o += `<path d="`
|
||||||
for (let i = 0; i < this._polylines.length; i++) {
|
for (let i = 0; i < this._polylines.length; i++) {
|
||||||
o += 'M'
|
o += 'M'
|
||||||
for (let j = 0; j < this._polylines[i].length; j++) {
|
for (let j = 0; j < this._polylines[i].length; j++) {
|
||||||
const [x, y] = this._polylines[i][j]
|
const [x, y] = this._polylines[i][j]
|
||||||
o += (nf(px + x * sclx)) + ' ' + (nf(py + y * scly)) + ' '
|
o += nf(px + x * sclx) + ' ' + nf(py + y * scly) + ' '
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
o += `"/>`
|
o += `"/>`
|
||||||
@@ -1040,10 +1143,14 @@ export class LaTexUtils {
|
|||||||
let pdf = ''
|
let pdf = ''
|
||||||
let count = 4
|
let count = 4
|
||||||
for (let i = 0; i < this._polylines.length; i++) {
|
for (let i = 0; i < this._polylines.length; i++) {
|
||||||
pdf += `${count} 0 obj \n<< /Length 0 >>\n stream\n 1 j 1 J ${opt.STROKE_W ?? 1} w\n`
|
pdf += `${count} 0 obj \n<< /Length 0 >>\n stream\n 1 j 1 J ${
|
||||||
|
opt.STROKE_W ?? 1
|
||||||
|
} w\n`
|
||||||
for (let j = 0; j < this._polylines[i].length; j++) {
|
for (let j = 0; j < this._polylines[i].length; j++) {
|
||||||
const [x, y] = this._polylines[i][j]
|
const [x, y] = this._polylines[i][j]
|
||||||
pdf += `${nf(px + x * sclx)} ${nf(height - (py + y * scly))} ${j ? 'l' : 'm'} `
|
pdf += `${nf(px + x * sclx)} ${nf(height - (py + y * scly))} ${
|
||||||
|
j ? 'l' : 'm'
|
||||||
|
} `
|
||||||
}
|
}
|
||||||
pdf += '\nS\nendstream\nendobj\n'
|
pdf += '\nS\nendstream\nendobj\n'
|
||||||
head += `${count} 0 R `
|
head += `${count} 0 R `
|
||||||
@@ -1077,6 +1184,13 @@ export class LaTexUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const _impl: Record<string, Function> = { tokenize, parse, environments, plan, flatten, render }
|
const _impl: Record<string, Function> = {
|
||||||
|
tokenize,
|
||||||
|
parse,
|
||||||
|
environments,
|
||||||
|
plan,
|
||||||
|
flatten,
|
||||||
|
render
|
||||||
|
}
|
||||||
|
|
||||||
export { CONFIG, _impl }
|
export { CONFIG, _impl }
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
interface HersheyEntry {
|
interface HersheyEntry {
|
||||||
w: number;
|
w: number
|
||||||
xmin: number;
|
xmin: number
|
||||||
xmax: number;
|
xmax: number
|
||||||
ymin: number;
|
ymin: number
|
||||||
ymax: number;
|
ymax: number
|
||||||
polylines: Array<Array<Array<number>>>;
|
polylines: Array<Array<Array<number>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
const ordR = 'R'.charCodeAt(0)
|
const ordR = 'R'.charCodeAt(0)
|
||||||
@@ -53,7 +53,7 @@ function compile(i: number): void {
|
|||||||
xmax: zmax,
|
xmax: zmax,
|
||||||
ymin: ymin,
|
ymin: ymin,
|
||||||
ymax: ymax,
|
ymax: ymax,
|
||||||
polylines: polylines,
|
polylines: polylines
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const data: Record<number, HersheyEntry> = {}
|
const data: Record<number, HersheyEntry> = {}
|
||||||
@@ -1628,5 +1628,5 @@ const raw: Record<number, string> = {
|
|||||||
3923: ' 59E_HMIOIXM[OYQX RINJOJXMZ RHMJNKOKWNYOY RRMPOQPQXU[WY[W RRPSORNQORPRXUZ RRMTOSPSWVYWY RZM\\O[P[W RZP[OZNYOZPZW RZMXOYPYX',
|
3923: ' 59E_HMIOIXM[OYQX RINJOJXMZ RHMJNKOKWNYOY RRMPOQPQXU[WY[W RRPSORNQORPRXUZ RRMTOSPSWVYWY RZM\\O[P[W RZP[OZNYOZPZW RZMXOYPYX',
|
||||||
3924: ' 39I[LONPUZV[XY RMNOOUYWZ RLONMONVXXY RXMVMVOXOXMVOSS RQUNYL[N[NYLYL[ RNTQT RSTVT',
|
3924: ' 39I[LONPUZV[XY RMNOOUYWZ RLONMONVXXY RXMVMVOXOXMVOSS RQUNYL[N[NYLYL[ RNTQT RSTVT',
|
||||||
3925: ' 49I[KOLOMPMYP[UY RMNNONYPZ RKOMMOOOXRZ RVMXOWPW]V_U`SaQaO`MaObQa RVPWOVNUOVPV^U_ RPaNa RVMTOUPU^T`Sa',
|
3925: ' 49I[KOLOMPMYP[UY RMNNONYPZ RKOMMOOOXRZ RVMXOWPW]V_U`SaQaO`MaObQa RVPWOVNUOVPV^U_ RPaNa RVMTOUPU^T`Sa',
|
||||||
3926: ' 43L[RNOPOORNTMWOWSRU RTNVOVS RRNUPUSTT RRUWWW]V_U`SaQaO`MaObQa RVWV^U_ RPaNa RTVUWU^T`Sa',
|
3926: ' 43L[RNOPOORNTMWOWSRU RTNVOVS RRNUPUSTT RRUWWW]V_U`SaQaO`MaObQa RVWV^U_ RPaNa RTVUWU^T`Sa'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,21 @@ https://oeis.org/wiki/List_of_LaTeX_mathematical_symbols
|
|||||||
https://en.wikibooks.org/wiki/LaTeX/Mathematics
|
https://en.wikibooks.org/wiki/LaTeX/Mathematics
|
||||||
*/
|
*/
|
||||||
export interface Symb {
|
export interface Symb {
|
||||||
glyph: number;
|
glyph: number
|
||||||
arity?: number;
|
arity?: number
|
||||||
flags: Record<string, boolean>;
|
flags: Record<string, boolean>
|
||||||
}
|
}
|
||||||
|
|
||||||
const SYMB: Record<string, Symb> = {
|
const SYMB: Record<string, Symb> = {
|
||||||
'\\frac': { glyph: 0, arity: 2, flags: {} },
|
'\\frac': { glyph: 0, arity: 2, flags: {} },
|
||||||
'\\binom': { glyph: 0, arity: 2, flags: {} },
|
'\\binom': { glyph: 0, arity: 2, flags: {} },
|
||||||
'\\sqrt': { glyph: 2267, arity: 1, flags: { opt: true, xfl: true, yfl: true } },
|
'\\sqrt': {
|
||||||
|
glyph: 2267,
|
||||||
|
arity: 1,
|
||||||
|
flags: { opt: true, xfl: true, yfl: true }
|
||||||
|
},
|
||||||
'^': { glyph: 0, arity: 1, flags: {} },
|
'^': { glyph: 0, arity: 1, flags: {} },
|
||||||
'_': { glyph: 0, arity: 1, flags: {} },
|
_: { glyph: 0, arity: 1, flags: {} },
|
||||||
'(': { glyph: 2221, arity: 0, flags: { yfl: true } },
|
'(': { glyph: 2221, arity: 0, flags: { yfl: true } },
|
||||||
')': { glyph: 2222, arity: 0, flags: { yfl: true } },
|
')': { glyph: 2222, arity: 0, flags: { yfl: true } },
|
||||||
'[': { glyph: 2223, arity: 0, flags: { yfl: true } },
|
'[': { glyph: 2223, arity: 0, flags: { yfl: true } },
|
||||||
@@ -56,12 +60,28 @@ const SYMB: Record<string, Symb> = {
|
|||||||
'\\ell': { glyph: 662, arity: 0, flags: {} },
|
'\\ell': { glyph: 662, arity: 0, flags: {} },
|
||||||
|
|
||||||
/*accents*/
|
/*accents*/
|
||||||
'\\vec': { glyph: 2261, arity: 1, flags: { hat: true, xfl: true, yfl: true } },
|
'\\vec': {
|
||||||
'\\overrightarrow': { glyph: 2261, arity: 1, flags: { hat: true, xfl: true, yfl: true } },
|
glyph: 2261,
|
||||||
'\\overleftarrow': { glyph: 2263, arity: 1, flags: { hat: true, xfl: true, yfl: true } },
|
arity: 1,
|
||||||
|
flags: { hat: true, xfl: true, yfl: true }
|
||||||
|
},
|
||||||
|
'\\overrightarrow': {
|
||||||
|
glyph: 2261,
|
||||||
|
arity: 1,
|
||||||
|
flags: { hat: true, xfl: true, yfl: true }
|
||||||
|
},
|
||||||
|
'\\overleftarrow': {
|
||||||
|
glyph: 2263,
|
||||||
|
arity: 1,
|
||||||
|
flags: { hat: true, xfl: true, yfl: true }
|
||||||
|
},
|
||||||
'\\bar': { glyph: 2231, arity: 1, flags: { hat: true, xfl: true } },
|
'\\bar': { glyph: 2231, arity: 1, flags: { hat: true, xfl: true } },
|
||||||
'\\overline': { glyph: 2231, arity: 1, flags: { hat: true, xfl: true } },
|
'\\overline': { glyph: 2231, arity: 1, flags: { hat: true, xfl: true } },
|
||||||
'\\widehat': { glyph: 2247, arity: 1, flags: { hat: true, xfl: true, yfl: true } },
|
'\\widehat': {
|
||||||
|
glyph: 2247,
|
||||||
|
arity: 1,
|
||||||
|
flags: { hat: true, xfl: true, yfl: true }
|
||||||
|
},
|
||||||
'\\hat': { glyph: 2247, arity: 1, flags: { hat: true } },
|
'\\hat': { glyph: 2247, arity: 1, flags: { hat: true } },
|
||||||
'\\acute': { glyph: 2248, arity: 1, flags: { hat: true } },
|
'\\acute': { glyph: 2248, arity: 1, flags: { hat: true } },
|
||||||
'\\grave': { glyph: 2249, arity: 1, flags: { hat: true } },
|
'\\grave': { glyph: 2249, arity: 1, flags: { hat: true } },
|
||||||
@@ -219,7 +239,7 @@ const SYMB: Record<string, Symb> = {
|
|||||||
'\\Phi': { glyph: 2047, flags: {} },
|
'\\Phi': { glyph: 2047, flags: {} },
|
||||||
'\\Chi': { glyph: 2048, flags: {} },
|
'\\Chi': { glyph: 2048, flags: {} },
|
||||||
'\\Psi': { glyph: 2049, flags: {} },
|
'\\Psi': { glyph: 2049, flags: {} },
|
||||||
'\\Omega': { glyph: 2050, flags: {} },
|
'\\Omega': { glyph: 2050, flags: {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
export { SYMB }
|
export { SYMB }
|
||||||
@@ -293,6 +313,6 @@ export function asciiMap(x: string, mode = 'math'): number {
|
|||||||
'>': 2242,
|
'>': 2242,
|
||||||
'~': 2246,
|
'~': 2246,
|
||||||
'@': 2273,
|
'@': 2273,
|
||||||
'\\': 804,
|
'\\': 804
|
||||||
}[x]
|
}[x]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import { EDITOR_PREFIX } from '../../../../dataset/constant/Editor'
|
import { EDITOR_PREFIX } from '../../../../dataset/constant/Editor'
|
||||||
import { IEditorOption } from '../../../../interface/Editor'
|
import { IEditorOption } from '../../../../interface/Editor'
|
||||||
import { IElement, IElementPosition } from '../../../../interface/Element'
|
import { IElement, IElementPosition } from '../../../../interface/Element'
|
||||||
import { IPreviewerCreateResult, IPreviewerDrawOption } from '../../../../interface/Previewer'
|
import {
|
||||||
|
IPreviewerCreateResult,
|
||||||
|
IPreviewerDrawOption
|
||||||
|
} from '../../../../interface/Previewer'
|
||||||
import { downloadFile } from '../../../../utils'
|
import { downloadFile } from '../../../../utils'
|
||||||
import { Draw } from '../../Draw'
|
import { Draw } from '../../Draw'
|
||||||
|
|
||||||
export class Previewer {
|
export class Previewer {
|
||||||
|
|
||||||
private container: HTMLDivElement
|
private container: HTMLDivElement
|
||||||
private canvas: HTMLCanvasElement
|
private canvas: HTMLCanvasElement
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
@@ -39,7 +41,12 @@ export class Previewer {
|
|||||||
this.previewerDrawOption = {}
|
this.previewerDrawOption = {}
|
||||||
this.curPosition = null
|
this.curPosition = null
|
||||||
// 图片尺寸缩放
|
// 图片尺寸缩放
|
||||||
const { resizerSelection, resizerHandleList, resizerImageContainer, resizerImage } = this._createResizerDom()
|
const {
|
||||||
|
resizerSelection,
|
||||||
|
resizerHandleList,
|
||||||
|
resizerImageContainer,
|
||||||
|
resizerImage
|
||||||
|
} = this._createResizerDom()
|
||||||
this.resizerSelection = resizerSelection
|
this.resizerSelection = resizerSelection
|
||||||
this.resizerHandleList = resizerHandleList
|
this.resizerHandleList = resizerHandleList
|
||||||
this.resizerImageContainer = resizerImageContainer
|
this.resizerImageContainer = resizerImageContainer
|
||||||
@@ -79,7 +86,12 @@ export class Previewer {
|
|||||||
const resizerImage = document.createElement('img')
|
const resizerImage = document.createElement('img')
|
||||||
resizerImageContainer.append(resizerImage)
|
resizerImageContainer.append(resizerImage)
|
||||||
this.container.append(resizerImageContainer)
|
this.container.append(resizerImageContainer)
|
||||||
return { resizerSelection, resizerHandleList, resizerImageContainer, resizerImage }
|
return {
|
||||||
|
resizerSelection,
|
||||||
|
resizerHandleList,
|
||||||
|
resizerImageContainer,
|
||||||
|
resizerImage
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _keydown = () => {
|
private _keydown = () => {
|
||||||
@@ -107,7 +119,11 @@ 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: { leftTop: [left, top] } } = this.curPosition
|
const {
|
||||||
|
coordinate: {
|
||||||
|
leftTop: [left, top]
|
||||||
|
}
|
||||||
|
} = this.curPosition
|
||||||
const prePageHeight = this.draw.getPageNo() * (height + pageGap)
|
const prePageHeight = this.draw.getPageNo() * (height + pageGap)
|
||||||
this.resizerImageContainer.style.left = `${left}px`
|
this.resizerImageContainer.style.left = `${left}px`
|
||||||
this.resizerImageContainer.style.top = `${top + prePageHeight}px`
|
this.resizerImageContainer.style.top = `${top + prePageHeight}px`
|
||||||
@@ -116,22 +132,30 @@ export class Previewer {
|
|||||||
// 追加全局事件
|
// 追加全局事件
|
||||||
const mousemoveFn = this._mousemove.bind(this)
|
const mousemoveFn = this._mousemove.bind(this)
|
||||||
document.addEventListener('mousemove', mousemoveFn)
|
document.addEventListener('mousemove', mousemoveFn)
|
||||||
document.addEventListener('mouseup', () => {
|
document.addEventListener(
|
||||||
// 改变尺寸
|
'mouseup',
|
||||||
if (this.curElement && this.curPosition) {
|
() => {
|
||||||
this.curElement.width = this.width
|
// 改变尺寸
|
||||||
this.curElement.height = this.height
|
if (this.curElement && this.curPosition) {
|
||||||
this.draw.render({ isSetCursor: false })
|
this.curElement.width = this.width
|
||||||
this.drawResizer(this.curElement, this.curPosition, this.previewerDrawOption)
|
this.curElement.height = this.height
|
||||||
|
this.draw.render({ isSetCursor: false })
|
||||||
|
this.drawResizer(
|
||||||
|
this.curElement,
|
||||||
|
this.curPosition,
|
||||||
|
this.previewerDrawOption
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// 还原副作用
|
||||||
|
this.resizerImageContainer.style.display = 'none'
|
||||||
|
document.removeEventListener('mousemove', mousemoveFn)
|
||||||
|
document.body.style.cursor = ''
|
||||||
|
this.canvas.style.cursor = 'text'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
once: true
|
||||||
}
|
}
|
||||||
// 还原副作用
|
)
|
||||||
this.resizerImageContainer.style.display = 'none'
|
|
||||||
document.removeEventListener('mousemove', mousemoveFn)
|
|
||||||
document.body.style.cursor = ''
|
|
||||||
this.canvas.style.cursor = 'text'
|
|
||||||
}, {
|
|
||||||
once: true
|
|
||||||
})
|
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +278,7 @@ export class Previewer {
|
|||||||
let startX = 0
|
let startX = 0
|
||||||
let startY = 0
|
let startY = 0
|
||||||
let isAllowDrag = false
|
let isAllowDrag = false
|
||||||
img.onmousedown = (evt) => {
|
img.onmousedown = evt => {
|
||||||
isAllowDrag = true
|
isAllowDrag = true
|
||||||
startX = evt.x
|
startX = evt.x
|
||||||
startY = evt.y
|
startY = evt.y
|
||||||
@@ -262,8 +286,8 @@ export class Previewer {
|
|||||||
}
|
}
|
||||||
previewerContainer.onmousemove = (evt: MouseEvent) => {
|
previewerContainer.onmousemove = (evt: MouseEvent) => {
|
||||||
if (!isAllowDrag) return
|
if (!isAllowDrag) return
|
||||||
x += (evt.x - startX)
|
x += evt.x - startX
|
||||||
y += (evt.y - startY)
|
y += evt.y - startY
|
||||||
startX = evt.x
|
startX = evt.x
|
||||||
startY = evt.y
|
startY = evt.y
|
||||||
this._setPreviewerTransform(scaleSize, rotateSize, x, y)
|
this._setPreviewerTransform(scaleSize, rotateSize, x, y)
|
||||||
@@ -272,7 +296,7 @@ export class Previewer {
|
|||||||
isAllowDrag = false
|
isAllowDrag = false
|
||||||
previewerContainer.style.cursor = 'auto'
|
previewerContainer.style.cursor = 'auto'
|
||||||
}
|
}
|
||||||
previewerContainer.onwheel = (evt) => {
|
previewerContainer.onwheel = evt => {
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
if (evt.deltaY < 0) {
|
if (evt.deltaY < 0) {
|
||||||
// 放大
|
// 放大
|
||||||
@@ -286,11 +310,18 @@ export class Previewer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public _setPreviewerTransform(scale: number, rotate: number, x: number, y: number) {
|
public _setPreviewerTransform(
|
||||||
|
scale: number,
|
||||||
|
rotate: number,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
if (!this.previewerImage) return
|
if (!this.previewerImage) return
|
||||||
this.previewerImage.style.left = `${x}px`
|
this.previewerImage.style.left = `${x}px`
|
||||||
this.previewerImage.style.top = `${y}px`
|
this.previewerImage.style.top = `${y}px`
|
||||||
this.previewerImage.style.transform = `scale(${scale}) rotate(${rotate * 90}deg)`
|
this.previewerImage.style.transform = `scale(${scale}) rotate(${
|
||||||
|
rotate * 90
|
||||||
|
}deg)`
|
||||||
}
|
}
|
||||||
|
|
||||||
private _clearPreviewer() {
|
private _clearPreviewer() {
|
||||||
@@ -299,10 +330,19 @@ export class Previewer {
|
|||||||
document.body.style.overflow = 'auto'
|
document.body.style.overflow = 'auto'
|
||||||
}
|
}
|
||||||
|
|
||||||
public drawResizer(element: IElement, position: IElementPosition, options: IPreviewerDrawOption = {}) {
|
public drawResizer(
|
||||||
|
element: IElement,
|
||||||
|
position: IElementPosition,
|
||||||
|
options: IPreviewerDrawOption = {}
|
||||||
|
) {
|
||||||
this.previewerDrawOption = options
|
this.previewerDrawOption = options
|
||||||
const { scale } = this.options
|
const { scale } = this.options
|
||||||
const { coordinate: { leftTop: [left, top] }, ascent } = position
|
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 height = this.draw.getHeight()
|
||||||
@@ -316,14 +356,16 @@ export class Previewer {
|
|||||||
this.resizerSelection.style.height = `${elementHeight}px`
|
this.resizerSelection.style.height = `${elementHeight}px`
|
||||||
// handle
|
// handle
|
||||||
for (let i = 0; i < 8; i++) {
|
for (let i = 0; i < 8; i++) {
|
||||||
const left = i === 0 || i === 6 || i === 7
|
const left =
|
||||||
? -handleSize
|
i === 0 || i === 6 || i === 7
|
||||||
: i === 1 || i === 5
|
? -handleSize
|
||||||
|
: i === 1 || i === 5
|
||||||
? elementWidth / 2
|
? elementWidth / 2
|
||||||
: elementWidth - handleSize
|
: elementWidth - handleSize
|
||||||
const top = i === 0 || i === 1 || i === 2
|
const top =
|
||||||
? -handleSize
|
i === 0 || i === 1 || i === 2
|
||||||
: i === 3 || i === 7
|
? -handleSize
|
||||||
|
: i === 3 || i === 7
|
||||||
? elementHeight / 2 - handleSize
|
? elementHeight / 2 - handleSize
|
||||||
: elementHeight - handleSize
|
: elementHeight - handleSize
|
||||||
this.resizerHandleList[i].style.left = `${left}px`
|
this.resizerHandleList[i].style.left = `${left}px`
|
||||||
@@ -342,5 +384,4 @@ export class Previewer {
|
|||||||
this.resizerSelection.style.display = 'none'
|
this.resizerSelection.style.display = 'none'
|
||||||
document.removeEventListener('keydown', this._keydown)
|
document.removeEventListener('keydown', this._keydown)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,16 +7,15 @@ import { RangeManager } from '../../../range/RangeManager'
|
|||||||
import { Draw } from '../../Draw'
|
import { Draw } from '../../Draw'
|
||||||
|
|
||||||
interface IDrawTableBorderOption {
|
interface IDrawTableBorderOption {
|
||||||
ctx: CanvasRenderingContext2D;
|
ctx: CanvasRenderingContext2D
|
||||||
startX: number;
|
startX: number
|
||||||
startY: number;
|
startY: number
|
||||||
width: number;
|
width: number
|
||||||
height: number;
|
height: number
|
||||||
isDrawFullBorder?: boolean;
|
isDrawFullBorder?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TableParticle {
|
export class TableParticle {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private range: RangeManager
|
private range: RangeManager
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
@@ -45,9 +44,17 @@ export class TableParticle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getRangeRowCol(): ITd[][] | null {
|
public getRangeRowCol(): ITd[][] | null {
|
||||||
const { isTable, index, trIndex, tdIndex } = this.draw.getPosition().getPositionContext()
|
const { isTable, index, trIndex, tdIndex } = this.draw
|
||||||
|
.getPosition()
|
||||||
|
.getPositionContext()
|
||||||
if (!isTable) return null
|
if (!isTable) return null
|
||||||
const { isCrossRowCol, startTdIndex, endTdIndex, startTrIndex, endTrIndex } = this.range.getRange()
|
const {
|
||||||
|
isCrossRowCol,
|
||||||
|
startTdIndex,
|
||||||
|
endTdIndex,
|
||||||
|
startTrIndex,
|
||||||
|
endTrIndex
|
||||||
|
} = this.range.getRange()
|
||||||
const originalElementList = this.draw.getOriginalElementList()
|
const originalElementList = this.draw.getOriginalElementList()
|
||||||
const element = originalElementList[index!]
|
const element = originalElementList[index!]
|
||||||
const curTrList = element.trList!
|
const curTrList = element.trList!
|
||||||
@@ -59,6 +66,7 @@ export class TableParticle {
|
|||||||
let endTd = curTrList[endTrIndex!].tdList[endTdIndex!]
|
let endTd = curTrList[endTrIndex!].tdList[endTdIndex!]
|
||||||
// 交换起始位置
|
// 交换起始位置
|
||||||
if (startTd.x! > endTd.x! || startTd.y! > endTd.y!) {
|
if (startTd.x! > endTd.x! || startTd.y! > endTd.y!) {
|
||||||
|
// prettier-ignore
|
||||||
[startTd, endTd] = [endTd, startTd]
|
[startTd, endTd] = [endTd, startTd]
|
||||||
}
|
}
|
||||||
const startColIndex = startTd.colIndex!
|
const startColIndex = startTd.colIndex!
|
||||||
@@ -75,8 +83,10 @@ export class TableParticle {
|
|||||||
const tdColIndex = td.colIndex!
|
const tdColIndex = td.colIndex!
|
||||||
const tdRowIndex = td.rowIndex!
|
const tdRowIndex = td.rowIndex!
|
||||||
if (
|
if (
|
||||||
tdColIndex >= startColIndex && tdColIndex <= endColIndex
|
tdColIndex >= startColIndex &&
|
||||||
&& tdRowIndex >= startRowIndex && tdRowIndex <= endRowIndex
|
tdColIndex <= endColIndex &&
|
||||||
|
tdRowIndex >= startRowIndex &&
|
||||||
|
tdRowIndex <= endRowIndex
|
||||||
) {
|
) {
|
||||||
tdList.push(td)
|
tdList.push(td)
|
||||||
}
|
}
|
||||||
@@ -105,7 +115,12 @@ export class TableParticle {
|
|||||||
ctx.translate(-0.5, -0.5)
|
ctx.translate(-0.5, -0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
private _drawBorder(ctx: CanvasRenderingContext2D, element: IElement, startX: number, startY: number) {
|
private _drawBorder(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IElement,
|
||||||
|
startX: number,
|
||||||
|
startY: number
|
||||||
|
) {
|
||||||
const { colgroup, trList, borderType } = element
|
const { colgroup, trList, borderType } = element
|
||||||
if (!colgroup || !trList || borderType === TableBorder.EMPTY) return
|
if (!colgroup || !trList || borderType === TableBorder.EMPTY) return
|
||||||
const { scale } = this.options
|
const { scale } = this.options
|
||||||
@@ -146,7 +161,12 @@ export class TableParticle {
|
|||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
|
||||||
private _drawBackgroundColor(ctx: CanvasRenderingContext2D, element: IElement, startX: number, startY: number) {
|
private _drawBackgroundColor(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IElement,
|
||||||
|
startX: number,
|
||||||
|
startY: number
|
||||||
|
) {
|
||||||
const { trList } = element
|
const { trList } = element
|
||||||
if (!trList) return
|
if (!trList) return
|
||||||
const { scale } = this.options
|
const { scale } = this.options
|
||||||
@@ -259,11 +279,22 @@ export class TableParticle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public drawRange(ctx: CanvasRenderingContext2D, element: IElement, startX: number, startY: number) {
|
public drawRange(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IElement,
|
||||||
|
startX: number,
|
||||||
|
startY: number
|
||||||
|
) {
|
||||||
const { scale, rangeAlpha, rangeColor } = this.options
|
const { scale, rangeAlpha, rangeColor } = this.options
|
||||||
const { type, trList } = element
|
const { type, trList } = element
|
||||||
if (!trList || type !== ElementType.TABLE) return
|
if (!trList || type !== ElementType.TABLE) return
|
||||||
const { isCrossRowCol, startTdIndex, endTdIndex, startTrIndex, endTrIndex } = this.range.getRange()
|
const {
|
||||||
|
isCrossRowCol,
|
||||||
|
startTdIndex,
|
||||||
|
endTdIndex,
|
||||||
|
startTrIndex,
|
||||||
|
endTrIndex
|
||||||
|
} = this.range.getRange()
|
||||||
// 存在跨行/列
|
// 存在跨行/列
|
||||||
if (!isCrossRowCol) return
|
if (!isCrossRowCol) return
|
||||||
let startTd = trList[startTrIndex!].tdList[startTdIndex!]
|
let startTd = trList[startTrIndex!].tdList[startTdIndex!]
|
||||||
@@ -284,8 +315,10 @@ export class TableParticle {
|
|||||||
const tdColIndex = td.colIndex!
|
const tdColIndex = td.colIndex!
|
||||||
const tdRowIndex = td.rowIndex!
|
const tdRowIndex = td.rowIndex!
|
||||||
if (
|
if (
|
||||||
tdColIndex >= startColIndex && tdColIndex <= endColIndex
|
tdColIndex >= startColIndex &&
|
||||||
&& tdRowIndex >= startRowIndex && tdRowIndex <= endRowIndex
|
tdColIndex <= endColIndex &&
|
||||||
|
tdRowIndex >= startRowIndex &&
|
||||||
|
tdRowIndex <= endRowIndex
|
||||||
) {
|
) {
|
||||||
const x = td.x! * scale
|
const x = td.x! * scale
|
||||||
const y = td.y! * scale
|
const y = td.y! * scale
|
||||||
@@ -300,9 +333,13 @@ export class TableParticle {
|
|||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IElement, startX: number, startY: number) {
|
public render(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IElement,
|
||||||
|
startX: number,
|
||||||
|
startY: number
|
||||||
|
) {
|
||||||
this._drawBackgroundColor(ctx, element, startX, startY)
|
this._drawBackgroundColor(ctx, element, startX, startY)
|
||||||
this._drawBorder(ctx, element, startX, startY)
|
this._drawBorder(ctx, element, startX, startY)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ import { Position } from '../../../position/Position'
|
|||||||
import { Draw } from '../../Draw'
|
import { Draw } from '../../Draw'
|
||||||
|
|
||||||
interface IAnchorMouseDown {
|
interface IAnchorMouseDown {
|
||||||
evt: MouseEvent;
|
evt: MouseEvent
|
||||||
order: TableOrder;
|
order: TableOrder
|
||||||
index: number;
|
index: number
|
||||||
element: IElement;
|
element: IElement
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TableTool {
|
export class TableTool {
|
||||||
|
|
||||||
// 单元格最小宽度
|
// 单元格最小宽度
|
||||||
private readonly MIN_TD_WIDTH = 20
|
private readonly MIN_TD_WIDTH = 20
|
||||||
// 行列工具相对表格偏移值
|
// 行列工具相对表格偏移值
|
||||||
@@ -58,12 +57,11 @@ export class TableTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const { isTable, index, trIndex, tdIndex } = this.position.getPositionContext()
|
const { isTable, index, trIndex, tdIndex } =
|
||||||
|
this.position.getPositionContext()
|
||||||
if (!isTable) return
|
if (!isTable) return
|
||||||
|
|
||||||
// 销毁之前工具
|
// 销毁之前工具
|
||||||
this.dispose()
|
this.dispose()
|
||||||
|
|
||||||
// 渲染所需数据
|
// 渲染所需数据
|
||||||
const { scale } = this.options
|
const { scale } = this.options
|
||||||
const elementList = this.draw.getOriginalElementList()
|
const elementList = this.draw.getOriginalElementList()
|
||||||
@@ -71,7 +69,9 @@ export class TableTool {
|
|||||||
const element = elementList[index!]
|
const element = elementList[index!]
|
||||||
const position = positionList[index!]
|
const position = positionList[index!]
|
||||||
const { colgroup, trList } = element
|
const { colgroup, trList } = element
|
||||||
const { coordinate: { leftTop } } = position
|
const {
|
||||||
|
coordinate: { leftTop }
|
||||||
|
} = position
|
||||||
const height = this.draw.getHeight()
|
const height = this.draw.getHeight()
|
||||||
const pageGap = this.draw.getPageGap()
|
const pageGap = this.draw.getPageGap()
|
||||||
const prePageHeight = this.draw.getPageNo() * (height + pageGap)
|
const prePageHeight = this.draw.getPageNo() * (height + pageGap)
|
||||||
@@ -80,12 +80,13 @@ export class TableTool {
|
|||||||
const td = element.trList![trIndex!].tdList[tdIndex!]
|
const td = element.trList![trIndex!].tdList[tdIndex!]
|
||||||
const rowIndex = td.rowIndex
|
const rowIndex = td.rowIndex
|
||||||
const colIndex = td.colIndex
|
const colIndex = td.colIndex
|
||||||
|
|
||||||
// 渲染行工具
|
// 渲染行工具
|
||||||
const rowHeightList = trList!.map(tr => tr.height)
|
const rowHeightList = trList!.map(tr => tr.height)
|
||||||
const rowContainer = document.createElement('div')
|
const rowContainer = document.createElement('div')
|
||||||
rowContainer.classList.add(`${EDITOR_PREFIX}-table-tool__row`)
|
rowContainer.classList.add(`${EDITOR_PREFIX}-table-tool__row`)
|
||||||
rowContainer.style.transform = `translateX(-${this.ROW_COL_OFFSET * scale}px)`
|
rowContainer.style.transform = `translateX(-${
|
||||||
|
this.ROW_COL_OFFSET * scale
|
||||||
|
}px)`
|
||||||
for (let r = 0; r < rowHeightList.length; r++) {
|
for (let r = 0; r < rowHeightList.length; r++) {
|
||||||
const rowHeight = rowHeightList[r] * scale
|
const rowHeight = rowHeightList[r] * scale
|
||||||
const rowItem = document.createElement('div')
|
const rowItem = document.createElement('div')
|
||||||
@@ -95,7 +96,7 @@ export class TableTool {
|
|||||||
}
|
}
|
||||||
const rowItemAnchor = document.createElement('div')
|
const rowItemAnchor = document.createElement('div')
|
||||||
rowItemAnchor.classList.add(`${EDITOR_PREFIX}-table-tool__anchor`)
|
rowItemAnchor.classList.add(`${EDITOR_PREFIX}-table-tool__anchor`)
|
||||||
rowItemAnchor.onmousedown = (evt) => {
|
rowItemAnchor.onmousedown = evt => {
|
||||||
this._mousedown({
|
this._mousedown({
|
||||||
evt,
|
evt,
|
||||||
element,
|
element,
|
||||||
@@ -116,7 +117,9 @@ export class TableTool {
|
|||||||
const colWidthList = colgroup!.map(col => col.width)
|
const colWidthList = colgroup!.map(col => col.width)
|
||||||
const colContainer = document.createElement('div')
|
const colContainer = document.createElement('div')
|
||||||
colContainer.classList.add(`${EDITOR_PREFIX}-table-tool__col`)
|
colContainer.classList.add(`${EDITOR_PREFIX}-table-tool__col`)
|
||||||
colContainer.style.transform = `translateY(-${this.ROW_COL_OFFSET * scale}px)`
|
colContainer.style.transform = `translateY(-${
|
||||||
|
this.ROW_COL_OFFSET * scale
|
||||||
|
}px)`
|
||||||
for (let c = 0; c < colWidthList.length; c++) {
|
for (let c = 0; c < colWidthList.length; c++) {
|
||||||
const colWidth = colWidthList[c] * scale
|
const colWidth = colWidthList[c] * scale
|
||||||
const colItem = document.createElement('div')
|
const colItem = document.createElement('div')
|
||||||
@@ -126,7 +129,7 @@ export class TableTool {
|
|||||||
}
|
}
|
||||||
const colItemAnchor = document.createElement('div')
|
const colItemAnchor = document.createElement('div')
|
||||||
colItemAnchor.classList.add(`${EDITOR_PREFIX}-table-tool__anchor`)
|
colItemAnchor.classList.add(`${EDITOR_PREFIX}-table-tool__anchor`)
|
||||||
colItemAnchor.onmousedown = (evt) => {
|
colItemAnchor.onmousedown = evt => {
|
||||||
this._mousedown({
|
this._mousedown({
|
||||||
evt,
|
evt,
|
||||||
element,
|
element,
|
||||||
@@ -160,9 +163,11 @@ export class TableTool {
|
|||||||
rowBorder.classList.add(`${EDITOR_PREFIX}-table-tool__border__row`)
|
rowBorder.classList.add(`${EDITOR_PREFIX}-table-tool__border__row`)
|
||||||
rowBorder.style.width = `${td.width! * scale}px`
|
rowBorder.style.width = `${td.width! * scale}px`
|
||||||
rowBorder.style.height = `${this.BORDER_VALUE}px`
|
rowBorder.style.height = `${this.BORDER_VALUE}px`
|
||||||
rowBorder.style.top = `${(td.y! + td.height!) * scale - this.BORDER_VALUE / 2}px`
|
rowBorder.style.top = `${
|
||||||
|
(td.y! + td.height!) * scale - this.BORDER_VALUE / 2
|
||||||
|
}px`
|
||||||
rowBorder.style.left = `${td.x! * scale}px`
|
rowBorder.style.left = `${td.x! * scale}px`
|
||||||
rowBorder.onmousedown = (evt) => {
|
rowBorder.onmousedown = evt => {
|
||||||
this._mousedown({
|
this._mousedown({
|
||||||
evt,
|
evt,
|
||||||
element,
|
element,
|
||||||
@@ -176,8 +181,10 @@ export class TableTool {
|
|||||||
colBorder.style.width = `${this.BORDER_VALUE}px`
|
colBorder.style.width = `${this.BORDER_VALUE}px`
|
||||||
colBorder.style.height = `${td.height! * scale}px`
|
colBorder.style.height = `${td.height! * scale}px`
|
||||||
colBorder.style.top = `${td.y! * scale}px`
|
colBorder.style.top = `${td.y! * scale}px`
|
||||||
colBorder.style.left = `${(td.x! + td.width!) * scale - this.BORDER_VALUE / 2}px`
|
colBorder.style.left = `${
|
||||||
colBorder.onmousedown = (evt) => {
|
(td.x! + td.width!) * scale - this.BORDER_VALUE / 2
|
||||||
|
}px`
|
||||||
|
colBorder.onmousedown = evt => {
|
||||||
this._mousedown({
|
this._mousedown({
|
||||||
evt,
|
evt,
|
||||||
element,
|
element,
|
||||||
@@ -239,82 +246,95 @@ export class TableTool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener('mousemove', mousemoveFn)
|
document.addEventListener('mousemove', mousemoveFn)
|
||||||
document.addEventListener('mouseup', () => {
|
document.addEventListener(
|
||||||
let isChangeSize = false
|
'mouseup',
|
||||||
// 改变尺寸
|
() => {
|
||||||
if (order === TableOrder.ROW) {
|
let isChangeSize = false
|
||||||
const tr = element.trList![index]
|
// 改变尺寸
|
||||||
// 最大移动高度-向上移动超出最小高度限定,则减少移动量
|
if (order === TableOrder.ROW) {
|
||||||
const { defaultTrMinHeight } = this.options
|
const tr = element.trList![index]
|
||||||
if (dy < 0 && tr.height + dy < defaultTrMinHeight) {
|
// 最大移动高度-向上移动超出最小高度限定,则减少移动量
|
||||||
dy = defaultTrMinHeight - tr.height
|
const { defaultTrMinHeight } = this.options
|
||||||
}
|
if (dy < 0 && tr.height + dy < defaultTrMinHeight) {
|
||||||
if (dy) {
|
dy = defaultTrMinHeight - tr.height
|
||||||
tr.height += dy
|
|
||||||
tr.minHeight = tr.height
|
|
||||||
isChangeSize = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const { colgroup } = element
|
|
||||||
if (colgroup && dx) {
|
|
||||||
// 宽度分配
|
|
||||||
const innerWidth = this.draw.getInnerWidth()
|
|
||||||
const curColWidth = colgroup[index].width
|
|
||||||
// 最小移动距离计算-如果向左移动:使单元格小于最小宽度,则减少移动量
|
|
||||||
if (dx < 0 && curColWidth + dx < this.MIN_TD_WIDTH) {
|
|
||||||
dx = this.MIN_TD_WIDTH - curColWidth
|
|
||||||
}
|
}
|
||||||
// 最大移动距离计算-如果向右移动:使后面一个单元格小于最小宽度,则减少移动量
|
if (dy) {
|
||||||
const nextColWidth = colgroup[index + 1]?.width
|
tr.height += dy
|
||||||
if (dx > 0 && nextColWidth && nextColWidth - dx < this.MIN_TD_WIDTH) {
|
tr.minHeight = tr.height
|
||||||
dx = nextColWidth - this.MIN_TD_WIDTH
|
|
||||||
}
|
|
||||||
const moveColWidth = curColWidth + dx
|
|
||||||
// 开始移动
|
|
||||||
let moveTableWidth = 0
|
|
||||||
for (let c = 0; c < colgroup.length; c++) {
|
|
||||||
const group = colgroup[c]
|
|
||||||
// 下一列减去偏移量
|
|
||||||
if (c === index + 1) {
|
|
||||||
moveTableWidth -= dx
|
|
||||||
}
|
|
||||||
// 当前列加上偏移量
|
|
||||||
if (c === index) {
|
|
||||||
moveTableWidth += moveColWidth
|
|
||||||
}
|
|
||||||
if (c !== index) {
|
|
||||||
moveTableWidth += group.width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (moveTableWidth > innerWidth) {
|
|
||||||
const tableWidth = element.width!
|
|
||||||
dx = innerWidth - tableWidth
|
|
||||||
}
|
|
||||||
if (dx) {
|
|
||||||
// 当前列增加,后列减少
|
|
||||||
if (colgroup.length - 1 !== index) {
|
|
||||||
colgroup[index + 1].width -= dx / scale
|
|
||||||
}
|
|
||||||
colgroup[index].width += dx / scale
|
|
||||||
isChangeSize = true
|
isChangeSize = true
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
const { colgroup } = element
|
||||||
|
if (colgroup && dx) {
|
||||||
|
// 宽度分配
|
||||||
|
const innerWidth = this.draw.getInnerWidth()
|
||||||
|
const curColWidth = colgroup[index].width
|
||||||
|
// 最小移动距离计算-如果向左移动:使单元格小于最小宽度,则减少移动量
|
||||||
|
if (dx < 0 && curColWidth + dx < this.MIN_TD_WIDTH) {
|
||||||
|
dx = this.MIN_TD_WIDTH - curColWidth
|
||||||
|
}
|
||||||
|
// 最大移动距离计算-如果向右移动:使后面一个单元格小于最小宽度,则减少移动量
|
||||||
|
const nextColWidth = colgroup[index + 1]?.width
|
||||||
|
if (
|
||||||
|
dx > 0 &&
|
||||||
|
nextColWidth &&
|
||||||
|
nextColWidth - dx < this.MIN_TD_WIDTH
|
||||||
|
) {
|
||||||
|
dx = nextColWidth - this.MIN_TD_WIDTH
|
||||||
|
}
|
||||||
|
const moveColWidth = curColWidth + dx
|
||||||
|
// 开始移动
|
||||||
|
let moveTableWidth = 0
|
||||||
|
for (let c = 0; c < colgroup.length; c++) {
|
||||||
|
const group = colgroup[c]
|
||||||
|
// 下一列减去偏移量
|
||||||
|
if (c === index + 1) {
|
||||||
|
moveTableWidth -= dx
|
||||||
|
}
|
||||||
|
// 当前列加上偏移量
|
||||||
|
if (c === index) {
|
||||||
|
moveTableWidth += moveColWidth
|
||||||
|
}
|
||||||
|
if (c !== index) {
|
||||||
|
moveTableWidth += group.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (moveTableWidth > innerWidth) {
|
||||||
|
const tableWidth = element.width!
|
||||||
|
dx = innerWidth - tableWidth
|
||||||
|
}
|
||||||
|
if (dx) {
|
||||||
|
// 当前列增加,后列减少
|
||||||
|
if (colgroup.length - 1 !== index) {
|
||||||
|
colgroup[index + 1].width -= dx / scale
|
||||||
|
}
|
||||||
|
colgroup[index].width += dx / scale
|
||||||
|
isChangeSize = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (isChangeSize) {
|
||||||
|
this.draw.render({ isSetCursor: false })
|
||||||
|
}
|
||||||
|
// 还原副作用
|
||||||
|
anchorLine.remove()
|
||||||
|
document.removeEventListener('mousemove', mousemoveFn)
|
||||||
|
document.body.style.cursor = ''
|
||||||
|
this.canvas.style.cursor = 'text'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
once: true
|
||||||
}
|
}
|
||||||
if (isChangeSize) {
|
)
|
||||||
this.draw.render({ isSetCursor: false })
|
|
||||||
}
|
|
||||||
// 还原副作用
|
|
||||||
anchorLine.remove()
|
|
||||||
document.removeEventListener('mousemove', mousemoveFn)
|
|
||||||
document.body.style.cursor = ''
|
|
||||||
this.canvas.style.cursor = 'text'
|
|
||||||
}, {
|
|
||||||
once: true
|
|
||||||
})
|
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
private _mousemove(evt: MouseEvent, tableOrder: TableOrder, startX: number, startY: number): { dx: number; dy: number } | null {
|
private _mousemove(
|
||||||
|
evt: MouseEvent,
|
||||||
|
tableOrder: TableOrder,
|
||||||
|
startX: number,
|
||||||
|
startY: number
|
||||||
|
): { dx: number; dy: number } | null {
|
||||||
if (!this.anchorLine) return null
|
if (!this.anchorLine) return null
|
||||||
const dx = evt.x - this.mousedownX
|
const dx = evt.x - this.mousedownX
|
||||||
const dy = evt.y - this.mousedownY
|
const dy = evt.y - this.mousedownY
|
||||||
@@ -326,5 +346,4 @@ export class TableTool {
|
|||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
return { dx, dy }
|
return { dx, dy }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,15 +10,23 @@ export abstract class AbstractRichText {
|
|||||||
|
|
||||||
public clearFillInfo() {
|
public clearFillInfo() {
|
||||||
this.fillColor = undefined
|
this.fillColor = undefined
|
||||||
return this.fillRect = {
|
this.fillRect = {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0
|
height: 0
|
||||||
}
|
}
|
||||||
|
return this.fillRect
|
||||||
}
|
}
|
||||||
|
|
||||||
public recordFillInfo(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height?: number, color?: string) {
|
public recordFillInfo(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
width: number,
|
||||||
|
height?: number,
|
||||||
|
color?: string
|
||||||
|
) {
|
||||||
const isFirstRecord = !this.fillRect.width
|
const isFirstRecord = !this.fillRect.width
|
||||||
if (!isFirstRecord && this.fillColor && this.fillColor !== color) {
|
if (!isFirstRecord && this.fillColor && this.fillColor !== color) {
|
||||||
this.render(ctx)
|
this.render(ctx)
|
||||||
@@ -37,5 +45,4 @@ export abstract class AbstractRichText {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract render(ctx: CanvasRenderingContext2D): void
|
public abstract render(ctx: CanvasRenderingContext2D): void
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { IEditorOption } from '../../../interface/Editor'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class Highlight extends AbstractRichText {
|
export class Highlight extends AbstractRichText {
|
||||||
|
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
@@ -22,5 +21,4 @@ export class Highlight extends AbstractRichText {
|
|||||||
ctx.restore()
|
ctx.restore()
|
||||||
this.clearFillInfo()
|
this.clearFillInfo()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { IEditorOption } from '../../../interface/Editor'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class Strikeout extends AbstractRichText {
|
export class Strikeout extends AbstractRichText {
|
||||||
|
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
@@ -25,5 +24,4 @@ export class Strikeout extends AbstractRichText {
|
|||||||
ctx.restore()
|
ctx.restore()
|
||||||
this.clearFillInfo()
|
this.clearFillInfo()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { IEditorOption } from '../../../interface/Editor'
|
|||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class Underline extends AbstractRichText {
|
export class Underline extends AbstractRichText {
|
||||||
|
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
@@ -25,5 +24,4 @@ export class Underline extends AbstractRichText {
|
|||||||
ctx.restore()
|
ctx.restore()
|
||||||
this.clearFillInfo()
|
this.clearFillInfo()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -20,14 +20,13 @@ import composition from './handlers/composition'
|
|||||||
import drag from './handlers/drag'
|
import drag from './handlers/drag'
|
||||||
|
|
||||||
export interface ICompositionInfo {
|
export interface ICompositionInfo {
|
||||||
elementList: IElement[];
|
elementList: IElement[]
|
||||||
startIndex: number;
|
startIndex: number
|
||||||
endIndex: number;
|
endIndex: number
|
||||||
value: string;
|
value: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CanvasEvent {
|
export class CanvasEvent {
|
||||||
|
|
||||||
public isAllowSelection: boolean
|
public isAllowSelection: boolean
|
||||||
public isComposing: boolean
|
public isComposing: boolean
|
||||||
public compositionInfo: ICompositionInfo | null
|
public compositionInfo: ICompositionInfo | null
|
||||||
@@ -70,7 +69,10 @@ export class CanvasEvent {
|
|||||||
public register() {
|
public register() {
|
||||||
this.pageContainer.addEventListener('mousedown', this.mousedown.bind(this))
|
this.pageContainer.addEventListener('mousedown', this.mousedown.bind(this))
|
||||||
this.pageContainer.addEventListener('mouseup', this.mouseup.bind(this))
|
this.pageContainer.addEventListener('mouseup', this.mouseup.bind(this))
|
||||||
this.pageContainer.addEventListener('mouseleave', this.mouseleave.bind(this))
|
this.pageContainer.addEventListener(
|
||||||
|
'mouseleave',
|
||||||
|
this.mouseleave.bind(this)
|
||||||
|
)
|
||||||
this.pageContainer.addEventListener('mousemove', this.mousemove.bind(this))
|
this.pageContainer.addEventListener('mousemove', this.mousemove.bind(this))
|
||||||
this.pageContainer.addEventListener('dblclick', this.dblclick.bind(this))
|
this.pageContainer.addEventListener('dblclick', this.dblclick.bind(this))
|
||||||
this.pageContainer.addEventListener('dragover', this.dragover.bind(this))
|
this.pageContainer.addEventListener('dragover', this.dragover.bind(this))
|
||||||
@@ -182,5 +184,4 @@ export class CanvasEvent {
|
|||||||
public dragover(evt: DragEvent | MouseEvent) {
|
public dragover(evt: DragEvent | MouseEvent) {
|
||||||
drag.dragover(evt, this)
|
drag.dragover(evt, this)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { RangeManager } from '../range/RangeManager'
|
|||||||
import { CanvasEvent } from './CanvasEvent'
|
import { CanvasEvent } from './CanvasEvent'
|
||||||
|
|
||||||
export class GlobalEvent {
|
export class GlobalEvent {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private canvas: HTMLCanvasElement
|
private canvas: HTMLCanvasElement
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
@@ -38,7 +37,9 @@ export class GlobalEvent {
|
|||||||
this.hyperlinkParticle = draw.getHyperlinkParticle()
|
this.hyperlinkParticle = draw.getHyperlinkParticle()
|
||||||
this.dateParticle = draw.getDateParticle()
|
this.dateParticle = draw.getDateParticle()
|
||||||
this.control = draw.getControl()
|
this.control = draw.getControl()
|
||||||
this.dprMediaQueryList = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`)
|
this.dprMediaQueryList = window.matchMedia(
|
||||||
|
`(resolution: ${window.devicePixelRatio}dppx)`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public register() {
|
public register() {
|
||||||
@@ -62,7 +63,10 @@ export class GlobalEvent {
|
|||||||
document.removeEventListener('click', this.recoverEffect)
|
document.removeEventListener('click', this.recoverEffect)
|
||||||
document.removeEventListener('mouseup', this.setCanvasEventAbility)
|
document.removeEventListener('mouseup', this.setCanvasEventAbility)
|
||||||
document.removeEventListener('wheel', this.setPageScale)
|
document.removeEventListener('wheel', this.setPageScale)
|
||||||
document.removeEventListener('visibilitychange', this._handleVisibilityChange)
|
document.removeEventListener(
|
||||||
|
'visibilitychange',
|
||||||
|
this._handleVisibilityChange
|
||||||
|
)
|
||||||
this.dprMediaQueryList.removeEventListener('change', this._handleDprChange)
|
this.dprMediaQueryList.removeEventListener('change', this._handleDprChange)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +82,8 @@ export class GlobalEvent {
|
|||||||
// 编辑器外部dom
|
// 编辑器外部dom
|
||||||
const outerEditorDom = findParent(
|
const outerEditorDom = findParent(
|
||||||
evt.target as Element,
|
evt.target as Element,
|
||||||
(node: Node & Element) => !!node && node.nodeType === 1 && !!node.getAttribute(EDITOR_COMPONENT),
|
(node: Node & Element) =>
|
||||||
|
!!node && node.nodeType === 1 && !!node.getAttribute(EDITOR_COMPONENT),
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
if (outerEditorDom) {
|
if (outerEditorDom) {
|
||||||
@@ -149,5 +154,4 @@ export class GlobalEvent {
|
|||||||
private _handleDprChange = () => {
|
private _handleDprChange = () => {
|
||||||
this.draw.setPageDevicePixel()
|
this.draw.setPageDevicePixel()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ function dblclick(host: CanvasEvent, evt: MouseEvent) {
|
|||||||
let upStartIndex = index - 1
|
let upStartIndex = index - 1
|
||||||
while (upStartIndex > 0) {
|
while (upStartIndex > 0) {
|
||||||
const value = elementList[upStartIndex].value
|
const value = elementList[upStartIndex].value
|
||||||
if ((isNumber && NUMBER_LIKE_REG.test(value)) || (!isNumber && LETTER_REG.test(value))) {
|
if (
|
||||||
|
(isNumber && NUMBER_LIKE_REG.test(value)) ||
|
||||||
|
(!isNumber && LETTER_REG.test(value))
|
||||||
|
) {
|
||||||
upCount++
|
upCount++
|
||||||
upStartIndex--
|
upStartIndex--
|
||||||
} else {
|
} else {
|
||||||
@@ -41,7 +44,10 @@ function dblclick(host: CanvasEvent, evt: MouseEvent) {
|
|||||||
let downStartIndex = index + 1
|
let downStartIndex = index + 1
|
||||||
while (downStartIndex < elementList.length) {
|
while (downStartIndex < elementList.length) {
|
||||||
const value = elementList[downStartIndex].value
|
const value = elementList[downStartIndex].value
|
||||||
if ((isNumber && NUMBER_LIKE_REG.test(value)) || (!isNumber && LETTER_REG.test(value))) {
|
if (
|
||||||
|
(isNumber && NUMBER_LIKE_REG.test(value)) ||
|
||||||
|
(!isNumber && LETTER_REG.test(value))
|
||||||
|
) {
|
||||||
downCount++
|
downCount++
|
||||||
downStartIndex++
|
downStartIndex++
|
||||||
} else {
|
} else {
|
||||||
@@ -106,4 +112,4 @@ function threeClick(host: CanvasEvent) {
|
|||||||
export default {
|
export default {
|
||||||
dblclick,
|
dblclick,
|
||||||
threeClick
|
threeClick
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,4 +34,4 @@ function compositionend(host: CanvasEvent, evt: CompositionEvent) {
|
|||||||
export default {
|
export default {
|
||||||
compositionstart,
|
compositionstart,
|
||||||
compositionend
|
compositionend
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ export function copy(host: CanvasEvent) {
|
|||||||
const elementList = draw.getElementList()
|
const elementList = draw.getElementList()
|
||||||
writeElementList(elementList.slice(startIndex + 1, endIndex + 1), options)
|
writeElementList(elementList.slice(startIndex + 1, endIndex + 1), options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,4 +46,4 @@ export function cut(host: CanvasEvent) {
|
|||||||
}
|
}
|
||||||
rangeManager.setRange(curIndex, curIndex)
|
rangeManager.setRange(curIndex, curIndex)
|
||||||
draw.render({ curIndex })
|
draw.render({ curIndex })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ function dragover(evt: DragEvent | MouseEvent, host: CanvasEvent) {
|
|||||||
position.setCursorPosition(positionList[curIndex])
|
position.setCursorPosition(positionList[curIndex])
|
||||||
}
|
}
|
||||||
const cursor = draw.getCursor()
|
const cursor = draw.getCursor()
|
||||||
const { cursor: { dragColor, dragWidth } } = draw.getOptions()
|
const {
|
||||||
|
cursor: { dragColor, dragWidth }
|
||||||
|
} = draw.getOptions()
|
||||||
cursor.drawCursor({
|
cursor.drawCursor({
|
||||||
width: dragWidth,
|
width: dragWidth,
|
||||||
color: dragColor,
|
color: dragColor,
|
||||||
@@ -46,4 +48,4 @@ function dragover(evt: DragEvent | MouseEvent, host: CanvasEvent) {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
dragover
|
dragover
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ export function drop(evt: DragEvent, host: CanvasEvent) {
|
|||||||
if (data) {
|
if (data) {
|
||||||
host.input(data)
|
host.input(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,12 +42,12 @@ export function input(data: string, host: CanvasEvent) {
|
|||||||
}
|
}
|
||||||
const nextElement = elementList[endIndex + 1]
|
const nextElement = elementList[endIndex + 1]
|
||||||
if (
|
if (
|
||||||
copyElement.type === TEXT
|
copyElement.type === TEXT ||
|
||||||
|| (!copyElement.type && copyElement.value !== ZERO)
|
(!copyElement.type && copyElement.value !== ZERO) ||
|
||||||
|| (copyElement.type === HYPERLINK && nextElement?.type === HYPERLINK)
|
(copyElement.type === HYPERLINK && nextElement?.type === HYPERLINK) ||
|
||||||
|| (copyElement.type === DATE && nextElement?.type === DATE)
|
(copyElement.type === DATE && nextElement?.type === DATE) ||
|
||||||
|| (copyElement.type === SUBSCRIPT && nextElement?.type === SUBSCRIPT)
|
(copyElement.type === SUBSCRIPT && nextElement?.type === SUBSCRIPT) ||
|
||||||
|| (copyElement.type === SUPERSCRIPT && nextElement?.type === SUPERSCRIPT)
|
(copyElement.type === SUPERSCRIPT && nextElement?.type === SUPERSCRIPT)
|
||||||
) {
|
) {
|
||||||
EDITOR_ELEMENT_COPY_ATTR.forEach(attr => {
|
EDITOR_ELEMENT_COPY_ATTR.forEach(attr => {
|
||||||
const value = copyElement[attr] as never
|
const value = copyElement[attr] as never
|
||||||
@@ -98,4 +98,4 @@ export function removeComposingInput(host: CanvasEvent) {
|
|||||||
const rangeManager = host.getDraw().getRange()
|
const rangeManager = host.getDraw().getRange()
|
||||||
rangeManager.setRange(startIndex, startIndex)
|
rangeManager.setRange(startIndex, startIndex)
|
||||||
host.compositionInfo = null
|
host.compositionInfo = null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,11 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (!isCollapsed) {
|
if (!isCollapsed) {
|
||||||
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
startIndex + 1,
|
||||||
|
endIndex - startIndex
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
draw.spliceElementList(elementList, index, 1)
|
draw.spliceElementList(elementList, index, 1)
|
||||||
}
|
}
|
||||||
@@ -64,7 +68,11 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
curIndex = control.removeControl(endIndex + 1)
|
curIndex = control.removeControl(endIndex + 1)
|
||||||
} else {
|
} else {
|
||||||
if (!isCollapsed) {
|
if (!isCollapsed) {
|
||||||
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
startIndex + 1,
|
||||||
|
endIndex - startIndex
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
draw.spliceElementList(elementList, index + 1, 1)
|
draw.spliceElementList(elementList, index + 1, 1)
|
||||||
}
|
}
|
||||||
@@ -84,7 +92,12 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
enterText.listWrap = true
|
enterText.listWrap = true
|
||||||
}
|
}
|
||||||
// 标题结尾处回车无需格式化
|
// 标题结尾处回车无需格式化
|
||||||
if (!(endElement.titleId && endElement.titleId !== elementList[endIndex + 1]?.titleId)) {
|
if (
|
||||||
|
!(
|
||||||
|
endElement.titleId &&
|
||||||
|
endElement.titleId !== elementList[endIndex + 1]?.titleId
|
||||||
|
)
|
||||||
|
) {
|
||||||
formatElementContext(elementList, [enterText], startIndex)
|
formatElementContext(elementList, [enterText], startIndex)
|
||||||
}
|
}
|
||||||
let curIndex: number
|
let curIndex: number
|
||||||
@@ -94,7 +107,12 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
if (isCollapsed) {
|
if (isCollapsed) {
|
||||||
draw.spliceElementList(elementList, index + 1, 0, enterText)
|
draw.spliceElementList(elementList, index + 1, 0, enterText)
|
||||||
} else {
|
} else {
|
||||||
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex, enterText)
|
draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
startIndex + 1,
|
||||||
|
endIndex - startIndex,
|
||||||
|
enterText
|
||||||
|
)
|
||||||
}
|
}
|
||||||
curIndex = index + 1
|
curIndex = index + 1
|
||||||
}
|
}
|
||||||
@@ -159,7 +177,12 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const maxElementListIndex = elementList.length - 1
|
const maxElementListIndex = elementList.length - 1
|
||||||
if (anchorStartIndex > maxElementListIndex || anchorEndIndex > maxElementListIndex) return
|
if (
|
||||||
|
anchorStartIndex > maxElementListIndex ||
|
||||||
|
anchorEndIndex > maxElementListIndex
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
rangeManager.setRange(anchorStartIndex, anchorEndIndex)
|
rangeManager.setRange(anchorStartIndex, anchorEndIndex)
|
||||||
const isCollapsed = anchorStartIndex === anchorEndIndex
|
const isCollapsed = anchorStartIndex === anchorEndIndex
|
||||||
draw.render({
|
draw.render({
|
||||||
@@ -181,21 +204,31 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
anchorPosition = positionList[startIndex]
|
anchorPosition = positionList[startIndex]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const { rowNo, index, pageNo, coordinate: { leftTop, rightTop } } = anchorPosition
|
const {
|
||||||
|
rowNo,
|
||||||
|
index,
|
||||||
|
pageNo,
|
||||||
|
coordinate: { leftTop, rightTop }
|
||||||
|
} = anchorPosition
|
||||||
if ((isUp && rowNo !== 0) || (!isUp && rowNo !== draw.getRowCount())) {
|
if ((isUp && rowNo !== 0) || (!isUp && rowNo !== draw.getRowCount())) {
|
||||||
// 下一个光标点所在行位置集合
|
// 下一个光标点所在行位置集合
|
||||||
const probablePosition = isUp
|
const probablePosition = isUp
|
||||||
? positionList.slice(0, index)
|
? positionList
|
||||||
.filter(p => p.rowNo === rowNo - 1 && pageNo === p.pageNo)
|
.slice(0, index)
|
||||||
: positionList.slice(index, positionList.length - 1)
|
.filter(p => p.rowNo === rowNo - 1 && pageNo === p.pageNo)
|
||||||
.filter(p => p.rowNo === rowNo + 1 && pageNo === p.pageNo)
|
: positionList
|
||||||
|
.slice(index, positionList.length - 1)
|
||||||
|
.filter(p => p.rowNo === rowNo + 1 && pageNo === p.pageNo)
|
||||||
// 查找与当前位置元素点交叉最多的位置
|
// 查找与当前位置元素点交叉最多的位置
|
||||||
let maxIndex = 0
|
let maxIndex = 0
|
||||||
let maxDistance = 0
|
let maxDistance = 0
|
||||||
for (let p = 0; p < probablePosition.length; p++) {
|
for (let p = 0; p < probablePosition.length; p++) {
|
||||||
const position = probablePosition[p]
|
const position = probablePosition[p]
|
||||||
// 当前光标在前
|
// 当前光标在前
|
||||||
if (position.coordinate.leftTop[0] >= leftTop[0] && position.coordinate.leftTop[0] <= rightTop[0]) {
|
if (
|
||||||
|
position.coordinate.leftTop[0] >= leftTop[0] &&
|
||||||
|
position.coordinate.leftTop[0] <= rightTop[0]
|
||||||
|
) {
|
||||||
const curDistance = rightTop[0] - position.coordinate.leftTop[0]
|
const curDistance = rightTop[0] - position.coordinate.leftTop[0]
|
||||||
if (curDistance > maxDistance) {
|
if (curDistance > maxDistance) {
|
||||||
maxIndex = position.index
|
maxIndex = position.index
|
||||||
@@ -204,7 +237,10 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 当前光标在后
|
// 当前光标在后
|
||||||
else if (position.coordinate.leftTop[0] <= leftTop[0] && position.coordinate.rightTop[0] >= leftTop[0]) {
|
else if (
|
||||||
|
position.coordinate.leftTop[0] <= leftTop[0] &&
|
||||||
|
position.coordinate.rightTop[0] >= leftTop[0]
|
||||||
|
) {
|
||||||
const curDistance = position.coordinate.rightTop[0] - leftTop[0]
|
const curDistance = position.coordinate.rightTop[0] - leftTop[0]
|
||||||
if (curDistance > maxDistance) {
|
if (curDistance > maxDistance) {
|
||||||
maxIndex = position.index
|
maxIndex = position.index
|
||||||
@@ -237,6 +273,7 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (anchorStartIndex > anchorEndIndex) {
|
if (anchorStartIndex > anchorEndIndex) {
|
||||||
|
// prettier-ignore
|
||||||
[anchorStartIndex, anchorEndIndex] = [anchorEndIndex, anchorStartIndex]
|
[anchorStartIndex, anchorEndIndex] = [anchorEndIndex, anchorStartIndex]
|
||||||
}
|
}
|
||||||
rangeManager.setRange(anchorStartIndex, anchorEndIndex)
|
rangeManager.setRange(anchorStartIndex, anchorEndIndex)
|
||||||
@@ -282,10 +319,12 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
}
|
}
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
} else if (evt.key === KeyMap.TAB) {
|
} else if (evt.key === KeyMap.TAB) {
|
||||||
draw.insertElementList([{
|
draw.insertElementList([
|
||||||
type: ElementType.TAB,
|
{
|
||||||
value: ''
|
type: ElementType.TAB,
|
||||||
}])
|
value: ''
|
||||||
|
}
|
||||||
|
])
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
if (!host.isAllowDrag) {
|
if (!host.isAllowDrag) {
|
||||||
const range = rangeManager.getRange()
|
const range = rangeManager.getRange()
|
||||||
if (!isReadonly && range.startIndex !== range.endIndex) {
|
if (!isReadonly && range.startIndex !== range.endIndex) {
|
||||||
const isPointInRange = rangeManager.getIsPointInRange(evt.offsetX, evt.offsetY)
|
const isPointInRange = rangeManager.getIsPointInRange(
|
||||||
|
evt.offsetX,
|
||||||
|
evt.offsetY
|
||||||
|
)
|
||||||
if (isPointInRange) {
|
if (isPointInRange) {
|
||||||
host.isAllowDrag = true
|
host.isAllowDrag = true
|
||||||
host.cacheRange = deepClone(range)
|
host.cacheRange = deepClone(range)
|
||||||
@@ -37,14 +40,8 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
y: evt.offsetY
|
y: evt.offsetY
|
||||||
})
|
})
|
||||||
if (!positionResult) return
|
if (!positionResult) return
|
||||||
const {
|
const { index, isDirectHit, isCheckbox, isImage, isTable, tdValueIndex } =
|
||||||
index,
|
positionResult
|
||||||
isDirectHit,
|
|
||||||
isCheckbox,
|
|
||||||
isImage,
|
|
||||||
isTable,
|
|
||||||
tdValueIndex,
|
|
||||||
} = positionResult
|
|
||||||
// 记录选区开始位置
|
// 记录选区开始位置
|
||||||
host.mouseDownStartPosition = {
|
host.mouseDownStartPosition = {
|
||||||
...positionResult,
|
...positionResult,
|
||||||
@@ -88,13 +85,16 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
const previewer = draw.getPreviewer()
|
const previewer = draw.getPreviewer()
|
||||||
previewer.clearResizer()
|
previewer.clearResizer()
|
||||||
if (isDirectHitImage && !isReadonly) {
|
if (isDirectHitImage && !isReadonly) {
|
||||||
previewer.drawResizer(curElement, positionList[curIndex],
|
previewer.drawResizer(
|
||||||
|
curElement,
|
||||||
|
positionList[curIndex],
|
||||||
curElement.type === ElementType.LATEX
|
curElement.type === ElementType.LATEX
|
||||||
? {
|
? {
|
||||||
mime: 'svg',
|
mime: 'svg',
|
||||||
srcKey: 'laTexSVG'
|
srcKey: 'laTexSVG'
|
||||||
}
|
}
|
||||||
: {})
|
: {}
|
||||||
|
)
|
||||||
// 光标事件代理丢失,重新定位
|
// 光标事件代理丢失,重新定位
|
||||||
draw.getCursor().drawCursor({
|
draw.getCursor().drawCursor({
|
||||||
isShow: false
|
isShow: false
|
||||||
@@ -122,4 +122,4 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
if (curElement.type === ElementType.DATE && !isReadonly) {
|
if (curElement.type === ElementType.DATE && !isReadonly) {
|
||||||
dateParticle.renderDatePicker(curElement, positionList[curIndex])
|
dateParticle.renderDatePicker(curElement, positionList[curIndex])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ export function mouseleave(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
const draw = host.getDraw()
|
const draw = host.getDraw()
|
||||||
const pageContainer = draw.getPageContainer()
|
const pageContainer = draw.getPageContainer()
|
||||||
const { x, y, width, height } = pageContainer.getBoundingClientRect()
|
const { x, y, width, height } = pageContainer.getBoundingClientRect()
|
||||||
if (evt.x >= x && evt.x <= x + width && evt.y >= y && evt.y <= y + height) return
|
if (evt.x >= x && evt.x <= x + width && evt.y >= y && evt.y <= y + height) {
|
||||||
|
return
|
||||||
|
}
|
||||||
host.setIsAllowSelection(false)
|
host.setIsAllowSelection(false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,15 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
const { startIndex, endIndex } = host.cacheRange!
|
const { startIndex, endIndex } = host.cacheRange!
|
||||||
const positionList = host.cachePositionList!
|
const positionList = host.cachePositionList!
|
||||||
for (let p = startIndex + 1; p <= endIndex; p++) {
|
for (let p = startIndex + 1; p <= endIndex; p++) {
|
||||||
const { coordinate: { leftTop, rightBottom } } = positionList[p]
|
const {
|
||||||
if (x >= leftTop[0] && x <= rightBottom[0] && y >= leftTop[1] && y <= rightBottom[1]) {
|
coordinate: { leftTop, rightBottom }
|
||||||
|
} = positionList[p]
|
||||||
|
if (
|
||||||
|
x >= leftTop[0] &&
|
||||||
|
x <= rightBottom[0] &&
|
||||||
|
y >= leftTop[1] &&
|
||||||
|
y <= rightBottom[1]
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,14 +40,8 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
y: evt.offsetY
|
y: evt.offsetY
|
||||||
})
|
})
|
||||||
if (!~positionResult.index) return
|
if (!~positionResult.index) return
|
||||||
const {
|
const { index, isTable, tdValueIndex, tdIndex, trIndex, tableId } =
|
||||||
index,
|
positionResult
|
||||||
isTable,
|
|
||||||
tdValueIndex,
|
|
||||||
tdIndex,
|
|
||||||
trIndex,
|
|
||||||
tableId
|
|
||||||
} = positionResult
|
|
||||||
const {
|
const {
|
||||||
index: startIndex,
|
index: startIndex,
|
||||||
isTable: startIsTable,
|
isTable: startIsTable,
|
||||||
@@ -50,7 +51,11 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
const endIndex = isTable ? tdValueIndex! : index
|
const endIndex = isTable ? tdValueIndex! : index
|
||||||
// 判断是否是表格跨行/列
|
// 判断是否是表格跨行/列
|
||||||
const rangeManager = draw.getRange()
|
const rangeManager = draw.getRange()
|
||||||
if (isTable && startIsTable && (tdIndex !== startTdIndex || trIndex !== startTrIndex)) {
|
if (
|
||||||
|
isTable &&
|
||||||
|
startIsTable &&
|
||||||
|
(tdIndex !== startTdIndex || trIndex !== startTrIndex)
|
||||||
|
) {
|
||||||
rangeManager.setRange(
|
rangeManager.setRange(
|
||||||
endIndex,
|
endIndex,
|
||||||
endIndex,
|
endIndex,
|
||||||
@@ -65,6 +70,7 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
// 开始位置
|
// 开始位置
|
||||||
let start = startIndex
|
let start = startIndex
|
||||||
if (start > end) {
|
if (start > end) {
|
||||||
|
// prettier-ignore
|
||||||
[start, end] = [end, start]
|
[start, end] = [end, start]
|
||||||
}
|
}
|
||||||
if (start === end) return
|
if (start === end) return
|
||||||
@@ -76,4 +82,4 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isCompute: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ function createDragId(element: IElement): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getElementIndexByDragId(dragId: string, elementList: IElement[]) {
|
function getElementIndexByDragId(dragId: string, elementList: IElement[]) {
|
||||||
return (<IDragElement[]>elementList).findIndex((el) => el.dragId === dragId)
|
return (<IDragElement[]>elementList).findIndex(el => el.dragId === dragId)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
||||||
@@ -30,7 +30,10 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
const cachePositionList = host.cachePositionList!
|
const cachePositionList = host.cachePositionList!
|
||||||
const range = rangeManager.getRange()
|
const range = rangeManager.getRange()
|
||||||
// 是否需要拖拽-位置发生改变
|
// 是否需要拖拽-位置发生改变
|
||||||
if (range.startIndex >= cacheRange.startIndex && range.endIndex <= cacheRange.endIndex) {
|
if (
|
||||||
|
range.startIndex >= cacheRange.startIndex &&
|
||||||
|
range.endIndex <= cacheRange.endIndex
|
||||||
|
) {
|
||||||
rangeManager.replaceRange({
|
rangeManager.replaceRange({
|
||||||
...cacheRange
|
...cacheRange
|
||||||
})
|
})
|
||||||
@@ -42,34 +45,29 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 是否是不可拖拽的控件结构元素
|
// 是否是不可拖拽的控件结构元素
|
||||||
const dragElementList = cacheElementList.slice(cacheRange.startIndex + 1, cacheRange.endIndex + 1)
|
const dragElementList = cacheElementList.slice(
|
||||||
const isContainControl = dragElementList.find(element => element.type === ElementType.CONTROL)
|
cacheRange.startIndex + 1,
|
||||||
|
cacheRange.endIndex + 1
|
||||||
|
)
|
||||||
|
const isContainControl = dragElementList.find(
|
||||||
|
element => element.type === ElementType.CONTROL
|
||||||
|
)
|
||||||
if (isContainControl) {
|
if (isContainControl) {
|
||||||
// 仅允许 (最前/后元素不是控件 || 在控件前后 || 文本控件且是值) 拖拽
|
// 仅允许 (最前/后元素不是控件 || 在控件前后 || 文本控件且是值) 拖拽
|
||||||
const cacheStartElement = cacheElementList[cacheRange.startIndex + 1]
|
const cacheStartElement = cacheElementList[cacheRange.startIndex + 1]
|
||||||
const cacheEndElement = cacheElementList[cacheRange.endIndex]
|
const cacheEndElement = cacheElementList[cacheRange.endIndex]
|
||||||
const isAllowDragControl =
|
const isAllowDragControl =
|
||||||
(
|
((cacheStartElement.type !== ElementType.CONTROL ||
|
||||||
(
|
cacheStartElement.controlComponent === ControlComponent.PREFIX) &&
|
||||||
cacheStartElement.type !== ElementType.CONTROL ||
|
(cacheEndElement.type !== ElementType.CONTROL ||
|
||||||
cacheStartElement.controlComponent === ControlComponent.PREFIX
|
cacheEndElement.controlComponent === ControlComponent.POSTFIX)) ||
|
||||||
) &&
|
(cacheStartElement.controlId === cacheEndElement.controlId &&
|
||||||
(
|
|
||||||
cacheEndElement.type !== ElementType.CONTROL ||
|
|
||||||
cacheEndElement.controlComponent === ControlComponent.POSTFIX
|
|
||||||
)
|
|
||||||
) ||
|
|
||||||
(
|
|
||||||
cacheStartElement.controlId === cacheEndElement.controlId &&
|
|
||||||
cacheStartElement.controlComponent === ControlComponent.PREFIX &&
|
cacheStartElement.controlComponent === ControlComponent.PREFIX &&
|
||||||
cacheEndElement.controlComponent === ControlComponent.POSTFIX
|
cacheEndElement.controlComponent === ControlComponent.POSTFIX) ||
|
||||||
) ||
|
(cacheStartElement.control?.type === ControlType.TEXT &&
|
||||||
(
|
|
||||||
cacheStartElement.control?.type === ControlType.TEXT &&
|
|
||||||
cacheStartElement.controlComponent === ControlComponent.VALUE &&
|
cacheStartElement.controlComponent === ControlComponent.VALUE &&
|
||||||
cacheEndElement.control?.type === ControlType.TEXT &&
|
cacheEndElement.control?.type === ControlType.TEXT &&
|
||||||
cacheEndElement.controlComponent === ControlComponent.VALUE
|
cacheEndElement.controlComponent === ControlComponent.VALUE)
|
||||||
)
|
|
||||||
if (!isAllowDragControl) {
|
if (!isAllowDragControl) {
|
||||||
draw.render({
|
draw.render({
|
||||||
curIndex: range.startIndex,
|
curIndex: range.startIndex,
|
||||||
@@ -83,7 +81,11 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
const editorOptions = draw.getOptions()
|
const editorOptions = draw.getOptions()
|
||||||
const elementList = draw.getElementList()
|
const elementList = draw.getElementList()
|
||||||
const replaceElementList = dragElementList.map(el => {
|
const replaceElementList = dragElementList.map(el => {
|
||||||
if (!el.type || el.type === ElementType.TEXT || el.control?.type === ControlType.TEXT) {
|
if (
|
||||||
|
!el.type ||
|
||||||
|
el.type === ElementType.TEXT ||
|
||||||
|
el.control?.type === ControlType.TEXT
|
||||||
|
) {
|
||||||
const newElement: IElement = {
|
const newElement: IElement = {
|
||||||
value: el.value
|
value: el.value
|
||||||
}
|
}
|
||||||
@@ -98,14 +100,16 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
const newElement = deepClone(el)
|
const newElement = deepClone(el)
|
||||||
formatElementList([newElement], {
|
formatElementList([newElement], {
|
||||||
isHandleFirstElement: false,
|
isHandleFirstElement: false,
|
||||||
editorOptions,
|
editorOptions
|
||||||
})
|
})
|
||||||
return newElement
|
return newElement
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
formatElementContext(elementList, replaceElementList, range.startIndex)
|
formatElementContext(elementList, replaceElementList, range.startIndex)
|
||||||
// 缓存拖拽选区开始结束id
|
// 缓存拖拽选区开始结束id
|
||||||
const cacheRangeStartId = createDragId(cacheElementList[cacheRange.startIndex])
|
const cacheRangeStartId = createDragId(
|
||||||
|
cacheElementList[cacheRange.startIndex]
|
||||||
|
)
|
||||||
const cacheRangeEndId = createDragId(cacheElementList[cacheRange.endIndex])
|
const cacheRangeEndId = createDragId(cacheElementList[cacheRange.endIndex])
|
||||||
// 设置拖拽值
|
// 设置拖拽值
|
||||||
const replaceLength = replaceElementList.length
|
const replaceLength = replaceElementList.length
|
||||||
@@ -113,11 +117,19 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
let rangeEnd = rangeStart + replaceLength
|
let rangeEnd = rangeStart + replaceLength
|
||||||
const control = draw.getControl()
|
const control = draw.getControl()
|
||||||
const activeControl = control.getActiveControl()
|
const activeControl = control.getActiveControl()
|
||||||
if (activeControl && cacheElementList[rangeStart].controlComponent !== ControlComponent.POSTFIX) {
|
if (
|
||||||
|
activeControl &&
|
||||||
|
cacheElementList[rangeStart].controlComponent !== ControlComponent.POSTFIX
|
||||||
|
) {
|
||||||
rangeEnd = activeControl.setValue(replaceElementList)
|
rangeEnd = activeControl.setValue(replaceElementList)
|
||||||
rangeStart = rangeEnd - replaceLength
|
rangeStart = rangeEnd - replaceLength
|
||||||
} else {
|
} else {
|
||||||
draw.spliceElementList(elementList, rangeStart + 1, 0, ...replaceElementList)
|
draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
rangeStart + 1,
|
||||||
|
0,
|
||||||
|
...replaceElementList
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (!~rangeEnd) {
|
if (!~rangeEnd) {
|
||||||
draw.render({
|
draw.render({
|
||||||
@@ -129,10 +141,19 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
const rangeStartId = createDragId(elementList[rangeStart])
|
const rangeStartId = createDragId(elementList[rangeStart])
|
||||||
const rangeEndId = createDragId(elementList[rangeEnd])
|
const rangeEndId = createDragId(elementList[rangeEnd])
|
||||||
// 删除原有拖拽元素
|
// 删除原有拖拽元素
|
||||||
const cacheRangeStartIndex = getElementIndexByDragId(cacheRangeStartId, cacheElementList)
|
const cacheRangeStartIndex = getElementIndexByDragId(
|
||||||
const cacheRangeEndIndex = getElementIndexByDragId(cacheRangeEndId, cacheElementList)
|
cacheRangeStartId,
|
||||||
|
cacheElementList
|
||||||
|
)
|
||||||
|
const cacheRangeEndIndex = getElementIndexByDragId(
|
||||||
|
cacheRangeEndId,
|
||||||
|
cacheElementList
|
||||||
|
)
|
||||||
const cacheEndElement = cacheElementList[cacheRangeEndIndex]
|
const cacheEndElement = cacheElementList[cacheRangeEndIndex]
|
||||||
if (cacheEndElement.type === ElementType.CONTROL && cacheEndElement.controlComponent !== ControlComponent.POSTFIX) {
|
if (
|
||||||
|
cacheEndElement.type === ElementType.CONTROL &&
|
||||||
|
cacheEndElement.controlComponent !== ControlComponent.POSTFIX
|
||||||
|
) {
|
||||||
rangeManager.replaceRange({
|
rangeManager.replaceRange({
|
||||||
...cacheRange,
|
...cacheRange,
|
||||||
startIndex: cacheRangeStartIndex,
|
startIndex: cacheRangeStartIndex,
|
||||||
@@ -140,7 +161,11 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
})
|
})
|
||||||
control.getActiveControl()?.cut()
|
control.getActiveControl()?.cut()
|
||||||
} else {
|
} else {
|
||||||
draw.spliceElementList(cacheElementList, cacheRangeStartIndex + 1, cacheRangeEndIndex - cacheRangeStartIndex)
|
draw.spliceElementList(
|
||||||
|
cacheElementList,
|
||||||
|
cacheRangeStartIndex + 1,
|
||||||
|
cacheRangeEndIndex - cacheRangeStartIndex
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// 重设上下文
|
// 重设上下文
|
||||||
const startElement = elementList[range.startIndex]
|
const startElement = elementList[range.startIndex]
|
||||||
@@ -186,4 +211,4 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
// 如果是允许拖拽不允许拖放则光标重置
|
// 如果是允许拖拽不允许拖放则光标重置
|
||||||
host.mousedown(evt)
|
host.mousedown(evt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Draw } from '../draw/Draw'
|
import { Draw } from '../draw/Draw'
|
||||||
|
|
||||||
export class HistoryManager {
|
export class HistoryManager {
|
||||||
|
|
||||||
private undoStack: Array<Function> = []
|
private undoStack: Array<Function> = []
|
||||||
private redoStack: Array<Function> = []
|
private redoStack: Array<Function> = []
|
||||||
private maxRecordCount: number
|
private maxRecordCount: number
|
||||||
@@ -51,5 +50,4 @@ export class HistoryManager {
|
|||||||
this.undoStack = []
|
this.undoStack = []
|
||||||
this.redoStack = []
|
this.redoStack = []
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { mergeObject } from '../../utils'
|
|||||||
import { DeepPartial } from '../../interface/Common'
|
import { DeepPartial } from '../../interface/Common'
|
||||||
|
|
||||||
export class I18n {
|
export class I18n {
|
||||||
|
|
||||||
private langMap: Map<string, ILang> = new Map([
|
private langMap: Map<string, ILang> = new Map([
|
||||||
['zhCN', zhCN],
|
['zhCN', zhCN],
|
||||||
['en', en]
|
['en', en]
|
||||||
@@ -15,10 +14,7 @@ export class I18n {
|
|||||||
|
|
||||||
public registerLangMap(locale: string, lang: DeepPartial<ILang>) {
|
public registerLangMap(locale: string, lang: DeepPartial<ILang>) {
|
||||||
const sourceLang = this.langMap.get(locale)
|
const sourceLang = this.langMap.get(locale)
|
||||||
this.langMap.set(
|
this.langMap.set(locale, <ILang>mergeObject(sourceLang || zhCN, lang))
|
||||||
locale,
|
|
||||||
<ILang>mergeObject(sourceLang || zhCN, lang)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public setLocale(locale: string) {
|
public setLocale(locale: string) {
|
||||||
@@ -44,5 +40,4 @@ export class I18n {
|
|||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
} from '../../interface/Listener'
|
} from '../../interface/Listener'
|
||||||
|
|
||||||
export class Listener {
|
export class Listener {
|
||||||
|
|
||||||
public rangeStyleChange: IRangeStyleChange | null
|
public rangeStyleChange: IRangeStyleChange | null
|
||||||
public visiblePageNoListChange: IVisiblePageNoListChange | null
|
public visiblePageNoListChange: IVisiblePageNoListChange | null
|
||||||
public intersectionPageNoChange: IIntersectionPageNoChange | null
|
public intersectionPageNoChange: IIntersectionPageNoChange | null
|
||||||
@@ -36,5 +35,4 @@ export class Listener {
|
|||||||
this.pageModeChange = null
|
this.pageModeChange = null
|
||||||
this.zoneChange = null
|
this.zoneChange = null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
export class ImageObserver {
|
export class ImageObserver {
|
||||||
|
|
||||||
private promiseList: Promise<unknown>[]
|
private promiseList: Promise<unknown>[]
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -17,5 +16,4 @@ export class ImageObserver {
|
|||||||
public allSettled() {
|
public allSettled() {
|
||||||
return Promise.allSettled(this.promiseList)
|
return Promise.allSettled(this.promiseList)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,16 +2,15 @@ import { debounce } from '../../utils'
|
|||||||
import { Draw } from '../draw/Draw'
|
import { Draw } from '../draw/Draw'
|
||||||
|
|
||||||
export interface IElementVisibleInfo {
|
export interface IElementVisibleInfo {
|
||||||
intersectionHeight: number;
|
intersectionHeight: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPageVisibleInfo {
|
export interface IPageVisibleInfo {
|
||||||
intersectionPageNo: number;
|
intersectionPageNo: number
|
||||||
visiblePageNoList: number[];
|
visiblePageNoList: number[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ScrollObserver {
|
export class ScrollObserver {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
@@ -35,8 +34,12 @@ export class ScrollObserver {
|
|||||||
|
|
||||||
public getElementVisibleInfo(element: Element): IElementVisibleInfo {
|
public getElementVisibleInfo(element: Element): IElementVisibleInfo {
|
||||||
const rect = element.getBoundingClientRect()
|
const rect = element.getBoundingClientRect()
|
||||||
const viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight)
|
const viewHeight = Math.max(
|
||||||
const visibleHeight = Math.min(rect.bottom, viewHeight) - Math.max(rect.top, 0)
|
document.documentElement.clientHeight,
|
||||||
|
window.innerHeight
|
||||||
|
)
|
||||||
|
const visibleHeight =
|
||||||
|
Math.min(rect.bottom, viewHeight) - Math.max(rect.top, 0)
|
||||||
return {
|
return {
|
||||||
intersectionHeight: visibleHeight > 0 ? visibleHeight : 0
|
intersectionHeight: visibleHeight > 0 ? visibleHeight : 0
|
||||||
}
|
}
|
||||||
@@ -71,5 +74,4 @@ export class ScrollObserver {
|
|||||||
this.draw.setIntersectionPageNo(intersectionPageNo)
|
this.draw.setIntersectionPageNo(intersectionPageNo)
|
||||||
this.draw.setVisiblePageNoList(visiblePageNoList)
|
this.draw.setVisiblePageNoList(visiblePageNoList)
|
||||||
}, 150)
|
}, 150)
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,11 +3,15 @@ import { Draw } from '../draw/Draw'
|
|||||||
import { RangeManager } from '../range/RangeManager'
|
import { RangeManager } from '../range/RangeManager'
|
||||||
|
|
||||||
export class SelectionObserver {
|
export class SelectionObserver {
|
||||||
|
|
||||||
// 每次滚动长度
|
// 每次滚动长度
|
||||||
private readonly step: number = 5
|
private readonly step: number = 5
|
||||||
// 触发滚动阀值
|
// 触发滚动阀值
|
||||||
private readonly thresholdPoints: [top: number, down: number, left: number, right: number] = [70, 40, 10, 20]
|
private readonly thresholdPoints: [
|
||||||
|
top: number,
|
||||||
|
down: number,
|
||||||
|
left: number,
|
||||||
|
right: number
|
||||||
|
] = [70, 40, 10, 20]
|
||||||
|
|
||||||
private rangeManager: RangeManager
|
private rangeManager: RangeManager
|
||||||
private requestAnimationFrameId: number | null
|
private requestAnimationFrameId: number | null
|
||||||
@@ -74,7 +78,9 @@ export class SelectionObserver {
|
|||||||
} else {
|
} else {
|
||||||
window.scrollTo(x + this.step, y)
|
window.scrollTo(x + this.step, y)
|
||||||
}
|
}
|
||||||
this.requestAnimationFrameId = window.requestAnimationFrame(this._move.bind(this, direction))
|
this.requestAnimationFrameId = window.requestAnimationFrame(
|
||||||
|
this._move.bind(this, direction)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private _startMove(direction: MoveDirection) {
|
private _startMove(direction: MoveDirection) {
|
||||||
@@ -90,5 +96,4 @@ export class SelectionObserver {
|
|||||||
this.isMoving = false
|
this.isMoving = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ import Editor from '../..'
|
|||||||
import { PluginFunction } from '../../interface/Plugin'
|
import { PluginFunction } from '../../interface/Plugin'
|
||||||
|
|
||||||
export class Plugin {
|
export class Plugin {
|
||||||
|
|
||||||
private editor: Editor
|
private editor: Editor
|
||||||
|
|
||||||
constructor(editor: Editor) {
|
constructor(editor: Editor) {
|
||||||
this.editor = editor
|
this.editor = editor
|
||||||
}
|
}
|
||||||
|
|
||||||
public use<Options>(pluginFunction: PluginFunction<Options>, options?: Options) {
|
public use<Options>(
|
||||||
|
pluginFunction: PluginFunction<Options>,
|
||||||
|
options?: Options
|
||||||
|
) {
|
||||||
pluginFunction(this.editor, options)
|
pluginFunction(this.editor, options)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
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, ImageDisplay } from '../../dataset/enum/Control'
|
||||||
import { IComputePageRowPositionPayload, IComputePageRowPositionResult } from '../../interface/Position'
|
import {
|
||||||
|
IComputePageRowPositionPayload,
|
||||||
|
IComputePageRowPositionResult
|
||||||
|
} 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'
|
||||||
import { ICurrentPosition, IGetPositionByXYPayload, IPositionContext } from '../../interface/Position'
|
import {
|
||||||
|
ICurrentPosition,
|
||||||
|
IGetPositionByXYPayload,
|
||||||
|
IPositionContext
|
||||||
|
} from '../../interface/Position'
|
||||||
import { Draw } from '../draw/Draw'
|
import { Draw } from '../draw/Draw'
|
||||||
import { EditorZone } from '../../dataset/enum/Editor'
|
import { EditorZone } from '../../dataset/enum/Editor'
|
||||||
|
|
||||||
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[]
|
||||||
@@ -29,9 +35,14 @@ export class Position {
|
|||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTablePositionList(sourceElementList: IElement[]): IElementPosition[] {
|
public getTablePositionList(
|
||||||
|
sourceElementList: IElement[]
|
||||||
|
): IElementPosition[] {
|
||||||
const { index, trIndex, tdIndex } = this.positionContext
|
const { index, trIndex, tdIndex } = this.positionContext
|
||||||
return sourceElementList[index!].trList![trIndex!].tdList[tdIndex!].positionList || []
|
return (
|
||||||
|
sourceElementList[index!].trList![trIndex!].tdList[tdIndex!]
|
||||||
|
.positionList || []
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPositionList(): IElementPosition[] {
|
public getPositionList(): IElementPosition[] {
|
||||||
@@ -67,8 +78,19 @@ export class Position {
|
|||||||
this.positionList = payload
|
this.positionList = payload
|
||||||
}
|
}
|
||||||
|
|
||||||
public computePageRowPosition(payload: IComputePageRowPositionPayload): IComputePageRowPositionResult {
|
public computePageRowPosition(
|
||||||
const { positionList, rowList, pageNo, startX, startY, startRowIndex, startIndex, innerWidth } = payload
|
payload: IComputePageRowPositionPayload
|
||||||
|
): IComputePageRowPositionResult {
|
||||||
|
const {
|
||||||
|
positionList,
|
||||||
|
rowList,
|
||||||
|
pageNo,
|
||||||
|
startX,
|
||||||
|
startY,
|
||||||
|
startRowIndex,
|
||||||
|
startIndex,
|
||||||
|
innerWidth
|
||||||
|
} = payload
|
||||||
const { scale, tdPadding } = this.options
|
const { scale, tdPadding } = this.options
|
||||||
let x = startX
|
let x = startX
|
||||||
let y = startY
|
let y = startY
|
||||||
@@ -92,8 +114,9 @@ export class Position {
|
|||||||
const element = curRow.elementList[j]
|
const element = curRow.elementList[j]
|
||||||
const metrics = element.metrics
|
const metrics = element.metrics
|
||||||
const offsetY =
|
const offsetY =
|
||||||
(element.imgDisplay !== ImageDisplay.INLINE && element.type === ElementType.IMAGE)
|
(element.imgDisplay !== ImageDisplay.INLINE &&
|
||||||
|| element.type === ElementType.LATEX
|
element.type === ElementType.IMAGE) ||
|
||||||
|
element.type === ElementType.LATEX
|
||||||
? curRow.ascent - metrics.height
|
? curRow.ascent - metrics.height
|
||||||
: curRow.ascent
|
: curRow.ascent
|
||||||
const positionItem: IElementPosition = {
|
const positionItem: IElementPosition = {
|
||||||
@@ -137,15 +160,23 @@ export class Position {
|
|||||||
})
|
})
|
||||||
// 垂直对齐方式
|
// 垂直对齐方式
|
||||||
if (
|
if (
|
||||||
td.verticalAlign === VerticalAlign.MIDDLE
|
td.verticalAlign === VerticalAlign.MIDDLE ||
|
||||||
|| td.verticalAlign === VerticalAlign.BOTTOM
|
td.verticalAlign === VerticalAlign.BOTTOM
|
||||||
) {
|
) {
|
||||||
const rowsHeight = rowList.reduce((pre, cur) => pre + cur.height, 0)
|
const rowsHeight = rowList.reduce(
|
||||||
|
(pre, cur) => pre + cur.height,
|
||||||
|
0
|
||||||
|
)
|
||||||
const blankHeight = (td.height! - tdGap) * scale - rowsHeight
|
const blankHeight = (td.height! - tdGap) * scale - rowsHeight
|
||||||
const offsetHeight = td.verticalAlign === VerticalAlign.MIDDLE ? blankHeight / 2 : blankHeight
|
const offsetHeight =
|
||||||
|
td.verticalAlign === VerticalAlign.MIDDLE
|
||||||
|
? blankHeight / 2
|
||||||
|
: blankHeight
|
||||||
if (Math.floor(offsetHeight) > 0) {
|
if (Math.floor(offsetHeight) > 0) {
|
||||||
td.positionList.forEach(tdPosition => {
|
td.positionList.forEach(tdPosition => {
|
||||||
const { coordinate: { leftTop, leftBottom, rightBottom, rightTop } } = tdPosition
|
const {
|
||||||
|
coordinate: { leftTop, leftBottom, rightBottom, rightTop }
|
||||||
|
} = tdPosition
|
||||||
leftTop[1] += offsetHeight
|
leftTop[1] += offsetHeight
|
||||||
leftBottom[1] += offsetHeight
|
leftBottom[1] += offsetHeight
|
||||||
rightBottom[1] += offsetHeight
|
rightBottom[1] += offsetHeight
|
||||||
@@ -228,10 +259,19 @@ export class Position {
|
|||||||
const isMainActive = zoneManager.isMainActive()
|
const isMainActive = zoneManager.isMainActive()
|
||||||
const positionNo = isMainActive ? curPageNo : 0
|
const positionNo = isMainActive ? curPageNo : 0
|
||||||
for (let j = 0; j < positionList.length; j++) {
|
for (let j = 0; j < positionList.length; j++) {
|
||||||
const { index, pageNo, coordinate: { leftTop, rightTop, leftBottom } } = positionList[j]
|
const {
|
||||||
|
index,
|
||||||
|
pageNo,
|
||||||
|
coordinate: { leftTop, rightTop, leftBottom }
|
||||||
|
} = positionList[j]
|
||||||
if (positionNo !== pageNo) continue
|
if (positionNo !== pageNo) continue
|
||||||
// 命中元素
|
// 命中元素
|
||||||
if (leftTop[0] <= x && rightTop[0] >= x && leftTop[1] <= y && leftBottom[1] >= y) {
|
if (
|
||||||
|
leftTop[0] <= x &&
|
||||||
|
rightTop[0] >= x &&
|
||||||
|
leftTop[1] <= y &&
|
||||||
|
leftBottom[1] >= y
|
||||||
|
) {
|
||||||
let curPositionIndex = j
|
let curPositionIndex = j
|
||||||
const element = elementList[j]
|
const element = elementList[j]
|
||||||
// 表格被命中
|
// 表格被命中
|
||||||
@@ -254,8 +294,10 @@ export class Position {
|
|||||||
const tdValueElement = td.value[tdValueIndex]
|
const tdValueElement = td.value[tdValueIndex]
|
||||||
return {
|
return {
|
||||||
index,
|
index,
|
||||||
isCheckbox: tdValueElement.type === ElementType.CHECKBOX ||
|
isCheckbox:
|
||||||
tdValueElement.controlComponent === ControlComponent.CHECKBOX,
|
tdValueElement.type === ElementType.CHECKBOX ||
|
||||||
|
tdValueElement.controlComponent ===
|
||||||
|
ControlComponent.CHECKBOX,
|
||||||
isControl: tdValueElement.type === ElementType.CONTROL,
|
isControl: tdValueElement.type === ElementType.CONTROL,
|
||||||
isImage: tablePosition.isImage,
|
isImage: tablePosition.isImage,
|
||||||
isDirectHit: tablePosition.isDirectHit,
|
isDirectHit: tablePosition.isDirectHit,
|
||||||
@@ -272,7 +314,10 @@ export class Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 图片区域均为命中
|
// 图片区域均为命中
|
||||||
if (element.type === ElementType.IMAGE || element.type === ElementType.LATEX) {
|
if (
|
||||||
|
element.type === ElementType.IMAGE ||
|
||||||
|
element.type === ElementType.LATEX
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
index: curPositionIndex,
|
index: curPositionIndex,
|
||||||
isDirectHit: true,
|
isDirectHit: true,
|
||||||
@@ -298,7 +343,7 @@ export class Position {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
index: curPositionIndex,
|
index: curPositionIndex,
|
||||||
isControl: element.type === ElementType.CONTROL,
|
isControl: element.type === ElementType.CONTROL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -323,18 +368,28 @@ export class Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 判断所属行是否存在元素
|
// 判断所属行是否存在元素
|
||||||
const lastLetterList = positionList.filter(p => p.isLastLetter && p.pageNo === positionNo)
|
const lastLetterList = positionList.filter(
|
||||||
|
p => p.isLastLetter && p.pageNo === positionNo
|
||||||
|
)
|
||||||
for (let j = 0; j < lastLetterList.length; j++) {
|
for (let j = 0; j < lastLetterList.length; j++) {
|
||||||
const { index, pageNo, coordinate: { leftTop, leftBottom } } = lastLetterList[j]
|
const {
|
||||||
|
index,
|
||||||
|
pageNo,
|
||||||
|
coordinate: { leftTop, leftBottom }
|
||||||
|
} = lastLetterList[j]
|
||||||
if (positionNo !== pageNo) continue
|
if (positionNo !== pageNo) continue
|
||||||
if (y > leftTop[1] && y <= leftBottom[1]) {
|
if (y > leftTop[1] && y <= leftBottom[1]) {
|
||||||
const isHead = x < this.options.margins[3]
|
const isHead = x < this.options.margins[3]
|
||||||
// 是否在头部
|
// 是否在头部
|
||||||
if (isHead) {
|
if (isHead) {
|
||||||
const headIndex = positionList.findIndex(p => p.pageNo === positionNo && p.rowNo === lastLetterList[j].rowNo)
|
const headIndex = positionList.findIndex(
|
||||||
|
p => p.pageNo === positionNo && p.rowNo === lastLetterList[j].rowNo
|
||||||
|
)
|
||||||
// 头部元素为空元素时无需选中
|
// 头部元素为空元素时无需选中
|
||||||
curPositionIndex = ~headIndex
|
curPositionIndex = ~headIndex
|
||||||
? positionList[headIndex].value === ZERO ? headIndex : headIndex - 1
|
? positionList[headIndex].value === ZERO
|
||||||
|
? headIndex
|
||||||
|
: headIndex - 1
|
||||||
: index
|
: index
|
||||||
} else {
|
} else {
|
||||||
curPositionIndex = index
|
curPositionIndex = index
|
||||||
@@ -350,7 +405,8 @@ export class Position {
|
|||||||
// 页脚上部距离页面顶部距离
|
// 页脚上部距离页面顶部距离
|
||||||
const footer = this.draw.getFooter()
|
const footer = this.draw.getFooter()
|
||||||
const pageHeight = this.draw.getHeight()
|
const pageHeight = this.draw.getHeight()
|
||||||
const footerTopY = pageHeight - (footer.getFooterBottom() + footer.getHeight())
|
const footerTopY =
|
||||||
|
pageHeight - (footer.getFooterBottom() + footer.getHeight())
|
||||||
// 判断所属位置是否属于页眉页脚区域
|
// 判断所属位置是否属于页眉页脚区域
|
||||||
if (isMainActive) {
|
if (isMainActive) {
|
||||||
// 页眉:当前位置小于页眉底部位置
|
// 页眉:当前位置小于页眉底部位置
|
||||||
@@ -378,7 +434,9 @@ export class Position {
|
|||||||
}
|
}
|
||||||
// 当前页最后一行
|
// 当前页最后一行
|
||||||
return {
|
return {
|
||||||
index: lastLetterList[lastLetterList.length - 1]?.index || positionList.length - 1,
|
index:
|
||||||
|
lastLetterList[lastLetterList.length - 1]?.index ||
|
||||||
|
positionList.length - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -387,19 +445,15 @@ export class Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public adjustPositionContext(payload: IGetPositionByXYPayload): ICurrentPosition | null {
|
public adjustPositionContext(
|
||||||
|
payload: IGetPositionByXYPayload
|
||||||
|
): ICurrentPosition | null {
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
const positionResult = this.getPositionByXY(payload)
|
const positionResult = this.getPositionByXY(payload)
|
||||||
if (!~positionResult.index) return null
|
if (!~positionResult.index) return null
|
||||||
// 移动控件内光标
|
// 移动控件内光标
|
||||||
if (positionResult.isControl && !isReadonly) {
|
if (positionResult.isControl && !isReadonly) {
|
||||||
const {
|
const { index, isTable, trIndex, tdIndex, tdValueIndex } = positionResult
|
||||||
index,
|
|
||||||
isTable,
|
|
||||||
trIndex,
|
|
||||||
tdIndex,
|
|
||||||
tdValueIndex
|
|
||||||
} = positionResult
|
|
||||||
const control = this.draw.getControl()
|
const control = this.draw.getControl()
|
||||||
const { newIndex } = control.moveCursor({
|
const { newIndex } = control.moveCursor({
|
||||||
index,
|
index,
|
||||||
@@ -439,5 +493,4 @@ export class Position {
|
|||||||
})
|
})
|
||||||
return positionResult
|
return positionResult
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { Listener } from '../listener/Listener'
|
|||||||
import { Position } from '../position/Position'
|
import { Position } from '../position/Position'
|
||||||
|
|
||||||
export class RangeManager {
|
export class RangeManager {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
private range: IRange
|
private range: IRange
|
||||||
@@ -55,7 +54,9 @@ export class RangeManager {
|
|||||||
public getTextLikeSelection(): IElement[] | null {
|
public getTextLikeSelection(): IElement[] | null {
|
||||||
const selection = this.getSelection()
|
const selection = this.getSelection()
|
||||||
if (!selection) return null
|
if (!selection) return null
|
||||||
return selection.filter(s => !s.type || TEXTLIKE_ELEMENT_TYPE.includes(s.type))
|
return selection.filter(
|
||||||
|
s => !s.type || TEXTLIKE_ELEMENT_TYPE.includes(s.type)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取光标所选位置行信息
|
// 获取光标所选位置行信息
|
||||||
@@ -100,7 +101,9 @@ export class RangeManager {
|
|||||||
if (
|
if (
|
||||||
positionList[start]?.value === ZERO ||
|
positionList[start]?.value === ZERO ||
|
||||||
elementList[start].titleId !== elementList[start - 1]?.titleId
|
elementList[start].titleId !== elementList[start - 1]?.titleId
|
||||||
) break
|
) {
|
||||||
|
break
|
||||||
|
}
|
||||||
start--
|
start--
|
||||||
}
|
}
|
||||||
// 中间选择
|
// 中间选择
|
||||||
@@ -125,7 +128,9 @@ export class RangeManager {
|
|||||||
if (
|
if (
|
||||||
positionList[end].value === ZERO ||
|
positionList[end].value === ZERO ||
|
||||||
elementList[end].titleId !== elementList[end + 1]?.titleId
|
elementList[end].titleId !== elementList[end + 1]?.titleId
|
||||||
) break
|
) {
|
||||||
|
break
|
||||||
|
}
|
||||||
const { pageNo, rowNo } = positionList[end]
|
const { pageNo, rowNo } = positionList[end]
|
||||||
let rowArray = rangeRow.get(pageNo)
|
let rowArray = rangeRow.get(pageNo)
|
||||||
if (!rowArray) {
|
if (!rowArray) {
|
||||||
@@ -172,8 +177,15 @@ export class RangeManager {
|
|||||||
const { startIndex, endIndex } = this.range
|
const { startIndex, endIndex } = this.range
|
||||||
const positionList = this.position.getPositionList()
|
const positionList = this.position.getPositionList()
|
||||||
for (let p = startIndex + 1; p <= endIndex; p++) {
|
for (let p = startIndex + 1; p <= endIndex; p++) {
|
||||||
const { coordinate: { leftTop, rightBottom } } = positionList[p]
|
const {
|
||||||
if (x >= leftTop[0] && x <= rightBottom[0] && y >= leftTop[1] && y <= rightBottom[1]) {
|
coordinate: { leftTop, rightBottom }
|
||||||
|
} = positionList[p]
|
||||||
|
if (
|
||||||
|
x >= leftTop[0] &&
|
||||||
|
x <= rightBottom[0] &&
|
||||||
|
y >= leftTop[1] &&
|
||||||
|
y <= rightBottom[1]
|
||||||
|
) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,7 +208,12 @@ export class RangeManager {
|
|||||||
this.range.endTdIndex = endTdIndex
|
this.range.endTdIndex = endTdIndex
|
||||||
this.range.startTrIndex = startTrIndex
|
this.range.startTrIndex = startTrIndex
|
||||||
this.range.endTrIndex = endTrIndex
|
this.range.endTrIndex = endTrIndex
|
||||||
this.range.isCrossRowCol = !!(startTdIndex || endTdIndex || startTrIndex || endTrIndex)
|
this.range.isCrossRowCol = !!(
|
||||||
|
startTdIndex ||
|
||||||
|
endTdIndex ||
|
||||||
|
startTrIndex ||
|
||||||
|
endTrIndex
|
||||||
|
)
|
||||||
this.range.zone = this.draw.getZone().getZone()
|
this.range.zone = this.draw.getZone().getZone()
|
||||||
// 激活控件
|
// 激活控件
|
||||||
const control = this.draw.getControl()
|
const control = this.draw.getControl()
|
||||||
@@ -349,8 +366,8 @@ export class RangeManager {
|
|||||||
while (index > 0) {
|
while (index > 0) {
|
||||||
const preElement = elementList[index]
|
const preElement = elementList[index]
|
||||||
if (
|
if (
|
||||||
preElement.controlId !== endElement.controlId
|
preElement.controlId !== endElement.controlId ||
|
||||||
|| preElement.controlComponent === ControlComponent.PREFIX
|
preElement.controlComponent === ControlComponent.PREFIX
|
||||||
) {
|
) {
|
||||||
range.startIndex = index
|
range.startIndex = index
|
||||||
range.endIndex = index
|
range.endIndex = index
|
||||||
@@ -365,12 +382,14 @@ export class RangeManager {
|
|||||||
while (index < elementList.length) {
|
while (index < elementList.length) {
|
||||||
const nextElement = elementList[index]
|
const nextElement = elementList[index]
|
||||||
if (
|
if (
|
||||||
nextElement.controlId !== startElement.controlId
|
nextElement.controlId !== startElement.controlId ||
|
||||||
|| nextElement.controlComponent === ControlComponent.VALUE
|
nextElement.controlComponent === ControlComponent.VALUE
|
||||||
) {
|
) {
|
||||||
range.startIndex = index - 1
|
range.startIndex = index - 1
|
||||||
break
|
break
|
||||||
} else if (nextElement.controlComponent === ControlComponent.PLACEHOLDER) {
|
} else if (
|
||||||
|
nextElement.controlComponent === ControlComponent.PLACEHOLDER
|
||||||
|
) {
|
||||||
range.startIndex = index - 1
|
range.startIndex = index - 1
|
||||||
range.endIndex = index - 1
|
range.endIndex = index - 1
|
||||||
return
|
return
|
||||||
@@ -384,12 +403,14 @@ export class RangeManager {
|
|||||||
while (index > 0) {
|
while (index > 0) {
|
||||||
const preElement = elementList[index]
|
const preElement = elementList[index]
|
||||||
if (
|
if (
|
||||||
preElement.controlId !== startElement.controlId
|
preElement.controlId !== startElement.controlId ||
|
||||||
|| preElement.controlComponent === ControlComponent.VALUE
|
preElement.controlComponent === ControlComponent.VALUE
|
||||||
) {
|
) {
|
||||||
range.startIndex = index
|
range.startIndex = index
|
||||||
break
|
break
|
||||||
} else if (preElement.controlComponent === ControlComponent.PLACEHOLDER) {
|
} else if (
|
||||||
|
preElement.controlComponent === ControlComponent.PLACEHOLDER
|
||||||
|
) {
|
||||||
range.startIndex = index
|
range.startIndex = index
|
||||||
range.endIndex = index
|
range.endIndex = index
|
||||||
return
|
return
|
||||||
@@ -400,7 +421,13 @@ export class RangeManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) {
|
public render(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
) {
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.globalAlpha = this.options.rangeAlpha
|
ctx.globalAlpha = this.options.rangeAlpha
|
||||||
ctx.fillStyle = this.options.rangeColor
|
ctx.fillStyle = this.options.rangeColor
|
||||||
@@ -411,9 +438,9 @@ export class RangeManager {
|
|||||||
public toString(): string {
|
public toString(): string {
|
||||||
const selection = this.getSelection()
|
const selection = this.getSelection()
|
||||||
if (!selection) return ''
|
if (!selection) return ''
|
||||||
return selection.map(s => s.value)
|
return selection
|
||||||
|
.map(s => s.value)
|
||||||
.join('')
|
.join('')
|
||||||
.replace(new RegExp(ZERO, 'g'), '')
|
.replace(new RegExp(ZERO, 'g'), '')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,13 +7,12 @@ import { ILang } from '../../interface/i18n/I18n'
|
|||||||
import { DeepPartial } from '../../interface/Common'
|
import { DeepPartial } from '../../interface/Common'
|
||||||
|
|
||||||
interface IRegisterPayload {
|
interface IRegisterPayload {
|
||||||
contextMenu: ContextMenu;
|
contextMenu: ContextMenu
|
||||||
shortcut: Shortcut;
|
shortcut: Shortcut
|
||||||
i18n: I18n;
|
i18n: I18n
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Register {
|
export class Register {
|
||||||
|
|
||||||
public contextMenuList: (payload: IRegisterContextMenu[]) => void
|
public contextMenuList: (payload: IRegisterContextMenu[]) => void
|
||||||
public shortcutList: (payload: IRegisterShortcut[]) => void
|
public shortcutList: (payload: IRegisterShortcut[]) => void
|
||||||
public langMap: (locale: string, lang: DeepPartial<ILang>) => void
|
public langMap: (locale: string, lang: DeepPartial<ILang>) => void
|
||||||
@@ -24,5 +23,4 @@ export class Register {
|
|||||||
this.shortcutList = shortcut.registerShortcutList.bind(shortcut)
|
this.shortcutList = shortcut.registerShortcutList.bind(shortcut)
|
||||||
this.langMap = i18n.registerLangMap.bind(i18n)
|
this.langMap = i18n.registerLangMap.bind(i18n)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { titleKeys } from './keys/titleKeys'
|
|||||||
import { listKeys } from './keys/listKeys'
|
import { listKeys } from './keys/listKeys'
|
||||||
|
|
||||||
export class Shortcut {
|
export class Shortcut {
|
||||||
|
|
||||||
private command: Command
|
private command: Command
|
||||||
private globalShortcutList: IRegisterShortcut[]
|
private globalShortcutList: IRegisterShortcut[]
|
||||||
private agentShortcutList: IRegisterShortcut[]
|
private agentShortcutList: IRegisterShortcut[]
|
||||||
@@ -17,11 +16,7 @@ export class Shortcut {
|
|||||||
this.globalShortcutList = []
|
this.globalShortcutList = []
|
||||||
this.agentShortcutList = []
|
this.agentShortcutList = []
|
||||||
// 内部快捷键
|
// 内部快捷键
|
||||||
this._addShortcutList([
|
this._addShortcutList([...richtextKeys, ...titleKeys, ...listKeys])
|
||||||
...richtextKeys,
|
|
||||||
...titleKeys,
|
|
||||||
...listKeys
|
|
||||||
])
|
|
||||||
// 全局快捷键
|
// 全局快捷键
|
||||||
this._addEvent()
|
this._addEvent()
|
||||||
// 编辑器快捷键
|
// 编辑器快捷键
|
||||||
@@ -66,11 +61,10 @@ export class Shortcut {
|
|||||||
for (let s = 0; s < shortCutList.length; s++) {
|
for (let s = 0; s < shortCutList.length; s++) {
|
||||||
const shortCut = shortCutList[s]
|
const shortCut = shortCutList[s]
|
||||||
if (
|
if (
|
||||||
(
|
(shortCut.mod
|
||||||
shortCut.mod
|
? isMod(evt) === !!shortCut.mod
|
||||||
? isMod(evt) === !!shortCut.mod
|
: evt.ctrlKey === !!shortCut.ctrl &&
|
||||||
: evt.ctrlKey === !!shortCut.ctrl && evt.metaKey === !!shortCut.meta
|
evt.metaKey === !!shortCut.meta) &&
|
||||||
) &&
|
|
||||||
evt.shiftKey === !!shortCut.shift &&
|
evt.shiftKey === !!shortCut.shift &&
|
||||||
evt.altKey === !!shortCut.alt &&
|
evt.altKey === !!shortCut.alt &&
|
||||||
evt.key === shortCut.key
|
evt.key === shortCut.key
|
||||||
@@ -81,5 +75,4 @@ export class Shortcut {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,4 +19,4 @@ export const listKeys: IRegisterShortcut[] = [
|
|||||||
command.executeList(ListType.OL)
|
command.executeList(ListType.OL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -91,4 +91,4 @@ export const richtextKeys: IRegisterShortcut[] = [
|
|||||||
command.executeRowFlex(RowFlex.ALIGNMENT)
|
command.executeRowFlex(RowFlex.ALIGNMENT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -10,42 +10,48 @@ export const titleKeys: IRegisterShortcut[] = [
|
|||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
command.executeTitle(null)
|
command.executeTitle(null)
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
key: KeyMap.ONE,
|
key: KeyMap.ONE,
|
||||||
alt: true,
|
alt: true,
|
||||||
ctrl: true,
|
ctrl: true,
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
command.executeTitle(TitleLevel.FIRST)
|
command.executeTitle(TitleLevel.FIRST)
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
key: KeyMap.TWO,
|
key: KeyMap.TWO,
|
||||||
alt: true,
|
alt: true,
|
||||||
ctrl: true,
|
ctrl: true,
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
command.executeTitle(TitleLevel.SECOND)
|
command.executeTitle(TitleLevel.SECOND)
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
key: KeyMap.THREE,
|
key: KeyMap.THREE,
|
||||||
alt: true,
|
alt: true,
|
||||||
ctrl: true,
|
ctrl: true,
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
command.executeTitle(TitleLevel.THIRD)
|
command.executeTitle(TitleLevel.THIRD)
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
key: KeyMap.FOUR,
|
key: KeyMap.FOUR,
|
||||||
alt: true,
|
alt: true,
|
||||||
ctrl: true,
|
ctrl: true,
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
command.executeTitle(TitleLevel.FOURTH)
|
command.executeTitle(TitleLevel.FOURTH)
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
key: KeyMap.FIVE,
|
key: KeyMap.FIVE,
|
||||||
alt: true,
|
alt: true,
|
||||||
ctrl: true,
|
ctrl: true,
|
||||||
callback: (command: Command) => {
|
callback: (command: Command) => {
|
||||||
command.executeTitle(TitleLevel.FIFTH)
|
command.executeTitle(TitleLevel.FIFTH)
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
key: KeyMap.SIX,
|
key: KeyMap.SIX,
|
||||||
alt: true,
|
alt: true,
|
||||||
ctrl: true,
|
ctrl: true,
|
||||||
@@ -53,4 +59,4 @@ export const titleKeys: IRegisterShortcut[] = [
|
|||||||
command.executeTitle(TitleLevel.SIXTH)
|
command.executeTitle(TitleLevel.SIXTH)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -3,9 +3,7 @@ import WordCountWorker from './works/wordCount?worker&inline'
|
|||||||
import CatalogWorker from './works/catalog?worker&inline'
|
import CatalogWorker from './works/catalog?worker&inline'
|
||||||
import { ICatalog } from '../../interface/Catalog'
|
import { ICatalog } from '../../interface/Catalog'
|
||||||
|
|
||||||
|
|
||||||
export class WorkerManager {
|
export class WorkerManager {
|
||||||
|
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private wordCountWorker: Worker
|
private wordCountWorker: Worker
|
||||||
private catalogWorker: Worker
|
private catalogWorker: Worker
|
||||||
@@ -18,11 +16,11 @@ export class WorkerManager {
|
|||||||
|
|
||||||
public getWordCount(): Promise<number> {
|
public getWordCount(): Promise<number> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.wordCountWorker.onmessage = (evt) => {
|
this.wordCountWorker.onmessage = evt => {
|
||||||
resolve(evt.data)
|
resolve(evt.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.wordCountWorker.onerror = (evt) => {
|
this.wordCountWorker.onerror = evt => {
|
||||||
reject(evt)
|
reject(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,11 +31,11 @@ export class WorkerManager {
|
|||||||
|
|
||||||
public getCatalog(): Promise<ICatalog | null> {
|
public getCatalog(): Promise<ICatalog | null> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.catalogWorker.onmessage = (evt) => {
|
this.catalogWorker.onmessage = evt => {
|
||||||
resolve(evt.data)
|
resolve(evt.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.catalogWorker.onerror = (evt) => {
|
this.catalogWorker.onerror = evt => {
|
||||||
reject(evt)
|
reject(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,5 +43,4 @@ export class WorkerManager {
|
|||||||
this.catalogWorker.postMessage(elementList)
|
this.catalogWorker.postMessage(elementList)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ function getCatalog(elementList: IElement[]): ICatalog | null {
|
|||||||
valueList.push(titleE)
|
valueList.push(titleE)
|
||||||
t++
|
t++
|
||||||
}
|
}
|
||||||
titleElement.value = valueList.map(s => s.value)
|
titleElement.value = valueList
|
||||||
|
.map(s => s.value)
|
||||||
.join('')
|
.join('')
|
||||||
.replace(new RegExp(ZERO, 'g'), '')
|
.replace(new RegExp(ZERO, 'g'), '')
|
||||||
titleElementList.push(titleElement)
|
titleElementList.push(titleElement)
|
||||||
@@ -60,7 +61,8 @@ function getCatalog(elementList: IElement[]): ICatalog | null {
|
|||||||
if (!titleElementList.length) return null
|
if (!titleElementList.length) return null
|
||||||
// 查找到比最新元素大的标题时终止
|
// 查找到比最新元素大的标题时终止
|
||||||
const recursiveInsert = (title: IElement, catalogItem: ICatalogItem) => {
|
const recursiveInsert = (title: IElement, catalogItem: ICatalogItem) => {
|
||||||
const subCatalogItem = catalogItem.subCatalog[catalogItem.subCatalog.length - 1]
|
const subCatalogItem =
|
||||||
|
catalogItem.subCatalog[catalogItem.subCatalog.length - 1]
|
||||||
const catalogItemLevel = titleOrderNumberMapping[subCatalogItem?.level]
|
const catalogItemLevel = titleOrderNumberMapping[subCatalogItem?.level]
|
||||||
const titleLevel = titleOrderNumberMapping[title.level!]
|
const titleLevel = titleOrderNumberMapping[title.level!]
|
||||||
if (subCatalogItem && titleLevel > catalogItemLevel) {
|
if (subCatalogItem && titleLevel > catalogItemLevel) {
|
||||||
@@ -97,7 +99,7 @@ function getCatalog(elementList: IElement[]): ICatalog | null {
|
|||||||
return catalog
|
return catalog
|
||||||
}
|
}
|
||||||
|
|
||||||
onmessage = (evt) => {
|
onmessage = evt => {
|
||||||
const elementList = <IElement[]>evt.data
|
const elementList = <IElement[]>evt.data
|
||||||
const catalog = getCatalog(elementList)
|
const catalog = getCatalog(elementList)
|
||||||
postMessage(catalog)
|
postMessage(catalog)
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ function groupText(text: string): string[] {
|
|||||||
return characterList
|
return characterList
|
||||||
}
|
}
|
||||||
|
|
||||||
onmessage = (evt) => {
|
onmessage = evt => {
|
||||||
const elementList = <IElement[]>evt.data
|
const elementList = <IElement[]>evt.data
|
||||||
// 提取文本
|
// 提取文本
|
||||||
const originText = pickText(elementList)
|
const originText = pickText(elementList)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { Draw } from '../draw/Draw'
|
|||||||
import { I18n } from '../i18n/I18n'
|
import { I18n } from '../i18n/I18n'
|
||||||
|
|
||||||
export class Zone {
|
export class Zone {
|
||||||
|
|
||||||
private readonly INDICATOR_PADDING = 2
|
private readonly INDICATOR_PADDING = 2
|
||||||
private readonly INDICATOR_TITLE_TRANSLATE = [20, 5]
|
private readonly INDICATOR_TITLE_TRANSLATE = [20, 5]
|
||||||
|
|
||||||
@@ -99,9 +98,13 @@ export class Zone {
|
|||||||
: startY - this.INDICATOR_PADDING
|
: startY - this.INDICATOR_PADDING
|
||||||
// 标题
|
// 标题
|
||||||
const indicatorTitle = document.createElement('div')
|
const indicatorTitle = document.createElement('div')
|
||||||
indicatorTitle.innerText = this.i18n.t(`frame.${isHeaderActive ? 'header' : 'footer'}`)
|
indicatorTitle.innerText = this.i18n.t(
|
||||||
|
`frame.${isHeaderActive ? 'header' : 'footer'}`
|
||||||
|
)
|
||||||
indicatorTitle.style.top = `${indicatorBottomY}px`
|
indicatorTitle.style.top = `${indicatorBottomY}px`
|
||||||
indicatorTitle.style.transform = `translate(${offsetX * scale}px, ${offsetY * scale}px) scale(${scale})`
|
indicatorTitle.style.transform = `translate(${offsetX * scale}px, ${
|
||||||
|
offsetY * scale
|
||||||
|
}px) scale(${scale})`
|
||||||
this.indicatorContainer.append(indicatorTitle)
|
this.indicatorContainer.append(indicatorTitle)
|
||||||
|
|
||||||
// 上边线
|
// 上边线
|
||||||
@@ -141,5 +144,4 @@ export class Zone {
|
|||||||
this.indicatorContainer?.remove()
|
this.indicatorContainer?.remove()
|
||||||
this.indicatorContainer = null
|
this.indicatorContainer = null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,4 +7,4 @@ export const defaultCheckboxOption: Readonly<Required<ICheckboxOption>> = {
|
|||||||
lineWidth: 1,
|
lineWidth: 1,
|
||||||
fillStyle: '#5175f4',
|
fillStyle: '#5175f4',
|
||||||
fontStyle: '#ffffff'
|
fontStyle: '#ffffff'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,25 @@ export const ZERO = '\u200B'
|
|||||||
export const WRAP = '\n'
|
export const WRAP = '\n'
|
||||||
export const HORIZON_TAB = '\t'
|
export const HORIZON_TAB = '\t'
|
||||||
export const NBSP = '\u0020'
|
export const NBSP = '\u0020'
|
||||||
export const PUNCTUATION_LIST = ['·', '、', ':', ':', ',', ',', '.', '。', ';', ';', '?', '?', '!', '!']
|
export const PUNCTUATION_LIST = [
|
||||||
|
'·',
|
||||||
|
'、',
|
||||||
|
':',
|
||||||
|
':',
|
||||||
|
',',
|
||||||
|
',',
|
||||||
|
'.',
|
||||||
|
'。',
|
||||||
|
';',
|
||||||
|
';',
|
||||||
|
'?',
|
||||||
|
'?',
|
||||||
|
'!',
|
||||||
|
'!'
|
||||||
|
]
|
||||||
|
|
||||||
export const maxHeightRadioMapping: Record<MaxHeightRatio, number> = {
|
export const maxHeightRadioMapping: Record<MaxHeightRatio, number> = {
|
||||||
[MaxHeightRatio.HALF]: 1 / 2,
|
[MaxHeightRatio.HALF]: 1 / 2,
|
||||||
[MaxHeightRatio.ONE_THIRD]: 1 / 3,
|
[MaxHeightRatio.ONE_THIRD]: 1 / 3,
|
||||||
[MaxHeightRatio.QUARTER]: 1 / 4
|
[MaxHeightRatio.QUARTER]: 1 / 4
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export const NAME_PLACEHOLDER = {
|
export const NAME_PLACEHOLDER = {
|
||||||
SELECTED_TEXT: '%s'
|
SELECTED_TEXT: '%s'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ export const defaultControlOption: Readonly<Required<IControlOption>> = {
|
|||||||
bracketColor: '#000000',
|
bracketColor: '#000000',
|
||||||
prefix: '{',
|
prefix: '{',
|
||||||
postfix: '}'
|
postfix: '}'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,4 +7,4 @@ export const defaultCursorOption: Readonly<Required<ICursorOption>> = {
|
|||||||
color: '#000000',
|
color: '#000000',
|
||||||
dragWidth: 2,
|
dragWidth: 2,
|
||||||
dragColor: '#0000FF'
|
dragColor: '#0000FF'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export const EDITOR_COMPONENT = 'editor-component'
|
export const EDITOR_COMPONENT = 'editor-component'
|
||||||
export const EDITOR_PREFIX = 'ce'
|
export const EDITOR_PREFIX = 'ce'
|
||||||
|
|||||||
@@ -65,10 +65,7 @@ export const TABLE_CONTEXT_ATTR: Array<keyof IElement> = [
|
|||||||
'tableId'
|
'tableId'
|
||||||
]
|
]
|
||||||
|
|
||||||
export const TITLE_CONTEXT_ATTR: Array<keyof IElement> = [
|
export const TITLE_CONTEXT_ATTR: Array<keyof IElement> = ['level', 'titleId']
|
||||||
'level',
|
|
||||||
'titleId',
|
|
||||||
]
|
|
||||||
|
|
||||||
export const LIST_CONTEXT_ATTR: Array<keyof IElement> = [
|
export const LIST_CONTEXT_ATTR: Array<keyof IElement> = [
|
||||||
'listId',
|
'listId',
|
||||||
@@ -98,14 +95,9 @@ export const INLINE_ELEMENT_TYPE: ElementType[] = [
|
|||||||
ElementType.TABLE
|
ElementType.TABLE
|
||||||
]
|
]
|
||||||
|
|
||||||
export const INLINE_NODE_NAME: string[] = [
|
export const INLINE_NODE_NAME: string[] = ['HR', 'TABLE', 'UL', 'OL']
|
||||||
'HR',
|
|
||||||
'TABLE',
|
|
||||||
'UL',
|
|
||||||
'OL'
|
|
||||||
]
|
|
||||||
|
|
||||||
export const VIRTUAL_ELEMENT_TYPE: ElementType[] = [
|
export const VIRTUAL_ELEMENT_TYPE: ElementType[] = [
|
||||||
ElementType.TITLE,
|
ElementType.TITLE,
|
||||||
ElementType.LIST
|
ElementType.LIST
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ export const defaultFooterOption: Readonly<Required<IFooter>> = {
|
|||||||
bottom: 30,
|
bottom: 30,
|
||||||
maxHeightRadio: MaxHeightRatio.HALF,
|
maxHeightRadio: MaxHeightRatio.HALF,
|
||||||
disabled: false
|
disabled: false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ export const defaultHeaderOption: Readonly<Required<IHeader>> = {
|
|||||||
top: 30,
|
top: 30,
|
||||||
maxHeightRadio: MaxHeightRatio.HALF,
|
maxHeightRadio: MaxHeightRatio.HALF,
|
||||||
disabled: false
|
disabled: false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,4 +16,4 @@ export const listStyleCSSMapping: Record<ListStyle, string> = {
|
|||||||
[ListStyle.CIRCLE]: 'circle',
|
[ListStyle.CIRCLE]: 'circle',
|
||||||
[ListStyle.SQUARE]: 'square',
|
[ListStyle.SQUARE]: 'square',
|
||||||
[ListStyle.DECIMAL]: 'decimal'
|
[ListStyle.DECIMAL]: 'decimal'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,4 +18,4 @@ export const defaultPageNumberOption: Readonly<Required<IPageNumber>> = {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
startPageNo: 1,
|
startPageNo: 1,
|
||||||
fromPageNo: 0
|
fromPageNo: 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ export const defaultPlaceholderOption: Readonly<Required<IPlaceholder>> = {
|
|||||||
opacity: 1,
|
opacity: 1,
|
||||||
size: 16,
|
size: 16,
|
||||||
font: 'Yahei'
|
font: 'Yahei'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ export const NUMBER_REG = /[0-9]/
|
|||||||
export const LETTER_REG = /[a-zA-Z]/
|
export const LETTER_REG = /[a-zA-Z]/
|
||||||
export const NUMBER_LIKE_REG = /[0-9.]/
|
export const NUMBER_LIKE_REG = /[0-9.]/
|
||||||
export const CHINESE_REG = /[\u4e00-\u9fa5]/
|
export const CHINESE_REG = /[\u4e00-\u9fa5]/
|
||||||
export const WORD_LIKE_REG = /[^a-zA-Z][a-zA-Z]/
|
export const WORD_LIKE_REG = /[^a-zA-Z][a-zA-Z]/
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ export const titleOrderNumberMapping: Record<TitleLevel, number> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const titleNodeNameMapping: Record<string, TitleLevel> = {
|
export const titleNodeNameMapping: Record<string, TitleLevel> = {
|
||||||
'H1': TitleLevel.FIRST,
|
H1: TitleLevel.FIRST,
|
||||||
'H2': TitleLevel.SECOND,
|
H2: TitleLevel.SECOND,
|
||||||
'H3': TitleLevel.THIRD,
|
H3: TitleLevel.THIRD,
|
||||||
'H4': TitleLevel.FOURTH,
|
H4: TitleLevel.FOURTH,
|
||||||
'H5': TitleLevel.FIFTH,
|
H5: TitleLevel.FIFTH,
|
||||||
'H6': TitleLevel.SIXTH
|
H6: TitleLevel.SIXTH
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ export const defaultWatermarkOption: Readonly<Required<IWatermark>> = {
|
|||||||
opacity: 0.3,
|
opacity: 0.3,
|
||||||
size: 200,
|
size: 200,
|
||||||
font: 'Yahei'
|
font: 'Yahei'
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user