diff --git a/node_info.js b/node_info.js
index b8742ea..1f76ac6 100644
--- a/node_info.js
+++ b/node_info.js
@@ -126,71 +126,26 @@ const Templates = {
};
// ======================== 最终导出的SVG常量 ========================
-const moveElementSvg = buildSVG(Templates.moveElement(), {
- t: '1745769856000',
- pId: '8808'
-});
-
-const alignLeftSvg = buildSVG(Templates.alignLeft(), {
- t: '1725534370541',
- pId: '2104'
-});
-
-const alignCenterVerticallySvg = buildSVG(Templates.alignCenterVertically(), {
- t: '1725534363707',
- pId: '1810'
-});
-
-const alignRightSvg = buildSVG(Templates.alignRight(), {
- t: '1725534384109',
- pId: '2398'
-});
-
-const alignTopSvg = buildSVG(Templates.alignTop(), {
- t: '1725534367556',
- pId: '1957'
-});
-
-const alignCenterHorizontallySvg = buildSVG(Templates.alignCenterHorizontally(), {
- t: '1725534379860',
- pId: '2251'
-});
-
-const alignBottomSvg = buildSVG(Templates.alignBottom(), {
- t: '1725534360155',
- pId: '1663'
-});
-
-const horizontalDistributionSvg = buildSVG(Templates.horizontalDistribution(), {
- t: '1725534354023',
- pId: '1516'
-});
-
-const verticalDistributionSvg = buildSVG(Templates.verticalDistribution(), {
- t: '1725534350231',
- pId: '1369'
-});
-
-const equalWidthSvg = buildSVG(Templates.equalWidth(), {
- t: '1725606034670',
- pId: '7216'
-});
-
-const equalHeightSvg = buildSVG(Templates.equalHeight(), {
- t: '1725606224564',
- pId: '7793'
-});
+const moveElementSvg = buildSVG(Templates.moveElement(), { t: '1745769856000', pId: '8808' });
+const alignLeftSvg = buildSVG(Templates.alignLeft(), { t: '1725534370541', pId: '2104' });
+const alignCenterVerticallySvg = buildSVG(Templates.alignCenterVertically(), { t: '1725534363707', pId: '1810' });
+const alignRightSvg = buildSVG(Templates.alignRight(), { t: '1725534384109', pId: '2398' });
+const alignTopSvg = buildSVG(Templates.alignTop(), { t: '1725534367556', pId: '1957' });
+const alignCenterHorizontallySvg = buildSVG(Templates.alignCenterHorizontally(), { t: '1725534379860', pId: '2251' });
+const alignBottomSvg = buildSVG(Templates.alignBottom(), { t: '1725534360155', pId: '1663' });
+const horizontalDistributionSvg = buildSVG(Templates.horizontalDistribution(), { t: '1725534354023', pId: '1516' });
+const verticalDistributionSvg = buildSVG(Templates.verticalDistribution(), { t: '1725534350231', pId: '1369' });
+const equalWidthSvg = buildSVG(Templates.equalWidth(), { t: '1725606034670', pId: '7216' });
+const equalHeightSvg = buildSVG(Templates.equalHeight(), { t: '1725606224564', pId: '7793' });
-
-
-
-
-
-
// 实现ButtonManager对象
const ButtonManager = {
-
+ // 2025-04-30 00:50:28 ================UI缩放====================
+ zoomLevels: [1.5, 2, 0.5, 1], // 缩放级别顺序
+ currentZoom: 1, // 当前缩放级别
+ isSystemZoom: false, // 是否系统级缩放
+
// 2025-04-28 18:44:47 ================= 颜色配置 =================
ColorConfig: {
@@ -211,6 +166,34 @@ const ButtonManager = {
}
},
+ // ================= UI缩放方法 =================
+ toggleUIScale(e) {
+ // 获取下一个缩放级别
+ const currentIndex = this.zoomLevels.indexOf(this.currentZoom);
+ const nextIndex = (currentIndex + 1) % this.zoomLevels.length;
+ this.currentZoom = this.zoomLevels[nextIndex];
+ this.isSystemZoom = e.ctrlKey;
+
+ // 应用缩放
+ if (this.isSystemZoom) {
+ document.body.style.zoom = this.currentZoom;
+ this.buttonContainer.style.transform = '';
+ } else {
+ this.buttonContainer.style.transform = `scale(${this.currentZoom})`;
+ document.body.style.zoom = '';
+ }
+
+ // 更新按钮文本
+ this.updateScaleButtonText();
+ },
+
+ updateScaleButtonText() {
+ const scaleBtn = this.contextMenu.querySelector('#ui-scale-btn');
+ if (scaleBtn) {
+ scaleBtn.textContent = `UI缩放 ${this.currentZoom}x`;
+ }
+ },
+
isInitialized: false, // 检查是否已经初始化
buttonContainer: null, // 保存按钮容器
contextMenu: null, // 右键菜单
@@ -227,6 +210,19 @@ const ButtonManager = {
init() {
if (this.isInitialized) return; // 如果已经初始化过,不再重复创建
+
+ // 2025-04-30 00:57:36 =============确保每次初始化时重置缩放状态==开始================
+ this.currentZoomIndex = 0;
+ this.systemWideZoom = false;
+ // 在init()方法中删除旧版本的重置逻辑
+ // if (this.buttonContainer) {
+ // this.buttonContainer.style.transform = '';
+ // }
+ // if (document.body) {
+ // document.body.style.zoom = '';
+ // }
+ // 2025-04-30 00:57:36 =============确保每次初始化时重置缩放状态==结束================
+
this.boundOnDragging = this.onDragging.bind(this);
this.boundOnDragEnd = this.onDragEnd.bind(this);
@@ -348,45 +344,78 @@ const ButtonManager = {
/* 2025-04-28 03:48:09 ArtsticH新增-右键菜单容器样式 */
#context-menu {
- display: flex;
- width: 1300;
- height: 32px;
+ display: flex; /* flex布局 */
+ white-space: nowrap; /* 防止换行、合并空白字符 */
+ box-sizing: border-box;
+
+ background: #18181B; /* 设置提示框的背景颜色-测试定位用 #70A3F3; */
+
+ align-items: center; /* 确保子元素垂直居中 */
+ justify-content: center; /* 确保子元素水平居中 */
+ width: auto; /* 改为自动宽度width: 1300;auto; */
+ height: auto; /* 保持固定高度height: 32px; */
+ border-radius: 6px;
z-index: 9999;
- margin-left: -200px; /* 向左偏移 20px */
- background: #70A3F3; /* 设置提示框的背景颜色-测试定位用 background: #333; */
+ padding: 0 8px; /* 添加内边距 */
+ gap: 6px; /* 按钮间距 */
+ margin-left: -656.73px;/* 微调水平偏移量 margin-left: -630.73px; */
+
+ /* margin-left: -200px; 向左偏移 20px */
/* display: inline-block; */
/* vertical-align: middle; */
- align-self: center; /* 新增:确保单个按钮垂直居中 */
+ /* align-self: center; 新增:确保单个按钮垂直居中 */
/* place-items: center; 子元素水平和垂直居中 */
/* text-align: center; 让子元素水平居中 */
}
/* 2025-04-28 03:48:09 ArtsticH新增-右键菜单按钮样式-精准控制按钮垂直位置 */
- #context-menu button {
- font-size: 16px; /* 字号 */
- background: #09090B; /* 背景色 background: #18181B; */
- border: 1px solid #3D3D43; /* 边框颜色 border: 1px solid #3D3D43; */
- border-radius: 6px; /* 圆角 border-radius: 6px; */
- color: #fff; /* 文字颜色 color: #fff; */
- padding: 6px 12px; /* 内边距 padding: 6px 12px; */
- margin: 0 3px; /* 按钮间距 margin: 0 4px; */
- cursor: pointer; /* 鼠标手势 cursor: pointer; */
- transition: all 0.1s ease; /* 过渡动画 transition: all 0.2s ease; */
- /* position: relative !important; */
- /* top: -4.5px !important; 微调垂直偏移量 */
- /* right: 35px !important; 微调水平偏移量 */
- /* vertical-align: middle !important; */
+ #context-menu :is(input, button) {
+ height: 26; /* 高度auto;height: 26px; */
+ min-height: 16px; /* 最小高度 */
+ font-size: 14px;
+ background: #09090B;
+ border: 1px solid #3D3D43;
+ border-radius: 6px;
+ color: #fff;
+ padding: 4px 12px; /* 调整内边距 */
+ margin: 0; /* 移除外边距。 按钮间距margin: 0 3px; */
+
+ transition: all 0.1s ease; /* 过渡动画 transition: all 0.2s ease; */
+ position: relative !important;
}
+ #context-menu button {
+ min-height: 32px !important;
+ /* top: -233x !important; 微调垂直偏移量 */
+ /* right: 35px !important; 微调水平偏移量 */
+ }
+ #context-menu input {
+ outline: none;
+ min-height: 32px !important;
+ top: -1.5px !important; /* 微调垂直偏移量 */
+ /* right: 35px !important; 微调水平偏移量 */
+ }
+
/* 2025-04-28 03:48:09 ArtsticH新增-悬停效果 */
- #context-menu button:hover {
+ #context-menu :is(input, button):hover {
background: #222226; /* 悬停背景色 background: #222226; */
border-color: #70A3F3; /* 悬停边框色 border-color: #70A3F3; */
transform: scale(1.1); /* 轻微放大 transform: scale(1.1); */
}
/* 2025-04-28 03:48:09 ArtsticH新增-点击效果 */
- #context-menu button:active {
+ #context-menu :is(input, button):active {
background: #2D2D32; /* 点击背景色 background: #2D2D32; */
transform: scale(0.98); /* 轻微缩小 transform: scale(0.98); */
}
+
+ #context-menu input:hover {
+ outline: none;
+ transform: scale(1) !important; /* 轻微放大 transform: scale(1.1); */
+ }
+ /* 2025-04-28 03:48:09 ArtsticH新增-点击效果 */
+ #context-menu input:active {
+ outline: none;
+ transform: scale(0.99) !important; /* 轻微缩小 transform: scale(0.98); */
+ }
+
/* 2025-04-28 03:48:09 ArtsticH新增-文字标签和文字链接样式 */
#context-menu a.no-underline {
color: #A1A1AA; /* 文字颜色 color: #A1A1AA; */
@@ -398,7 +427,6 @@ const ButtonManager = {
/* margin-right: 8px !important; */
}
-
/* 2025-04-28 18:44:47 新增颜色按钮专用样式 */
#alignment-buttons [id^="color"] {
width: 24px !important; /* width: 16px !important; */
@@ -466,7 +494,6 @@ const ButtonManager = {
font-size: 12px;
white-space: nowrap;
}
-
`;
document.head.appendChild(style);
@@ -633,6 +660,45 @@ const ButtonManager = {
console.error("颜色设置失败:", error);
}
},
+ // 2025-04-30 12:51:05 =====================新增 resetNodesColor 方法===================
+ resetNodesColor() {
+ try {
+ const app = this.getComfyUIAppInstance();
+ if (!app) return;
+
+ // 获取选中节点和组
+ const selected = [...this.getSelectedNodes(app), ...this.getSelectedGroups(app)];
+ if (selected.length === 0) return;
+
+ // 重置颜色
+ selected.forEach(item => {
+ if (item.is_system) return;
+
+ if (item.pos !== undefined) { // 节点
+ item.color = undefined;
+ item.bgcolor = undefined;
+ if (item.setDirtyCanvas) item.setDirtyCanvas(true);
+ }
+ else if (item.children) { // 组
+ item.color = undefined;
+ item.children.forEach(nodeId => {
+ const node = app.graph.getNodeById(nodeId);
+ if (node) {
+ node.color = undefined;
+ node.bgcolor = undefined;
+ if (node.setDirtyCanvas) node.setDirtyCanvas(true);
+ }
+ });
+ }
+ });
+
+ // 刷新画布
+ app.graph.setDirtyCanvas(true, true);
+ if (app.graph.afterChange) app.graph.afterChange();
+ } catch (error) {
+ console.error("颜色重置失败:", error);
+ }
+ },
// 2025-04-28 18:44:47 ================打开原生颜色选择器==========================
openNativeColorPicker() {
@@ -780,25 +846,38 @@ const ButtonManager = {
{ id: 'colorCyan', svg: this.createColorCircle('cyan'), action: (e) => this.setNodesColor(e, 'cyan') },
{ id: 'colorBlue', svg: this.createColorCircle('blue'), action: (e) => this.setNodesColor(e, 'blue') },
{ id: 'colorPurple', svg: this.createColorCircle('purple'), action: (e) => this.setNodesColor(e, 'purple') },
- { id: 'colorClear', svg: this.createColorCircle('clear'), action: (e) => this.setNodesColor(e, 'clear') },
+ // {
+ // id: 'colorReset',
+ // svg: ``,
+ // action: this.resetNodesColor.bind(this)
+ // },
+
+ { id: 'colorClear', svg: this.createColorCircle('clear'), action: this.resetNodesColor.bind(this) },
+ // { id: 'colorClear', svg: this.createColorCircle('clear'), action: (e) => this.setNodesColor(e, 'clear') },
{ id: 'colorCustom', svg: this.createColorPickerIcon(), action: () => this.openNativeColorPicker() },
{ id: 'moveElement', svg: moveElementSvg },
];
},
- // 显示右键菜单
+ // ================================显示右键菜单=============================
+
showContextMenu() {
// 创建右键菜单元素
this.contextMenu = document.createElement('div');
this.contextMenu.id = 'context-menu';
this.contextMenu.style.display = 'none'; // 初始设置为不显示
-
+
/* ↓若需加提示文字,请把此注释加到常驻显示button前: 显示模式: */
// ↓2025-04-28 17:20:25 ArtsticH新增 配色按钮组
this.contextMenu.innerHTML = `
+
+
-
-
+
+
`;
@@ -864,7 +943,19 @@ const ButtonManager = {
this.isPermanent = false;
localStorage.setItem('NodeAlignerIsPermanent', '0');
});
+
+
+ // 2025-04-30 00:56:39 ==================添加UI缩放按钮事件==开始===================
+ this.contextMenu.querySelector('#ui-scale-btn').addEventListener('click', (e) => {
+ this.contextMenu.querySelector('#ui-scale-btn').addEventListener('click', (e) => {
+ // 检测Ctrl键是否按下
+ this.systemWideZoom = e.ctrlKey;
+ this.toggleUIScale();
+ });
+ });
+ // 2025-04-30 00:56:39 ==================添加UI缩放按钮事件==结束===================
},
+
// 显示按钮
show() {
this.isShow = true;
@@ -880,6 +971,31 @@ const ButtonManager = {
this.buttonContainer.style.left = `${x}px`;
this.buttonContainer.style.top = `${y}px`;
},
+
+ // =============================UI缩放==开始====================
+ // 添加缩放方法
+ toggleUIScale() {
+ // 新的循环逻辑:1→1.5→2→0.5→1
+ this.currentZoomIndex = (this.currentZoomIndex + 1) % 4;
+ const scale = this.zoomLevels[this.currentZoomIndex];
+
+ // 此时systemWideZoom来自点击事件中的e.ctrlKey
+ if (this.systemWideZoom) {
+ // 系统级缩放
+ document.body.style.zoom = scale;
+ this.buttonContainer.style.transform = '';
+ } else {
+ // 仅缩放插件容器
+ this.buttonContainer.style.transform = `scale(${scale})`;
+ document.body.style.zoom = '';
+
+ // 更新按钮文本
+ this.contextMenu.querySelector('#ui-scale-btn').textContent = `UI缩放 ${this.zoomLevels[this.currentZoomIndex]}x`;
+ }
+ },
+
+ // =============================UI缩放==结束====================
+
// 开始拖拽-2025-04-28 02:54:54修正
onDragStart(e) {
// 2025-04-28 01:39:38 新增-修正后的 onDragStart 方法
@@ -946,101 +1062,113 @@ const ButtonManager = {
this.buttonContainer.style.top = `${newTop}px`;
}
},
+
+
+
+// ======================== 新增位置验证方法 ========================
+validateAndAdjustPosition(pos) {
+ const containerRect = this.buttonContainer.getBoundingClientRect();
+ const windowWidth = window.innerWidth;
+ const windowHeight = window.innerHeight;
+
+ // 计算安全边界(考虑元素自身尺寸)
+ const safeLeft = Math.max(0, Math.min(pos.left, windowWidth - containerRect.width));
+ const safeTop = Math.max(0, Math.min(pos.top, windowHeight - containerRect.height));
+
+ // 如果计算结果与原始值偏差超过20px则认为需要重置位置
+ if (Math.abs(pos.left - safeLeft) > 20 || Math.abs(pos.top - safeTop) > 20) {
+ return this.getCentralPosition();
+ }
+
+ return { left: safeLeft, top: safeTop };
+},
+
+// ======================== 获取中间靠上位置 ========================
+getCentralPosition() {
+ return {
+ left: Math.max(0, window.innerWidth/2 - this.buttonContainer.offsetWidth/2),
+ top: 20
+ };
+},
+
+
+
// 结束拖拽
- onDragEnd() {
- this.isDragging = false;
- // 移除事件监听器
- document.removeEventListener('mousemove', this.onDragging);
- document.removeEventListener('mouseup', this.onDragEnd);
+// ======================== 修改后的 onDragEnd 方法 ========================
+onDragEnd() {
+ this.isDragging = false;
+ document.removeEventListener('mousemove', this.boundOnDragging);
+ document.removeEventListener('mouseup', this.boundOnDragEnd);
- // 获取按钮容器的位置信息
- const rect = this.buttonContainer.getBoundingClientRect();
- const windowWidth = window.innerWidth;
- const windowHeight = window.innerHeight;
+ // 获取当前实际位置
+ const rect = this.buttonContainer.getBoundingClientRect();
+ const originalPos = {
+ left: rect.left,
+ top: rect.top
+ };
- // 计算距离四个边的距离
- const distanceToTop = rect.top;
- const distanceToBottom = windowHeight - rect.bottom;
- const distanceToLeft = rect.left;
- const distanceToRight = windowWidth - rect.right;
+ // 验证并调整位置
+ const safePos = this.validateAndAdjustPosition(originalPos);
+
+ // 应用调整后的位置
+ this.buttonContainer.style.left = `${safePos.left}px`;
+ this.buttonContainer.style.top = `${safePos.top}px`;
- // 选择两个最近的边
- let top = 'unset';
- let bottom = 'unset';
- let left = 'unset';
- let right = 'unset';
+ // 保存安全位置
+ localStorage.setItem('NodeAlignerButtonContainerPosition', JSON.stringify({
+ left: safePos.left,
+ top: safePos.top
+ }));
- if (distanceToTop < distanceToBottom) {
- top = `${distanceToTop}px`;
- } else {
- bottom = `${distanceToBottom}px`;
- }
+ // 恢复自适应宽度
+ this.buttonContainer.style.width = 'fit-content';
+},
- if (distanceToLeft < distanceToRight) {
- left = `${distanceToLeft}px`;
- } else {
- right = `${distanceToRight}px`;
- }
-
- // 更新样式使其根据距离四边的情况固定
- this.buttonContainer.style.top = top;
- this.buttonContainer.style.bottom = bottom;
- this.buttonContainer.style.left = left;
- this.buttonContainer.style.right = right;
-
- // 2025-04-29 16:36:27 恢复自适应宽度
- this.buttonContainer.style.width = 'fit-content';
-
- // 保存位置到 localStorage
- localStorage.setItem('NodeAlignerButtonContainerPosition', JSON.stringify({ top, left, right, bottom }));
- },
// 恢复位置
- restorePosition() {
- try {
- const savedPosition = JSON.parse(localStorage.getItem('NodeAlignerButtonContainerPosition'));
- if (savedPosition && typeof savedPosition === 'object') {
- this.buttonContainer.style.top = savedPosition.top || '20px';
- this.buttonContainer.style.bottom = savedPosition.bottom || 'unset';
- this.buttonContainer.style.left = savedPosition.left || 'unset';
- this.buttonContainer.style.right = savedPosition.right || '20px';
- } else {
- this.setDefaultPosition();
- }
- } catch (e) {
- console.warn('Failed to parse saved position:', e);
- this.setDefaultPosition();
+// ======================== 修改后的 restorePosition 方法 ========================
+restorePosition() {
+ try {
+ const savedPosition = JSON.parse(localStorage.getItem('NodeAlignerButtonContainerPosition'));
+ if (!savedPosition) {
+ this.setCentralPosition();
+ return;
}
- // ===== 在这里检测是否超出屏幕边界 =====
- const containerRect = this.buttonContainer.getBoundingClientRect();
- const windowWidth = window.innerWidth;
- const windowHeight = window.innerHeight;
+ // 初始验证
+ let pos = {
+ left: savedPosition.left || window.innerWidth/2 - this.buttonContainer.offsetWidth/2,
+ top: savedPosition.top || 20
+ };
+
+ // 二次验证
+ const validatedPos = this.validateAndAdjustPosition(pos);
+
+ // 应用验证后的位置
+ this.buttonContainer.style.left = `${validatedPos.left}px`;
+ this.buttonContainer.style.top = `${validatedPos.top}px`;
+
+ // 强制更新存储
+ localStorage.setItem('NodeAlignerButtonContainerPosition', JSON.stringify(validatedPos));
+
+ } catch (e) {
+ console.warn('位置信息异常,重置到默认位置:', e);
+ this.setCentralPosition();
+ }
+},
+
+
+// ======================== 修改默认位置设置 ========================
+setCentralPosition() {
+ const pos = this.getCentralPosition();
+ this.buttonContainer.style.left = `${pos.left}px`;
+ this.buttonContainer.style.top = `${pos.top}px`;
+ localStorage.setItem('NodeAlignerButtonContainerPosition', JSON.stringify(pos));
+},
+
+
+
- if (
- containerRect.left < 0 ||
- containerRect.top < 0 ||
- containerRect.right > windowWidth ||
- containerRect.bottom > windowHeight
- ) {
- console.log('NodeAligner位置已超出屏幕范围,重置为默认位置');
- // 调用setDefaultPosition重置位置
- this.setDefaultPosition();
- // 保存默认位置到 localStorage,确保下次进入不会越界
- localStorage.setItem('NodeAlignerButtonContainerPosition', JSON.stringify({
- top: this.buttonContainer.style.top,
- left: this.buttonContainer.style.left,
- right: this.buttonContainer.style.right,
- bottom: this.buttonContainer.style.bottom
- }));
- }
- },
- setDefaultPosition() {
- this.buttonContainer.style.top = '20px';
- this.buttonContainer.style.right = '20px';
- this.buttonContainer.style.bottom = 'unset';
- this.buttonContainer.style.left = 'unset';
- },
// 获取当前选中的节点
getSelectedNodes() {
if (!LGraphCanvas.active_canvas) return [];