Skip to content

Commit 585d52e

Browse files
huchenleigithub-actions
andauthored
[Bug] Fix DOM widgets position when canvas bounding box change (#3565)
Co-authored-by: github-actions <[email protected]>
1 parent b753575 commit 585d52e

File tree

7 files changed

+86
-82
lines changed

7 files changed

+86
-82
lines changed

browser_tests/tests/domWidget.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,11 @@ test.describe('DOM Widget', () => {
2424
await expect(firstMultiline).not.toBeVisible()
2525
await expect(lastMultiline).not.toBeVisible()
2626
})
27+
28+
test('Position update when entering focus mode', async ({ comfyPage }) => {
29+
await comfyPage.setSetting('Comfy.UseNewMenu', 'Top')
30+
await comfyPage.executeCommand('Workspace.ToggleFocusMode')
31+
await comfyPage.nextFrame()
32+
await expect(comfyPage.canvas).toHaveScreenshot('focus-mode-on.png')
33+
})
2734
})
83 KB
Loading

src/components/graph/DomWidgets.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ watch(
7373
updateWidgets()
7474
}
7575
)
76-
}
76+
},
77+
{ immediate: true }
7778
)
7879
</script>

src/components/graph/GraphCanvas.vue

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,27 @@
1919
<GraphCanvasMenu v-if="canvasMenuEnabled" class="pointer-events-auto" />
2020
</template>
2121
</LiteGraphCanvasSplitterOverlay>
22-
<TitleEditor />
2322
<GraphCanvasMenu v-if="!betaMenuEnabled && canvasMenuEnabled" />
2423
<canvas
2524
id="graph-canvas"
2625
ref="canvasRef"
2726
tabindex="1"
2827
class="w-full h-full touch-none"
2928
/>
30-
<NodeSearchboxPopover />
31-
<SelectionOverlay v-if="selectionToolboxEnabled">
32-
<SelectionToolbox />
33-
</SelectionOverlay>
34-
<NodeTooltip v-if="tooltipEnabled" />
29+
3530
<NodeBadge />
36-
<DomWidgets />
31+
<NodeTooltip v-if="tooltipEnabled" />
32+
<NodeSearchboxPopover />
33+
34+
<!-- Initialize components after comfyApp is ready. useAbsolutePosition requires
35+
canvasStore.canvas to be initialized. -->
36+
<template v-if="comfyAppReady">
37+
<TitleEditor />
38+
<SelectionOverlay v-if="selectionToolboxEnabled">
39+
<SelectionToolbox />
40+
</SelectionOverlay>
41+
<DomWidgets />
42+
</template>
3743
</template>
3844

3945
<script setup lang="ts">
@@ -78,7 +84,9 @@ import { useSettingStore } from '@/stores/settingStore'
7884
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
7985
import { useWorkspaceStore } from '@/stores/workspaceStore'
8086
81-
const emit = defineEmits(['ready'])
87+
const emit = defineEmits<{
88+
ready: []
89+
}>()
8290
const canvasRef = ref<HTMLCanvasElement | null>(null)
8391
const settingStore = useSettingStore()
8492
const nodeDefStore = useNodeDefStore()

src/components/graph/TitleEditor.vue

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import { LGraphGroup, LGraphNode, LiteGraph } from '@comfyorg/litegraph'
1717
import type { LiteGraphCanvasEvent } from '@comfyorg/litegraph'
1818
import { useEventListener } from '@vueuse/core'
19-
import { ref, watch } from 'vue'
19+
import { type CSSProperties, computed, ref, watch } from 'vue'
2020
2121
import EditableText from '@/components/common/EditableText.vue'
2222
import { useAbsolutePosition } from '@/composables/element/useAbsolutePosition'
@@ -28,7 +28,12 @@ const settingStore = useSettingStore()
2828
2929
const showInput = ref(false)
3030
const editedTitle = ref('')
31-
const { style: inputStyle, updatePosition } = useAbsolutePosition()
31+
const { style: inputPositionStyle, updatePosition } = useAbsolutePosition()
32+
const inputFontStyle = ref<CSSProperties>({})
33+
const inputStyle = computed<CSSProperties>(() => ({
34+
...inputPositionStyle.value,
35+
...inputFontStyle.value
36+
}))
3237
3338
const titleEditorStore = useTitleEditorStore()
3439
const canvasStore = useCanvasStore()
@@ -59,23 +64,19 @@ watch(
5964
6065
if (target instanceof LGraphGroup) {
6166
const group = target
62-
updatePosition(
63-
{
64-
pos: group.pos,
65-
size: [group.size[0], group.titleHeight]
66-
},
67-
{ fontSize: `${group.font_size * scale}px` }
68-
)
67+
updatePosition({
68+
pos: group.pos,
69+
size: [group.size[0], group.titleHeight]
70+
})
71+
inputFontStyle.value = { fontSize: `${group.font_size * scale}px` }
6972
} else if (target instanceof LGraphNode) {
7073
const node = target
7174
const [x, y] = node.getBounding()
72-
updatePosition(
73-
{
74-
pos: [x, y],
75-
size: [node.width, LiteGraph.NODE_TITLE_HEIGHT]
76-
},
77-
{ fontSize: `${12 * scale}px` }
78-
)
75+
updatePosition({
76+
pos: [x, y],
77+
size: [node.width, LiteGraph.NODE_TITLE_HEIGHT]
78+
})
79+
inputFontStyle.value = { fontSize: `${12 * scale}px` }
7980
}
8081
}
8182
)

src/components/graph/widgets/DomWidget.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,14 @@ const { widget, widgetState } = defineProps<{
3737
}>()
3838
3939
const emit = defineEmits<{
40-
(e: 'update:widgetValue', value: string | object): void
40+
'update:widgetValue': [value: string | object]
4141
}>()
4242
4343
const widgetElement = ref<HTMLElement | undefined>()
4444
45-
const { style: positionStyle, updatePositionWithTransform } =
46-
useAbsolutePosition()
45+
const { style: positionStyle, updatePosition } = useAbsolutePosition({
46+
useTransform: true
47+
})
4748
const { style: clippingStyle, updateClipPath } = useDomClipping()
4849
const style = computed<CSSProperties>(() => ({
4950
...positionStyle.value,
@@ -94,7 +95,7 @@ const updateDomClipping = () => {
9495
watch(
9596
() => widgetState,
9697
(newState) => {
97-
updatePositionWithTransform(newState)
98+
updatePosition(newState)
9899
if (enableDomClipping.value) {
99100
updateDomClipping()
100101
}
Lines changed: 39 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Size, Vector2 } from '@comfyorg/litegraph'
2-
import { CSSProperties, ref } from 'vue'
2+
import { CSSProperties, computed, ref } from 'vue'
33

4-
import { app } from '@/scripts/app'
4+
import { useCanvasPositionConversion } from '@/composables/element/useCanvasPositionConversion'
55
import { useCanvasStore } from '@/stores/graphStore'
66

77
export interface PositionConfig {
@@ -13,70 +13,56 @@ export interface PositionConfig {
1313
scale?: number
1414
}
1515

16-
export function useAbsolutePosition() {
16+
export function useAbsolutePosition(options: { useTransform?: boolean } = {}) {
17+
const { useTransform = false } = options
18+
1719
const canvasStore = useCanvasStore()
18-
const style = ref<CSSProperties>({
19-
position: 'fixed',
20-
left: '0px',
21-
top: '0px',
22-
width: '0px',
23-
height: '0px'
20+
const lgCanvas = canvasStore.getCanvas()
21+
const { canvasPosToClientPos } = useCanvasPositionConversion(
22+
lgCanvas.canvas,
23+
lgCanvas
24+
)
25+
26+
const position = ref<PositionConfig>({
27+
pos: [0, 0],
28+
size: [0, 0]
2429
})
2530

26-
/**
27-
* Update the position of the element on the litegraph canvas.
28-
*
29-
* @param config
30-
* @param extraStyle
31-
*/
32-
const updatePosition = (
33-
config: PositionConfig,
34-
extraStyle?: CSSProperties
35-
) => {
36-
const { pos, size, scale = canvasStore.canvas?.ds?.scale ?? 1 } = config
37-
const [left, top] = app.canvasPosToClientPos(pos)
31+
const style = computed<CSSProperties>(() => {
32+
const { pos, size, scale = lgCanvas.ds.scale } = position.value
33+
const [left, top] = canvasPosToClientPos(pos)
3834
const [width, height] = size
3935

40-
style.value = {
41-
...style.value,
42-
left: `${left}px`,
43-
top: `${top}px`,
44-
width: `${width * scale}px`,
45-
height: `${height * scale}px`,
46-
...extraStyle
47-
}
48-
}
36+
return useTransform
37+
? {
38+
position: 'fixed',
39+
transformOrigin: '0 0',
40+
transform: `scale(${scale})`,
41+
left: `${left}px`,
42+
top: `${top}px`,
43+
width: `${width}px`,
44+
height: `${height}px`
45+
}
46+
: {
47+
position: 'fixed',
48+
left: `${left}px`,
49+
top: `${top}px`,
50+
width: `${width * scale}px`,
51+
height: `${height * scale}px`
52+
}
53+
})
4954

5055
/**
51-
* Update the position and size of the element on the litegraph canvas,
52-
* with CSS transform scaling applied.
56+
* Update the position of the element on the litegraph canvas.
5357
*
5458
* @param config
55-
* @param extraStyle
5659
*/
57-
const updatePositionWithTransform = (
58-
config: PositionConfig,
59-
extraStyle?: CSSProperties
60-
) => {
61-
const { pos, size, scale = canvasStore.canvas?.ds?.scale ?? 1 } = config
62-
const [left, top] = app.canvasPosToClientPos(pos)
63-
const [width, height] = size
64-
65-
style.value = {
66-
...style.value,
67-
transformOrigin: '0 0',
68-
transform: `scale(${scale})`,
69-
left: `${left}px`,
70-
top: `${top}px`,
71-
width: `${width}px`,
72-
height: `${height}px`,
73-
...extraStyle
74-
}
60+
const updatePosition = (config: PositionConfig) => {
61+
position.value = config
7562
}
7663

7764
return {
7865
style,
79-
updatePosition,
80-
updatePositionWithTransform
66+
updatePosition
8167
}
8268
}

0 commit comments

Comments
 (0)