diff --git a/docs/en/guide/command-execute.md b/docs/en/guide/command-execute.md index d0fb8791..55840554 100644 --- a/docs/en/guide/command-execute.md +++ b/docs/en/guide/command-execute.md @@ -772,6 +772,26 @@ Usage: instance.command.executeSetPaperMargin([top: number, right: number, bottom: number, left: number]) ``` +## executeSetMainBadge + +Feature: Set main badge + +Usage: + +```javascript +instance.command.executeSetMainBadge(payload: IBadge | null) +``` + +## executeSetAreaBadge + +Feature: Set area badge + +Usage: + +```javascript +instance.command.executeSetAreaBadge(payload: IAreaBadge[]) +``` + ## executeInsertElementList Feature: Insert an element diff --git a/docs/en/guide/option.md b/docs/en/guide/option.md index f5665cda..5d42cb99 100644 --- a/docs/en/guide/option.md +++ b/docs/en/guide/option.md @@ -73,6 +73,7 @@ interface IEditorOption { separator?: ISeparatorOption // Separator option. {lineWidth?:number; strokeStyle?:string;} lineNumber?: ILineNumberOption // LineNumber option. {size?:number; font?:string; color?:string; disabled?:boolean; right?:number} pageBorder?: IPageBorderOption // PageBorder option. {color?:string; lineWidth:number; padding?:IPadding; disabled?:boolean;} + badge?: IBadgeOption // Badge option. {top?:number; left?:number} } ``` diff --git a/docs/guide/command-execute.md b/docs/guide/command-execute.md index c9db8c40..3474980d 100644 --- a/docs/guide/command-execute.md +++ b/docs/guide/command-execute.md @@ -772,6 +772,26 @@ instance.command.executePaperDirection(paperDirection: PaperDirection) instance.command.executeSetPaperMargin([top: number, right: number, bottom: number, left: number]) ``` +## executeSetMainBadge + +功能:设置正文徽章 + +用法: + +```javascript +instance.command.executeSetMainBadge(payload: IBadge | null) +``` + +## executeSetAreaBadge + +功能:设置区域徽章 + +用法: + +```javascript +instance.command.executeSetAreaBadge(payload: IAreaBadge[]) +``` + ## executeInsertElementList 功能:插入元素 diff --git a/docs/guide/option.md b/docs/guide/option.md index bb106315..b7a02ef2 100644 --- a/docs/guide/option.md +++ b/docs/guide/option.md @@ -73,6 +73,7 @@ interface IEditorOption { separator?: ISeparatorOption // 分隔符配置。{lineWidth?:number; strokeStyle?:string;} lineNumber?: ILineNumberOption // 行号配置。{size?:number; font?:string; color?:string; disabled?:boolean; right?:number} pageBorder?: IPageBorderOption // 页面边框配置。{color?:string; lineWidth:number; padding?:IPadding; disabled?:boolean;} + badge?: IBadgeOption // 徽章配置。{top?:number; left?:number} } ``` diff --git a/src/editor/core/command/Command.ts b/src/editor/core/command/Command.ts index a6579e92..9bc25570 100644 --- a/src/editor/core/command/Command.ts +++ b/src/editor/core/command/Command.ts @@ -76,6 +76,8 @@ export class Command { public executePaperSize: CommandAdapt['paperSize'] public executePaperDirection: CommandAdapt['paperDirection'] public executeSetPaperMargin: CommandAdapt['setPaperMargin'] + public executeSetMainBadge: CommandAdapt['setMainBadge'] + public executeSetAreaBadge: CommandAdapt['setAreaBadge'] public executeInsertElementList: CommandAdapt['insertElementList'] public executeInsertArea: CommandAdapt['insertArea'] public executeSetAreaProperties: CommandAdapt['setAreaProperties'] @@ -209,6 +211,9 @@ export class Command { this.executePaperSize = adapt.paperSize.bind(adapt) this.executePaperDirection = adapt.paperDirection.bind(adapt) this.executeSetPaperMargin = adapt.setPaperMargin.bind(adapt) + // 签章 + this.executeSetMainBadge = adapt.setMainBadge.bind(adapt) + this.executeSetAreaBadge = adapt.setAreaBadge.bind(adapt) // 区域 this.getAreaValue = adapt.getAreaValue.bind(adapt) this.executeInsertArea = adapt.insertArea.bind(adapt) diff --git a/src/editor/core/command/CommandAdapt.ts b/src/editor/core/command/CommandAdapt.ts index f4ebacc4..a3519b77 100644 --- a/src/editor/core/command/CommandAdapt.ts +++ b/src/editor/core/command/CommandAdapt.ts @@ -119,6 +119,7 @@ import { IInsertAreaOption, ISetAreaPropertiesOption } from '../../interface/Area' +import { IAreaBadge, IBadge } from '../../interface/Badge' export class CommandAdapt { private draw: Draw @@ -1724,6 +1725,22 @@ export class CommandAdapt { return this.draw.setPaperMargin(payload) } + public setMainBadge(payload: IBadge | null) { + this.draw.getBadge().setMainBadge(payload) + this.draw.render({ + isCompute: false, + isSubmitHistory: false + }) + } + + public setAreaBadge(payload: IAreaBadge[]) { + this.draw.getBadge().setAreaBadgeMap(payload) + this.draw.render({ + isCompute: false, + isSubmitHistory: false + }) + } + public insertElementList(payload: IElement[]) { if (!payload.length) return const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index 32334486..d188d9cc 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -109,6 +109,7 @@ import { ITd } from '../../interface/table/Td' import { Actuator } from '../actuator/Actuator' import { TableOperate } from './particle/table/TableOperate' import { Area } from './interactive/Area' +import { Badge } from './frame/Badge' export class Draw { private container: HTMLDivElement @@ -133,6 +134,7 @@ export class Draw { private range: RangeManager private margin: Margin private background: Background + private badge: Badge private search: Search private group: Group private area: Area @@ -213,6 +215,7 @@ export class Draw { this.range = new RangeManager(this) this.margin = new Margin(this) this.background = new Background(this) + this.badge = new Badge(this) this.search = new Search(this) this.group = new Group(this) this.area = new Area(this) @@ -575,6 +578,10 @@ export class Draw { return this.area } + public getBadge(): Badge { + return this.badge + } + public getHistoryManager(): HistoryManager { return this.historyManager } @@ -2471,6 +2478,8 @@ export class Draw { if (!pageBorder.disabled) { this.pageBorder.render(ctx) } + // 绘制签章 + this.badge.render(ctx, pageNo) } private _disconnectLazyRender() { diff --git a/src/editor/core/draw/frame/Badge.ts b/src/editor/core/draw/frame/Badge.ts new file mode 100644 index 00000000..24dac8ff --- /dev/null +++ b/src/editor/core/draw/frame/Badge.ts @@ -0,0 +1,88 @@ +import { IAreaBadge, IBadge } from '../../../interface/Badge' +import { DeepRequired } from '../../../interface/Common' +import { IEditorOption } from '../../../interface/Editor' +import { Draw } from '../Draw' + +export class Badge { + private draw: Draw + private options: DeepRequired + private imageCache: Map + private mainBadge: IBadge | null + private areaBadgeMap: Map + + constructor(draw: Draw) { + this.draw = draw + this.options = draw.getOptions() + this.imageCache = new Map() + this.mainBadge = null + this.areaBadgeMap = new Map() + } + + public setMainBadge(payload: IBadge | null) { + this.mainBadge = payload + } + + public setAreaBadgeMap(payload: IAreaBadge[]) { + this.areaBadgeMap.clear() + payload.forEach(areaBadge => { + this.areaBadgeMap.set(areaBadge.areaId, areaBadge.badge) + }) + } + + private _drawImage( + ctx: CanvasRenderingContext2D, + x: number, + y: number, + width: number, + height: number, + value: string + ) { + if (this.imageCache.has(value)) { + const img = this.imageCache.get(value)! + ctx.drawImage(img, x, y, width, height) + } else { + const img = new Image() + img.setAttribute('crossOrigin', 'Anonymous') + img.src = value + img.onload = () => { + this.imageCache.set(value, img) + ctx.drawImage(img, x, y, width, height) + } + } + } + + public render(ctx: CanvasRenderingContext2D, pageNo: number) { + // 文档签章 + if (pageNo === 0 && this.mainBadge) { + const { scale, badge } = this.options + const { left, top, width, height, value } = this.mainBadge + // 默认从页眉下开始 + const headerTop = + this.draw.getMargins()[0] + this.draw.getHeader().getExtraHeight() + const x = (left || badge.left) * scale + const y = (top || badge.top) * scale + headerTop + this._drawImage(ctx, x, y, width * scale, height * scale, value) + } + // 区域签章 + if (this.areaBadgeMap.size) { + const areaInfo = this.draw.getArea().getAreaInfo() + if (areaInfo.size) { + const { scale, badge } = this.options + for (const areaItem of areaInfo) { + // 忽略非本页区域 + const { positionList } = areaItem[1] + const firstPosition = positionList[0] + if (firstPosition.pageNo !== pageNo) continue + // 忽略未设置签章区域 + const badgeItem = this.areaBadgeMap.get(areaItem[0]) + if (!badgeItem) continue + const { left, top, width, height, value } = badgeItem + const x = (left || badge.left) * scale + const y = + (top || badge.top) * scale + firstPosition.coordinate.leftTop[1] + this._drawImage(ctx, x, y, width * scale, height * scale, value) + } + } + } + } +} diff --git a/src/editor/core/draw/interactive/Area.ts b/src/editor/core/draw/interactive/Area.ts index 8b6cbdc2..00993dd6 100644 --- a/src/editor/core/draw/interactive/Area.ts +++ b/src/editor/core/draw/interactive/Area.ts @@ -30,6 +30,10 @@ export class Area { this.position = draw.getPosition() } + public getAreaInfo(): Map { + return this.areaInfoMap + } + public getActiveAreaId(): string | null { if (!this.areaInfoMap.size) return null const { startIndex } = this.range.getRange() diff --git a/src/editor/dataset/constant/Badge.ts b/src/editor/dataset/constant/Badge.ts new file mode 100644 index 00000000..66143631 --- /dev/null +++ b/src/editor/dataset/constant/Badge.ts @@ -0,0 +1,6 @@ +import { IBadgeOption } from '../../interface/Badge' + +export const defaultBadgeOption: Readonly> = { + top: 0, + left: 5 +} diff --git a/src/editor/index.ts b/src/editor/index.ts index bb3db246..1236ff1a 100644 --- a/src/editor/index.ts +++ b/src/editor/index.ts @@ -64,6 +64,7 @@ import { TextDecorationStyle } from './dataset/enum/Text' import { mergeOption } from './utils/option' import { LineNumberType } from './dataset/enum/LineNumber' import { AreaMode } from './dataset/enum/Area' +import { IBadge } from './interface/Badge' export default class Editor { public command: Command @@ -215,5 +216,6 @@ export type { ICatalogItem, IRange, IRangeStyle, + IBadge, IGetElementListByHTMLOption } diff --git a/src/editor/interface/Badge.ts b/src/editor/interface/Badge.ts new file mode 100644 index 00000000..3c9d116f --- /dev/null +++ b/src/editor/interface/Badge.ts @@ -0,0 +1,17 @@ +export interface IBadge { + top?: number + left?: number + width: number + height: number + value: string +} + +export interface IBadgeOption { + top?: number + left?: number +} + +export interface IAreaBadge { + areaId: string + badge: IBadge +} diff --git a/src/editor/interface/Editor.ts b/src/editor/interface/Editor.ts index 7d266702..c93dfc06 100644 --- a/src/editor/interface/Editor.ts +++ b/src/editor/interface/Editor.ts @@ -26,6 +26,7 @@ import { ISeparatorOption } from './Separator' import { ITableOption } from './table/Table' import { ILineNumberOption } from './LineNumber' import { IPageBorderOption } from './PageBorder' +import { IBadgeOption } from './Badge' export interface IEditorData { header?: IElement[] @@ -93,6 +94,7 @@ export interface IEditorOption { separator?: ISeparatorOption lineNumber?: ILineNumberOption pageBorder?: IPageBorderOption + badge?: IBadgeOption } export interface IEditorResult { diff --git a/src/editor/utils/option.ts b/src/editor/utils/option.ts index c4a14a51..6da47126 100644 --- a/src/editor/utils/option.ts +++ b/src/editor/utils/option.ts @@ -46,6 +46,8 @@ import { RenderMode, WordBreak } from '../dataset/enum/Editor' +import { defaultBadgeOption } from '../dataset/constant/Badge' +import { IBadgeOption } from '../interface/Badge' export function mergeOption( options: IEditorOption = {} @@ -126,6 +128,10 @@ export function mergeOption( ...defaultPageBorderOption, ...options.pageBorder } + const badgeOptions: Required = { + ...defaultBadgeOption, + ...options.badge + } return { mode: EditorMode.EDIT, @@ -187,6 +193,7 @@ export function mergeOption( lineBreak: lineBreakOptions, separator: separatorOptions, lineNumber: lineNumberOptions, - pageBorder: pageBorderOptions + pageBorder: pageBorderOptions, + badge: badgeOptions } }