mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-29 08:58:53 -03:00
fix: wheel zoom behavior for LoRA Manager widgets
- Add forwardWheelToCanvas() utility for vanilla JS widgets - Implement wheel event handling in Vue widgets (LoraCyclerWidget, LoraRandomizerWidget, LoraPoolWidget) - Update SingleSlider and DualRangeSlider to stop event propagation after value adjustment - Ensure consistent behavior: slider adjusts value only, other areas trigger canvas zoom - Support pinch-to-zoom (Ctrl+wheel) and horizontal scroll forwarding
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="lora-cycler-widget">
|
||||
<div class="lora-cycler-widget" @wheel="onWheel">
|
||||
<LoraCyclerSettingsView
|
||||
:current-index="state.currentIndex.value"
|
||||
:total-count="displayTotalCount"
|
||||
@@ -257,6 +257,53 @@ const handleResetIndex = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse wheel events on the widget.
|
||||
* Forwards the event to the ComfyUI canvas for zooming when appropriate.
|
||||
*/
|
||||
const onWheel = (event: WheelEvent) => {
|
||||
// Check if the event originated from a slider component
|
||||
// Sliders have data-capture-wheel="true" attribute
|
||||
const target = event.target as HTMLElement
|
||||
if (target?.closest('[data-capture-wheel="true"]')) {
|
||||
// Event is from a slider, slider already handled it
|
||||
// Just stop propagation to prevent canvas zoom
|
||||
event.stopPropagation()
|
||||
return
|
||||
}
|
||||
|
||||
// Access ComfyUI app from global window
|
||||
const app = (window as any).app
|
||||
if (!app || !app.canvas || typeof app.canvas.processMouseWheel !== 'function') {
|
||||
return
|
||||
}
|
||||
|
||||
const deltaX = event.deltaX
|
||||
const deltaY = event.deltaY
|
||||
const isHorizontal = Math.abs(deltaX) > Math.abs(deltaY)
|
||||
|
||||
// 1. Handle pinch-to-zoom (ctrlKey is true for pinch-to-zoom on most browsers)
|
||||
if (event.ctrlKey) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
app.canvas.processMouseWheel(event)
|
||||
return
|
||||
}
|
||||
|
||||
// 2. Horizontal scroll: pass to canvas (widgets usually don't scroll horizontally)
|
||||
if (isHorizontal) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
app.canvas.processMouseWheel(event)
|
||||
return
|
||||
}
|
||||
|
||||
// 3. Vertical scrolling: forward to canvas
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
app.canvas.processMouseWheel(event)
|
||||
}
|
||||
|
||||
// Check for pool config changes
|
||||
const checkPoolConfigChanges = async () => {
|
||||
if (!isMounted.value) return
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="lora-pool-widget">
|
||||
<div class="lora-pool-widget" @wheel="onWheel">
|
||||
<!-- Summary View -->
|
||||
<LoraPoolSummaryView
|
||||
:selected-base-models="state.selectedBaseModels.value"
|
||||
@@ -99,6 +99,53 @@ const openModal = (modal: ModalType) => {
|
||||
modalState.openModal(modal)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse wheel events on the widget.
|
||||
* Forwards the event to the ComfyUI canvas for zooming when appropriate.
|
||||
*/
|
||||
const onWheel = (event: WheelEvent) => {
|
||||
// Check if the event originated from a slider component
|
||||
// Sliders have data-capture-wheel="true" attribute
|
||||
const target = event.target as HTMLElement
|
||||
if (target?.closest('[data-capture-wheel="true"]')) {
|
||||
// Event is from a slider, slider already handled it
|
||||
// Just stop propagation to prevent canvas zoom
|
||||
event.stopPropagation()
|
||||
return
|
||||
}
|
||||
|
||||
// Access ComfyUI app from global window
|
||||
const app = (window as any).app
|
||||
if (!app || !app.canvas || typeof app.canvas.processMouseWheel !== 'function') {
|
||||
return
|
||||
}
|
||||
|
||||
const deltaX = event.deltaX
|
||||
const deltaY = event.deltaY
|
||||
const isHorizontal = Math.abs(deltaX) > Math.abs(deltaY)
|
||||
|
||||
// 1. Handle pinch-to-zoom (ctrlKey is true for pinch-to-zoom on most browsers)
|
||||
if (event.ctrlKey) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
app.canvas.processMouseWheel(event)
|
||||
return
|
||||
}
|
||||
|
||||
// 2. Horizontal scroll: pass to canvas (widgets usually don't scroll horizontally)
|
||||
if (isHorizontal) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
app.canvas.processMouseWheel(event)
|
||||
return
|
||||
}
|
||||
|
||||
// 3. Vertical scrolling: forward to canvas
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
app.canvas.processMouseWheel(event)
|
||||
}
|
||||
|
||||
// Lifecycle
|
||||
onMounted(async () => {
|
||||
// Setup callback for external value updates (e.g., workflow load, undo/redo)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="lora-randomizer-widget">
|
||||
<div class="lora-randomizer-widget" @wheel="onWheel">
|
||||
<LoraRandomizerSettingsView
|
||||
:count-mode="state.countMode.value"
|
||||
:count-fixed="state.countFixed.value"
|
||||
@@ -154,6 +154,53 @@ const handleReuseLast = () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse wheel events on the widget.
|
||||
* Forwards the event to the ComfyUI canvas for zooming when appropriate.
|
||||
*/
|
||||
const onWheel = (event: WheelEvent) => {
|
||||
// Check if the event originated from a slider component
|
||||
// Sliders have data-capture-wheel="true" attribute
|
||||
const target = event.target as HTMLElement
|
||||
if (target?.closest('[data-capture-wheel="true"]')) {
|
||||
// Event is from a slider, slider already handled it
|
||||
// Just stop propagation to prevent canvas zoom
|
||||
event.stopPropagation()
|
||||
return
|
||||
}
|
||||
|
||||
// Access ComfyUI app from global window
|
||||
const app = (window as any).app
|
||||
if (!app || !app.canvas || typeof app.canvas.processMouseWheel !== 'function') {
|
||||
return
|
||||
}
|
||||
|
||||
const deltaX = event.deltaX
|
||||
const deltaY = event.deltaY
|
||||
const isHorizontal = Math.abs(deltaX) > Math.abs(deltaY)
|
||||
|
||||
// 1. Handle pinch-to-zoom (ctrlKey is true for pinch-to-zoom on most browsers)
|
||||
if (event.ctrlKey) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
app.canvas.processMouseWheel(event)
|
||||
return
|
||||
}
|
||||
|
||||
// 2. Horizontal scroll: pass to canvas (widgets usually don't scroll horizontally)
|
||||
if (isHorizontal) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
app.canvas.processMouseWheel(event)
|
||||
return
|
||||
}
|
||||
|
||||
// 3. Vertical scrolling: forward to canvas
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
app.canvas.processMouseWheel(event)
|
||||
}
|
||||
|
||||
// Watch for changes to the loras widget to track current loras
|
||||
watch(() => props.node.widgets?.find((w: any) => w.name === 'loras')?.value, (newVal) => {
|
||||
// Only update after component is mounted
|
||||
|
||||
@@ -280,8 +280,7 @@ const onWheel = (event: WheelEvent) => {
|
||||
if (event.clientX < rootRect.left || event.clientX > rootRect.right ||
|
||||
event.clientY < rootRect.top || event.clientY > rootRect.bottom) return
|
||||
|
||||
event.preventDefault()
|
||||
|
||||
// Adjust slider values when wheeling over the slider area
|
||||
const delta = event.deltaY > 0 ? -1 : 1
|
||||
const relativeX = event.clientX - rect.left
|
||||
const rangeWidth = rect.width
|
||||
@@ -320,6 +319,9 @@ const onWheel = (event: WheelEvent) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop propagation to prevent canvas zoom
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
const stopDrag = (event?: PointerEvent) => {
|
||||
|
||||
@@ -131,11 +131,13 @@ const onWheel = (event: WheelEvent) => {
|
||||
if (event.clientX < rootRect.left || event.clientX > rootRect.right ||
|
||||
event.clientY < rootRect.top || event.clientY > rootRect.bottom) return
|
||||
|
||||
event.preventDefault()
|
||||
|
||||
// Adjust slider value when wheeling over the slider area
|
||||
const delta = event.deltaY > 0 ? -1 : 1
|
||||
const newValue = snapToStep(props.value + delta * props.step)
|
||||
emit('update:value', newValue)
|
||||
|
||||
// Stop propagation to prevent canvas zoom
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
const stopDrag = (event?: PointerEvent) => {
|
||||
|
||||
Reference in New Issue
Block a user