feat: add radio and checkbox vertical align setting

Co-authored-by: Hufe921 <huangyunfeihufe@hotmail.com>
main
zhoujingfu 2 years ago committed by GitHub
parent d1a1aaa6ae
commit c3754663ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -60,8 +60,8 @@ interface IEditorOption {
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 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;} watermark?: IWatermark // Watermark{data:string; color?:string; opacity?:number; size?:number; font?:string;}
control?: IControlOption // Control {placeholderColor?:string; bracketColor?:string; prefix?:string; postfix?:string; borderWidth?: number; borderColor?: 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; strokeStyle?: string;} checkbox?: ICheckboxOption // Checkbox {width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string; verticalAlign?: VerticalAlign;}
radio?: IRadioOption // Radio {width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string;} radio?: IRadioOption // Radio {width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string; verticalAlign?: VerticalAlign;}
cursor?: ICursorOption // Cursor style. {width?: number; color?: string; dragWidth?: number; dragColor?: 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;} title?: ITitleOption // Title configuration.{ defaultFirstSize?: number; defaultSecondSize?: number; defaultThirdSize?: number defaultFourthSize?: number; defaultFifthSize?: number; defaultSixthSize?: number;}
placeholder?: IPlaceholder // Placeholder text placeholder?: IPlaceholder // Placeholder text

@ -60,8 +60,8 @@ interface IEditorOption {
wordBreak?: WordBreak // 单词与标点断行BREAK_WORD首行不出现标点&单词不拆分、BREAK_ALL按字符宽度撑满后折行。默认BREAK_WORD wordBreak?: WordBreak // 单词与标点断行BREAK_WORD首行不出现标点&单词不拆分、BREAK_ALL按字符宽度撑满后折行。默认BREAK_WORD
watermark?: IWatermark // 水印信息。{data:string; color?:string; opacity?:number; size?:number; font?:string;} watermark?: IWatermark // 水印信息。{data:string; color?:string; opacity?:number; size?:number; font?:string;}
control?: IControlOption // 控件信息。 {placeholderColor?:string; bracketColor?:string; prefix?:string; postfix?:string; borderWidth?: number; borderColor?: 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; strokeStyle?: string;} checkbox?: ICheckboxOption // 复选框信息。{width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string; verticalAlign?: VerticalAlign;}
radio?: IRadioOption // 单选框信息。{width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string;} radio?: IRadioOption // 单选框信息。{width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string; verticalAlign?: VerticalAlign;}
cursor?: ICursorOption // 光标样式。{width?: number; color?: string; dragWidth?: number; dragColor?: 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;} title?: ITitleOption // 标题配置。{ defaultFirstSize?: number; defaultSecondSize?: number; defaultThirdSize?: number defaultFourthSize?: number; defaultFifthSize?: number; defaultSixthSize?: number;}
placeholder?: IPlaceholder // 编辑器空白占位文本 placeholder?: IPlaceholder // 编辑器空白占位文本

@ -1912,13 +1912,25 @@ export class Draw {
element.controlComponent === ControlComponent.CHECKBOX element.controlComponent === ControlComponent.CHECKBOX
) { ) {
this.textParticle.complete() this.textParticle.complete()
this.checkboxParticle.render(ctx, element, x, y + offsetY) this.checkboxParticle.render({
ctx,
x,
y: y + offsetY,
index: j,
row: curRow
})
} else if ( } else if (
element.type === ElementType.RADIO || element.type === ElementType.RADIO ||
element.controlComponent === ControlComponent.RADIO element.controlComponent === ControlComponent.RADIO
) { ) {
this.textParticle.complete() this.textParticle.complete()
this.radioParticle.render(ctx, element, x, y + offsetY) this.radioParticle.render({
ctx,
x,
y: y + offsetY,
index: j,
row: curRow
})
} else if (element.type === ElementType.TAB) { } else if (element.type === ElementType.TAB) {
this.textParticle.complete() this.textParticle.complete()
} else if ( } else if (

@ -1,9 +1,19 @@
import { NBSP, ZERO } from '../../../dataset/constant/Common'
import { VerticalAlign } from '../../../dataset/enum/VerticalAlign'
import { DeepRequired } from '../../../interface/Common' import { DeepRequired } from '../../../interface/Common'
import { IEditorOption } from '../../../interface/Editor' import { IEditorOption } from '../../../interface/Editor'
import { IElement } from '../../../interface/Element' import { IElement } from '../../../interface/Element'
import { IRowElement } from '../../../interface/Row' import { IRow, IRowElement } from '../../../interface/Row'
import { Draw } from '../Draw' import { Draw } from '../Draw'
interface ICheckboxRenderOption {
ctx: CanvasRenderingContext2D
x: number
y: number
row: IRow
index: number
}
export class CheckboxParticle { export class CheckboxParticle {
private draw: Draw private draw: Draw
private options: DeepRequired<IEditorOption> private options: DeepRequired<IEditorOption>
@ -28,17 +38,41 @@ export class CheckboxParticle {
}) })
} }
public render( public render(payload: ICheckboxRenderOption) {
ctx: CanvasRenderingContext2D, const { ctx, x, index, row } = payload
element: IRowElement, let { y } = payload
x: number,
y: number
) {
const { const {
checkbox: { gap, lineWidth, fillStyle, strokeStyle }, checkbox: { gap, lineWidth, fillStyle, strokeStyle, verticalAlign },
scale scale
} = this.options } = this.options
const { metrics, checkbox } = element const { metrics, checkbox } = row.elementList[index]
// 垂直布局设置
if (
verticalAlign === VerticalAlign.TOP ||
verticalAlign === VerticalAlign.MIDDLE
) {
let nextIndex = index + 1
let nextElement: IRowElement | null = null
while (nextIndex < row.elementList.length) {
nextElement = row.elementList[nextIndex]
if (nextElement.value !== ZERO && nextElement.value !== NBSP) break
nextIndex++
}
// 以后一个非空格元素为基准
if (nextElement) {
const {
metrics: { boundingBoxAscent, boundingBoxDescent }
} = nextElement
const textHeight = boundingBoxAscent + boundingBoxDescent
if (textHeight > metrics.height) {
if (verticalAlign === VerticalAlign.TOP) {
y -= boundingBoxAscent - metrics.height
} else if (verticalAlign === VerticalAlign.MIDDLE) {
y -= (textHeight - metrics.height) / 2
}
}
}
}
// left top 四舍五入避免1像素问题 // left top 四舍五入避免1像素问题
const left = Math.round(x + gap * scale) const left = Math.round(x + gap * scale)
const top = Math.round(y - metrics.height + lineWidth) const top = Math.round(y - metrics.height + lineWidth)

@ -199,9 +199,16 @@ export class ListParticle {
height: height * scale height: height * scale
} }
} }
this.draw this.draw.getCheckboxParticle().render({
.getCheckboxParticle() ctx,
.render(ctx, checkboxRowElement, x - gap * scale, y) x: x - gap * scale,
y,
index: 0,
row: {
...row,
elementList: [checkboxRowElement, ...row.elementList]
}
})
} else { } else {
let text = '' let text = ''
if (startElement.listType === ListType.UL) { if (startElement.listType === ListType.UL) {

@ -1,9 +1,19 @@
import { NBSP, ZERO } from '../../../dataset/constant/Common'
import { VerticalAlign } from '../../../dataset/enum/VerticalAlign'
import { DeepRequired } from '../../../interface/Common' import { DeepRequired } from '../../../interface/Common'
import { IEditorOption } from '../../../interface/Editor' import { IEditorOption } from '../../../interface/Editor'
import { IElement } from '../../../interface/Element' import { IElement } from '../../../interface/Element'
import { IRowElement } from '../../../interface/Row' import { IRow, IRowElement } from '../../../interface/Row'
import { Draw } from '../Draw' import { Draw } from '../Draw'
interface IRadioRenderOption {
ctx: CanvasRenderingContext2D
x: number
y: number
row: IRow
index: number
}
export class RadioParticle { export class RadioParticle {
private draw: Draw private draw: Draw
private options: DeepRequired<IEditorOption> private options: DeepRequired<IEditorOption>
@ -28,17 +38,41 @@ export class RadioParticle {
}) })
} }
public render( public render(payload: IRadioRenderOption) {
ctx: CanvasRenderingContext2D, const { ctx, x, index, row } = payload
element: IRowElement, let { y } = payload
x: number,
y: number
) {
const { const {
radio: { gap, lineWidth, fillStyle, strokeStyle }, radio: { gap, lineWidth, fillStyle, strokeStyle, verticalAlign },
scale scale
} = this.options } = this.options
const { metrics, radio } = element const { metrics, radio } = row.elementList[index]
// 垂直布局设置
if (
verticalAlign === VerticalAlign.TOP ||
verticalAlign === VerticalAlign.MIDDLE
) {
let nextIndex = index + 1
let nextElement: IRowElement | null = null
while (nextIndex < row.elementList.length) {
nextElement = row.elementList[nextIndex]
if (nextElement.value !== ZERO && nextElement.value !== NBSP) break
nextIndex++
}
// 以后一个非空格元素为基准
if (nextElement) {
const {
metrics: { boundingBoxAscent, boundingBoxDescent }
} = nextElement
const textHeight = boundingBoxAscent + boundingBoxDescent
if (textHeight > metrics.height) {
if (verticalAlign === VerticalAlign.TOP) {
y -= boundingBoxAscent - metrics.height
} else if (verticalAlign === VerticalAlign.MIDDLE) {
y -= (textHeight - metrics.height) / 2
}
}
}
}
// left top 四舍五入避免1像素问题 // left top 四舍五入避免1像素问题
const left = Math.round(x + gap * scale) const left = Math.round(x + gap * scale)
const top = Math.round(y - metrics.height + lineWidth) const top = Math.round(y - metrics.height + lineWidth)

@ -1,4 +1,5 @@
import { ICheckboxOption } from '../../interface/Checkbox' import { ICheckboxOption } from '../../interface/Checkbox'
import { VerticalAlign } from '../enum/VerticalAlign'
export const defaultCheckboxOption: Readonly<Required<ICheckboxOption>> = { export const defaultCheckboxOption: Readonly<Required<ICheckboxOption>> = {
width: 14, width: 14,
@ -6,5 +7,6 @@ export const defaultCheckboxOption: Readonly<Required<ICheckboxOption>> = {
gap: 5, gap: 5,
lineWidth: 1, lineWidth: 1,
fillStyle: '#5175f4', fillStyle: '#5175f4',
strokeStyle: '#ffffff' strokeStyle: '#ffffff',
verticalAlign: VerticalAlign.BOTTOM
} }

@ -1,4 +1,5 @@
import { IRadioOption } from '../../interface/Radio' import { IRadioOption } from '../../interface/Radio'
import { VerticalAlign } from '../enum/VerticalAlign'
export const defaultRadioOption: Readonly<Required<IRadioOption>> = { export const defaultRadioOption: Readonly<Required<IRadioOption>> = {
width: 14, width: 14,
@ -6,5 +7,6 @@ export const defaultRadioOption: Readonly<Required<IRadioOption>> = {
gap: 5, gap: 5,
lineWidth: 1, lineWidth: 1,
fillStyle: '#5175f4', fillStyle: '#5175f4',
strokeStyle: '#000000' strokeStyle: '#000000',
verticalAlign: VerticalAlign.BOTTOM
} }

@ -1,3 +1,5 @@
import { VerticalAlign } from '../dataset/enum/VerticalAlign'
export interface ICheckbox { export interface ICheckbox {
value: boolean | null value: boolean | null
code?: string code?: string
@ -11,4 +13,5 @@ export interface ICheckboxOption {
lineWidth?: number lineWidth?: number
fillStyle?: string fillStyle?: string
strokeStyle?: string strokeStyle?: string
verticalAlign?: VerticalAlign
} }

@ -1,3 +1,5 @@
import { VerticalAlign } from '../dataset/enum/VerticalAlign'
export interface IRadio { export interface IRadio {
value: boolean | null value: boolean | null
code?: string code?: string
@ -11,4 +13,5 @@ export interface IRadioOption {
lineWidth?: number lineWidth?: number
fillStyle?: string fillStyle?: string
strokeStyle?: string strokeStyle?: string
verticalAlign?: VerticalAlign
} }

Loading…
Cancel
Save