feat: add radio element #494
Co-authored-by: jeffycai <caixiaobing@live.cn> Co-authored-by: Hufe921 <huangyunfeihufe@hotmail.com>pr675
parent
2e1403507f
commit
c6d9cffc27
|
After Width: | Height: | Size: 236 B |
@ -0,0 +1,57 @@
|
|||||||
|
import { ControlComponent } from '../../../../dataset/enum/Control'
|
||||||
|
import {
|
||||||
|
IControlContext,
|
||||||
|
IControlRuleOption
|
||||||
|
} from '../../../../interface/Control'
|
||||||
|
import { CheckboxControl } from '../checkbox/CheckboxControl'
|
||||||
|
|
||||||
|
export class RadioControl extends CheckboxControl {
|
||||||
|
public setSelect(
|
||||||
|
codes: string[],
|
||||||
|
context: IControlContext = {},
|
||||||
|
options: IControlRuleOption = {}
|
||||||
|
) {
|
||||||
|
// 校验是否可以设置
|
||||||
|
if (!options.isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { control } = this.element
|
||||||
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
|
const { startIndex } = context.range || this.control.getRange()
|
||||||
|
const startElement = elementList[startIndex]
|
||||||
|
// 向左查找
|
||||||
|
let preIndex = startIndex
|
||||||
|
while (preIndex > 0) {
|
||||||
|
const preElement = elementList[preIndex]
|
||||||
|
if (
|
||||||
|
preElement.controlId !== startElement.controlId ||
|
||||||
|
preElement.controlComponent === ControlComponent.PREFIX
|
||||||
|
) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (preElement.controlComponent === ControlComponent.RADIO) {
|
||||||
|
const radio = preElement.radio!
|
||||||
|
radio.value = codes.includes(radio.code!)
|
||||||
|
}
|
||||||
|
preIndex--
|
||||||
|
}
|
||||||
|
// 向右查找
|
||||||
|
let nextIndex = startIndex + 1
|
||||||
|
while (nextIndex < elementList.length) {
|
||||||
|
const nextElement = elementList[nextIndex]
|
||||||
|
if (
|
||||||
|
nextElement.controlId !== startElement.controlId ||
|
||||||
|
nextElement.controlComponent === ControlComponent.POSTFIX
|
||||||
|
) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (nextElement.controlComponent === ControlComponent.RADIO) {
|
||||||
|
const radio = nextElement.radio!
|
||||||
|
radio.value = codes.includes(radio.code!)
|
||||||
|
}
|
||||||
|
nextIndex++
|
||||||
|
}
|
||||||
|
control!.code = codes.join(',')
|
||||||
|
this.control.repaintControl()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
import { DeepRequired } from '../../../interface/Common'
|
||||||
|
import { IEditorOption } from '../../../interface/Editor'
|
||||||
|
import { IElement } from '../../../interface/Element'
|
||||||
|
import { IRowElement } from '../../../interface/Row'
|
||||||
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
|
export class RadioParticle {
|
||||||
|
private draw: Draw
|
||||||
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
|
constructor(draw: Draw) {
|
||||||
|
this.draw = draw
|
||||||
|
this.options = draw.getOptions()
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSelect(element: IElement) {
|
||||||
|
const { radio } = element
|
||||||
|
if (radio) {
|
||||||
|
radio.value = !radio.value
|
||||||
|
} else {
|
||||||
|
element.radio = {
|
||||||
|
value: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.draw.render({
|
||||||
|
isCompute: false,
|
||||||
|
isSetCursor: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
element: IRowElement,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
) {
|
||||||
|
const {
|
||||||
|
radio: { gap, lineWidth, fillStyle, strokeStyle },
|
||||||
|
scale
|
||||||
|
} = this.options
|
||||||
|
const { metrics, radio } = element
|
||||||
|
// left top 四舍五入避免1像素问题
|
||||||
|
const left = Math.round(x + gap * scale)
|
||||||
|
const top = Math.round(y - metrics.height + lineWidth)
|
||||||
|
const width = metrics.width - gap * 2 * scale
|
||||||
|
const height = metrics.height
|
||||||
|
ctx.save()
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.translate(0.5, 0.5)
|
||||||
|
// 边框
|
||||||
|
ctx.strokeStyle = radio?.value ? fillStyle : strokeStyle
|
||||||
|
ctx.lineWidth = lineWidth
|
||||||
|
ctx.arc(left + width / 2, top + height / 2, width / 2, 0, Math.PI * 2)
|
||||||
|
ctx.stroke()
|
||||||
|
// 填充选中色
|
||||||
|
if (radio?.value) {
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.fillStyle = fillStyle
|
||||||
|
ctx.arc(left + width / 2, top + height / 2, width / 3, 0, Math.PI * 2)
|
||||||
|
ctx.fill()
|
||||||
|
}
|
||||||
|
ctx.closePath()
|
||||||
|
ctx.restore()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { IRadioOption } from '../../interface/Radio'
|
||||||
|
|
||||||
|
export const defaultRadioOption: Readonly<Required<IRadioOption>> = {
|
||||||
|
width: 14,
|
||||||
|
height: 14,
|
||||||
|
gap: 5,
|
||||||
|
lineWidth: 1,
|
||||||
|
fillStyle: '#5175f4',
|
||||||
|
strokeStyle: '#000000'
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
export interface IRadio {
|
||||||
|
value: boolean | null
|
||||||
|
code?: string
|
||||||
|
disabled?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRadioOption {
|
||||||
|
width?: number
|
||||||
|
height?: number
|
||||||
|
gap?: number
|
||||||
|
lineWidth?: number
|
||||||
|
fillStyle?: string
|
||||||
|
strokeStyle?: string
|
||||||
|
}
|
||||||
Loading…
Reference in new issue