Skip to content

Commit e9d5ce7

Browse files
authored
selection rectangle for vueNodes (#7088)
## Summary fix: render selection rectangle in DOM layer for Vue nodes mode. When Vue nodes are enabled, the canvas selection rectangle was being rendered behind Vue node elements due to DOM stacking order (canvas layer is below the TransformPane layer). ## Changes - Adds a new SelectionRectangle.vue component that renders the selection box as a DOM element - Places it above the Vue nodes layer so it's always visible during drag selection - Skips canvas-based selection rectangle rendering when Vue nodes mode is active - Bonus: adds a semi-transparent blue fill style for better visibility ## Screenshots before https://github.com/user-attachments/assets/a8ee2ca3-00fd-4fdc-925a-dc9f846f4280 after https://github.com/user-attachments/assets/66b7f2f5-f0a0-486f-9556-3872d07d65be One more thing, the following improvement will be live selection, something like: https://github.com/user-attachments/assets/05a2b7ea-89b1-4568-bd2a-792f4fc11d8e but I don't want to increase this PR, so I will send live selection after this selection rectangle ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7088-selection-rectangle-for-vueNodes-2bd6d73d3650817aa2e9cf4526f179d8) by [Unito](https://www.unito.io)
1 parent 19d98a0 commit e9d5ce7

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

src/components/graph/GraphCanvas.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@
7777
/>
7878
</TransformPane>
7979

80+
<!-- Selection rectangle overlay for Vue nodes mode -->
81+
<SelectionRectangle v-if="shouldRenderVueNodes && comfyAppReady" />
82+
8083
<NodeTooltip v-if="tooltipEnabled" />
8184
<NodeSearchboxPopover ref="nodeSearchboxPopoverRef" />
8285

@@ -159,6 +162,7 @@ import { useWorkspaceStore } from '@/stores/workspaceStore'
159162
import { isNativeWindow } from '@/utils/envUtil'
160163
161164
import TryVueNodeBanner from '../topbar/TryVueNodeBanner.vue'
165+
import SelectionRectangle from './SelectionRectangle.vue'
162166
163167
const emit = defineEmits<{
164168
ready: []
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<template>
2+
<div
3+
v-if="isVisible"
4+
class="pointer-events-none absolute border border-blue-400 bg-blue-500/20"
5+
:style="rectangleStyle"
6+
/>
7+
</template>
8+
9+
<script setup lang="ts">
10+
import { useRafFn } from '@vueuse/core'
11+
import { computed, ref } from 'vue'
12+
13+
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
14+
15+
const canvasStore = useCanvasStore()
16+
17+
const selectionRect = ref<{
18+
x: number
19+
y: number
20+
w: number
21+
h: number
22+
} | null>(null)
23+
24+
useRafFn(() => {
25+
const canvas = canvasStore.canvas
26+
if (!canvas) {
27+
selectionRect.value = null
28+
return
29+
}
30+
31+
const { pointer, dragging_rectangle } = canvas
32+
33+
if (dragging_rectangle && pointer.eDown && pointer.eMove) {
34+
const x = pointer.eDown.safeOffsetX
35+
const y = pointer.eDown.safeOffsetY
36+
const w = pointer.eMove.safeOffsetX - x
37+
const h = pointer.eMove.safeOffsetY - y
38+
39+
selectionRect.value = { x, y, w, h }
40+
} else {
41+
selectionRect.value = null
42+
}
43+
})
44+
45+
const isVisible = computed(() => selectionRect.value !== null)
46+
47+
const rectangleStyle = computed(() => {
48+
const rect = selectionRect.value
49+
if (!rect) return {}
50+
51+
const left = rect.w >= 0 ? rect.x : rect.x + rect.w
52+
const top = rect.h >= 0 ? rect.y : rect.y + rect.h
53+
const width = Math.abs(rect.w)
54+
const height = Math.abs(rect.h)
55+
56+
return {
57+
left: `${left}px`,
58+
top: `${top}px`,
59+
width: `${width}px`,
60+
height: `${height}px`
61+
}
62+
})
63+
</script>

src/lib/litegraph/src/LGraphCanvas.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4799,7 +4799,8 @@ export class LGraphCanvas
47994799
}
48004800

48014801
// Area-selection rectangle
4802-
if (this.dragging_rectangle) {
4802+
// In Vue nodes mode, selection rectangle is rendered in DOM layer
4803+
if (this.dragging_rectangle && !LiteGraph.vueNodesMode) {
48034804
const { eDown, eMove } = this.pointer
48044805
ctx.strokeStyle = '#FFF'
48054806

0 commit comments

Comments
 (0)