feat: add control border #388
This commit is contained in:
@@ -60,7 +60,7 @@ interface IEditorOption {
|
||||
scrollContainerSelector?: string // scroll container selector. default: document
|
||||
wordBreak?: WordBreak // Word and punctuation breaks: No punctuation in the first line of the BREAK_WORD &The word is not split, and the line is folded after BREAK_ALL full according to the width of the character. default: BREAK_WORD
|
||||
watermark?: IWatermark // Watermark{data:string; color?:string; opacity?:number; size?:number; font?:string;}
|
||||
control?: IControlOption // Control {placeholderColor?:string; bracketColor?:string; prefix?:string; postfix?:string;}
|
||||
control?: IControlOption // Control {placeholderColor?:string; bracketColor?:string; prefix?:string; postfix?:string; borderWidth?: number; borderColor?: string;}
|
||||
checkbox?: ICheckboxOption // Checkbox {width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; fontStyle?: string;}
|
||||
cursor?: ICursorOption // Cursor style. {width?: number; color?: string; dragWidth?: number; dragColor?: string;}
|
||||
title?: ITitleOption // Title configuration.{ defaultFirstSize?: number; defaultSecondSize?: number; defaultThirdSize?: number defaultFourthSize?: number; defaultFifthSize?: number; defaultSixthSize?: number;}
|
||||
|
||||
@@ -84,6 +84,7 @@ interface IElement {
|
||||
postfix?: string;
|
||||
minWidth?: number;
|
||||
underline?: boolean;
|
||||
border?: boolean;
|
||||
extension?: unknown;
|
||||
indentation?: ControlIndentation;
|
||||
deletable?: boolean;
|
||||
|
||||
@@ -60,7 +60,7 @@ interface IEditorOption {
|
||||
scrollContainerSelector?: string // 滚动区域选择器。默认:document
|
||||
wordBreak?: WordBreak // 单词与标点断行:BREAK_WORD首行不出现标点&单词不拆分、BREAK_ALL按字符宽度撑满后折行。默认:BREAK_WORD
|
||||
watermark?: IWatermark // 水印信息。{data:string; color?:string; opacity?:number; size?:number; font?:string;}
|
||||
control?: IControlOption // 控件信息。 {placeholderColor?:string; bracketColor?:string; prefix?:string; postfix?:string;}
|
||||
control?: IControlOption // 控件信息。 {placeholderColor?:string; bracketColor?:string; prefix?:string; postfix?:string; borderWidth?: number; borderColor?: string;}
|
||||
checkbox?: ICheckboxOption // 复选框信息。{width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; fontStyle?: string;}
|
||||
cursor?: ICursorOption // 光标样式。{width?: number; color?: string; dragWidth?: number; dragColor?: string;}
|
||||
title?: ITitleOption // 标题配置。{ defaultFirstSize?: number; defaultSecondSize?: number; defaultThirdSize?: number defaultFourthSize?: number; defaultFifthSize?: number; defaultSixthSize?: number;}
|
||||
|
||||
@@ -84,6 +84,7 @@ interface IElement {
|
||||
postfix?: string;
|
||||
minWidth?: number;
|
||||
underline?: boolean;
|
||||
border?: boolean;
|
||||
extension?: unknown;
|
||||
indentation?: ControlIndentation;
|
||||
deletable?: boolean;
|
||||
|
||||
@@ -1096,6 +1096,14 @@ export class Draw {
|
||||
return el.actualSize || el.size || this.options.defaultSize
|
||||
}
|
||||
|
||||
public getElementRowMargin(el: IElement) {
|
||||
const { defaultBasicRowMarginHeight, defaultRowMargin, scale } =
|
||||
this.options
|
||||
return (
|
||||
defaultBasicRowMarginHeight * (el.rowMargin || defaultRowMargin) * scale
|
||||
)
|
||||
}
|
||||
|
||||
public computeRowList(payload: IComputeRowListPayload) {
|
||||
const { innerWidth, elementList, isPagingMode = false } = payload
|
||||
const { defaultSize, defaultRowMargin, scale, tdPadding, defaultTabWidth } =
|
||||
@@ -1695,13 +1703,7 @@ export class Draw {
|
||||
const { rowList, pageNo, elementList, positionList, startIndex, zone } =
|
||||
payload
|
||||
const isPrintMode = this.mode === EditorMode.PRINT
|
||||
const {
|
||||
scale,
|
||||
tdPadding,
|
||||
defaultBasicRowMarginHeight,
|
||||
defaultRowMargin,
|
||||
group
|
||||
} = this.options
|
||||
const { scale, tdPadding, group } = this.options
|
||||
const { isCrossRowCol, tableId } = this.range.getRange()
|
||||
let index = startIndex
|
||||
for (let i = 0; i < rowList.length; i++) {
|
||||
@@ -1803,6 +1805,26 @@ export class Draw {
|
||||
this.textParticle.complete()
|
||||
}
|
||||
}
|
||||
// 边框绘制(目前仅支持控件)
|
||||
if (element.control?.border) {
|
||||
// 不同控件边框立刻绘制
|
||||
if (
|
||||
preElement?.control?.border &&
|
||||
preElement.controlId !== element.controlId
|
||||
) {
|
||||
this.control.drawBorder(ctx)
|
||||
}
|
||||
// 当前元素位置信息记录
|
||||
const rowMargin = this.getElementRowMargin(element)
|
||||
this.control.recordBorderInfo(
|
||||
x,
|
||||
y + rowMargin,
|
||||
element.metrics.width,
|
||||
curRow.height - 2 * rowMargin
|
||||
)
|
||||
} else if (preElement?.control?.border) {
|
||||
this.control.drawBorder(ctx)
|
||||
}
|
||||
// 下划线记录
|
||||
if (element.underline || element.control?.underline) {
|
||||
// 上下标元素下划线单独绘制
|
||||
@@ -1815,10 +1837,7 @@ export class Draw {
|
||||
this.underline.render(ctx)
|
||||
}
|
||||
// 行间距
|
||||
const rowMargin =
|
||||
defaultBasicRowMarginHeight *
|
||||
(element.rowMargin || defaultRowMargin) *
|
||||
scale
|
||||
const rowMargin = this.getElementRowMargin(element)
|
||||
// 元素向左偏移量
|
||||
const offsetX = element.left || 0
|
||||
// 上下标元素y轴偏移值
|
||||
@@ -1954,8 +1973,9 @@ export class Draw {
|
||||
positionList[curRow.startIndex]
|
||||
)
|
||||
}
|
||||
// 绘制文字、下划线、删除线
|
||||
// 绘制文字、边框、下划线、删除线
|
||||
this.textParticle.complete()
|
||||
this.control.drawBorder(ctx)
|
||||
this.underline.render(ctx)
|
||||
this.strikeout.render(ctx)
|
||||
// 绘制批注样式
|
||||
|
||||
@@ -33,6 +33,7 @@ import { RangeManager } from '../../range/RangeManager'
|
||||
import { Draw } from '../Draw'
|
||||
import { CheckboxControl } from './checkbox/CheckboxControl'
|
||||
import { ControlSearch } from './interactive/ControlSearch'
|
||||
import { ControlBorder } from './richtext/Border'
|
||||
import { SelectControl } from './select/SelectControl'
|
||||
import { TextControl } from './text/TextControl'
|
||||
|
||||
@@ -41,6 +42,7 @@ interface IMoveCursorResult {
|
||||
newElement: IElement
|
||||
}
|
||||
export class Control {
|
||||
private controlBorder: ControlBorder
|
||||
private draw: Draw
|
||||
private range: RangeManager
|
||||
private listener: Listener
|
||||
@@ -51,6 +53,8 @@ export class Control {
|
||||
private activeControl: IControlInstance | null
|
||||
|
||||
constructor(draw: Draw) {
|
||||
this.controlBorder = new ControlBorder(draw)
|
||||
|
||||
this.draw = draw
|
||||
this.range = draw.getRange()
|
||||
this.listener = draw.getListener()
|
||||
@@ -760,4 +764,12 @@ export class Control {
|
||||
}
|
||||
return zipElementList(controlElementList)
|
||||
}
|
||||
|
||||
public recordBorderInfo(x: number, y: number, width: number, height: number) {
|
||||
this.controlBorder.recordBorderInfo(x, y, width, height)
|
||||
}
|
||||
|
||||
public drawBorder(ctx: CanvasRenderingContext2D) {
|
||||
this.controlBorder.render(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import { DeepRequired } from '../../../../interface/Common'
|
||||
import { IEditorOption } from '../../../../interface/Editor'
|
||||
import { IElementFillRect } from '../../../../interface/Element'
|
||||
import { Draw } from '../../Draw'
|
||||
|
||||
export class ControlBorder {
|
||||
protected borderRect: IElementFillRect
|
||||
private options: DeepRequired<IEditorOption>
|
||||
|
||||
constructor(draw: Draw) {
|
||||
this.borderRect = this.clearBorderInfo()
|
||||
this.options = draw.getOptions()
|
||||
}
|
||||
|
||||
public clearBorderInfo() {
|
||||
this.borderRect = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0
|
||||
}
|
||||
return this.borderRect
|
||||
}
|
||||
|
||||
public recordBorderInfo(x: number, y: number, width: number, height: number) {
|
||||
const isFirstRecord = !this.borderRect.width
|
||||
if (isFirstRecord) {
|
||||
this.borderRect.x = x
|
||||
this.borderRect.y = y
|
||||
this.borderRect.height = height
|
||||
}
|
||||
this.borderRect.width += width
|
||||
}
|
||||
|
||||
public render(ctx: CanvasRenderingContext2D) {
|
||||
if (!this.borderRect.width) return
|
||||
const {
|
||||
scale,
|
||||
control: { borderWidth, borderColor }
|
||||
} = this.options
|
||||
const { x, y, width, height } = this.borderRect
|
||||
ctx.save()
|
||||
ctx.translate(0, 1 * scale)
|
||||
ctx.lineWidth = borderWidth * scale
|
||||
ctx.strokeStyle = borderColor
|
||||
ctx.beginPath()
|
||||
ctx.rect(x, y, width, height)
|
||||
ctx.stroke()
|
||||
ctx.restore()
|
||||
this.clearBorderInfo()
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,7 @@ export const defaultControlOption: Readonly<Required<IControlOption>> = {
|
||||
placeholderColor: '#9c9b9b',
|
||||
bracketColor: '#000000',
|
||||
prefix: '{',
|
||||
postfix: '}'
|
||||
postfix: '}',
|
||||
borderWidth: 1,
|
||||
borderColor: '#000000'
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ export interface IControlBasic {
|
||||
postfix?: string
|
||||
minWidth?: number
|
||||
underline?: boolean
|
||||
border?: boolean
|
||||
extension?: unknown
|
||||
indentation?: ControlIndentation
|
||||
}
|
||||
@@ -61,6 +62,8 @@ export interface IControlOption {
|
||||
bracketColor?: string
|
||||
prefix?: string
|
||||
postfix?: string
|
||||
borderWidth?: number
|
||||
borderColor?: string
|
||||
}
|
||||
|
||||
export interface IControlInitOption {
|
||||
|
||||
Reference in New Issue
Block a user