130 lines
4.7 KiB
JavaScript
130 lines
4.7 KiB
JavaScript
|
|
// 通用多按钮组件定义
|
|
const MultiButtonWidget = (app, inputName, options, buttons) => {
|
|
const widget = {
|
|
name: inputName,
|
|
type: "multi_button",
|
|
y: 0,
|
|
value: null,
|
|
options: options || {},
|
|
clicked_button: null,
|
|
click_time: 0
|
|
};
|
|
|
|
// 使用 ComfyUI 原生样式常量
|
|
const margin = 15;
|
|
const button_height = LiteGraph.NODE_WIDGET_HEIGHT || 20;
|
|
const label_width = options.labelWidth !== undefined ? options.labelWidth : 80;
|
|
const button_spacing = options.buttonSpacing || 4;
|
|
const button_count = buttons.length;
|
|
|
|
// 原生 ComfyUI 按钮颜色
|
|
const BUTTON_BGCOLOR = "#222";
|
|
const BUTTON_OUTLINE_COLOR = "#666";
|
|
const BUTTON_TEXT_COLOR = "#DDD";
|
|
const BUTTON_CLICKED_COLOR = "#AAA";
|
|
|
|
widget.draw = function(ctx, node, width, Y, height) {
|
|
if (app.canvas.ds.scale < 0.50) return;
|
|
|
|
ctx.save();
|
|
ctx.lineWidth = 1;
|
|
|
|
// 绘制标签(仅当有标签时)
|
|
if (label_width > 0 && inputName) {
|
|
ctx.fillStyle = LiteGraph.WIDGET_SECONDARY_TEXT_COLOR;
|
|
ctx.textAlign = "left";
|
|
ctx.fillText(inputName, margin, Y + height * 0.7);
|
|
}
|
|
|
|
// 计算按钮区域
|
|
const label_space = label_width > 0 ? label_width : 0;
|
|
const left_margin = label_width > 0 ? margin : 10; // 没有标签时使用小边距避免超出节点
|
|
const right_margin = label_width > 0 ? margin : 10; // 右边也保持小边距
|
|
const available_width = width - label_space - left_margin - right_margin;
|
|
const total_spacing = button_spacing * (button_count - 1);
|
|
const button_width = (available_width - total_spacing) / button_count;
|
|
const start_x = label_space + left_margin;
|
|
|
|
// 检查点击高亮是否需要清除
|
|
const now = Date.now();
|
|
if (widget.click_time && now - widget.click_time > 150) {
|
|
widget.clicked_button = null;
|
|
widget.click_time = 0;
|
|
}
|
|
|
|
// 循环绘制所有按钮
|
|
for (let i = 0; i < button_count; i++) {
|
|
const button = buttons[i];
|
|
const button_x = start_x + i * (button_width + button_spacing);
|
|
|
|
// 确定按钮颜色(点击高亮或默认)
|
|
const is_clicked = (widget.clicked_button === i);
|
|
const button_color = is_clicked ? BUTTON_CLICKED_COLOR :
|
|
(button.color || BUTTON_BGCOLOR);
|
|
|
|
// 绘制按钮背景
|
|
ctx.fillStyle = button_color;
|
|
ctx.fillRect(button_x, Y, button_width, button_height);
|
|
|
|
// 绘制按钮边框
|
|
ctx.strokeStyle = BUTTON_OUTLINE_COLOR;
|
|
ctx.strokeRect(button_x, Y, button_width, button_height);
|
|
|
|
// 绘制按钮文字
|
|
ctx.fillStyle = BUTTON_TEXT_COLOR;
|
|
ctx.textAlign = "center";
|
|
ctx.fillText(button.text, button_x + button_width / 2, Y + button_height * 0.7);
|
|
}
|
|
|
|
ctx.restore();
|
|
};
|
|
|
|
widget.onPointerDown = function(pointer, node) {
|
|
const e = pointer.eDown;
|
|
const label_space = label_width > 0 ? label_width : 0;
|
|
const left_margin = label_width > 0 ? margin : 10;
|
|
const right_margin = label_width > 0 ? margin : 10;
|
|
const x = e.canvasX - node.pos[0] - label_space - left_margin;
|
|
const available_width = node.size[0] - label_space - left_margin - right_margin;
|
|
const total_spacing = button_spacing * (button_count - 1);
|
|
const button_width = (available_width - total_spacing) / button_count;
|
|
|
|
pointer.onClick = () => {
|
|
// 计算点击了哪个按钮
|
|
for (let i = 0; i < button_count; i++) {
|
|
const button_start = i * (button_width + button_spacing);
|
|
const button_end = button_start + button_width;
|
|
|
|
if (x >= button_start && x <= button_end) {
|
|
// 点击了第 i 个按钮
|
|
widget.clicked_button = i;
|
|
widget.click_time = Date.now();
|
|
|
|
// 执行回调函数
|
|
if (buttons[i] && buttons[i].callback) {
|
|
buttons[i].callback();
|
|
}
|
|
|
|
// 触发重绘以显示点击效果
|
|
app.graph.setDirtyCanvas(true);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
widget.computeSize = function() {
|
|
return [0, button_height];
|
|
};
|
|
|
|
widget.serializeValue = async () => {
|
|
return null;
|
|
};
|
|
|
|
return widget;
|
|
};
|
|
|
|
// 导出组件
|
|
export { MultiButtonWidget };
|