Files
ComfyUI_frontend/src/widgets/SliderWidget.ts
filtered 81a00b5e6c [Refactor] Remove repeat interface definitions (#976)
Prefers param destructuring over manual impl.
2025-04-27 16:30:59 +00:00

128 lines
3.6 KiB
TypeScript

import type { ISliderWidget, IWidgetSliderOptions } from "@/types/widgets"
import { clamp } from "@/litegraph"
import { BaseWidget, type DrawWidgetOptions, type WidgetEventOptions } from "./BaseWidget"
export class SliderWidget extends BaseWidget implements ISliderWidget {
// ISliderWidget properties
declare type: "slider"
declare value: number
declare options: IWidgetSliderOptions
marker?: number
constructor(widget: ISliderWidget) {
super(widget)
this.type = "slider"
this.value = widget.value
this.options = widget.options
this.marker = widget.marker
}
/**
* Draws the widget
* @param ctx The canvas context
* @param options The options for drawing the widget
*/
override drawWidget(ctx: CanvasRenderingContext2D, {
y,
width,
show_text = true,
margin = BaseWidget.margin,
}: DrawWidgetOptions) {
// Store original context attributes
const originalTextAlign = ctx.textAlign
const originalStrokeStyle = ctx.strokeStyle
const originalFillStyle = ctx.fillStyle
const { height } = this
// Draw background
ctx.fillStyle = this.background_color
ctx.fillRect(margin, y, width - margin * 2, height)
// Calculate normalized value
const range = this.options.max - this.options.min
let nvalue = (this.value - this.options.min) / range
nvalue = clamp(nvalue, 0, 1)
// Draw slider bar
ctx.fillStyle = this.options.slider_color ?? "#678"
ctx.fillRect(margin, y, nvalue * (width - margin * 2), height)
// Draw outline if not disabled
if (show_text && !this.computedDisabled) {
ctx.strokeStyle = this.outline_color
ctx.strokeRect(margin, y, width - margin * 2, height)
}
// Draw marker if present
if (this.marker != null) {
let marker_nvalue = (this.marker - this.options.min) / range
marker_nvalue = clamp(marker_nvalue, 0, 1)
ctx.fillStyle = this.options.marker_color ?? "#AA9"
ctx.fillRect(
margin + marker_nvalue * (width - margin * 2),
y,
2,
height,
)
}
// Draw text
if (show_text) {
ctx.textAlign = "center"
ctx.fillStyle = this.text_color
const fixedValue = Number(this.value).toFixed(this.options.precision ?? 3)
ctx.fillText(
`${this.label || this.name} ${fixedValue}`,
width * 0.5,
y + height * 0.7,
)
}
// Restore original context attributes
ctx.textAlign = originalTextAlign
ctx.strokeStyle = originalStrokeStyle
ctx.fillStyle = originalFillStyle
}
/**
* Handles click events for the slider widget
*/
override onClick(options: WidgetEventOptions) {
if (this.options.read_only) return
const { e, node } = options
const width = this.width || node.size[0]
const x = e.canvasX - node.pos[0]
// Calculate new value based on click position
const slideFactor = clamp((x - 15) / (width - 30), 0, 1)
const newValue = this.options.min + (this.options.max - this.options.min) * slideFactor
if (newValue !== this.value) {
this.setValue(newValue, options)
}
}
/**
* Handles drag events for the slider widget
*/
override onDrag(options: WidgetEventOptions) {
if (this.options.read_only) return false
const { e, node } = options
const width = this.width || node.size[0]
const x = e.canvasX - node.pos[0]
// Calculate new value based on drag position
const slideFactor = clamp((x - 15) / (width - 30), 0, 1)
const newValue = this.options.min + (this.options.max - this.options.min) * slideFactor
if (newValue !== this.value) {
this.setValue(newValue, options)
}
}
}