mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-06 08:00:05 +00:00
[Bug] Fix zoom lag of DOM widget (#3714)
This commit is contained in:
@@ -9,7 +9,9 @@ test.describe('Load Workflow in Media', () => {
|
||||
'no_workflow.webp',
|
||||
'large_workflow.webp',
|
||||
'workflow.webm',
|
||||
'workflow.glb',
|
||||
// Skipped due to 3d widget unstable visual result.
|
||||
// 3d widget shows grid after fully loaded.
|
||||
// 'workflow.glb',
|
||||
'workflow.mp4',
|
||||
'workflow.mov',
|
||||
'workflow.m4v',
|
||||
|
||||
@@ -187,7 +187,10 @@ test.describe('Image widget', () => {
|
||||
})
|
||||
|
||||
test.describe('Animated image widget', () => {
|
||||
test('Shows preview of uploaded animated image', async ({ comfyPage }) => {
|
||||
// https://github.com/Comfy-Org/ComfyUI_frontend/issues/3718
|
||||
test.skip('Shows preview of uploaded animated image', async ({
|
||||
comfyPage
|
||||
}) => {
|
||||
await comfyPage.loadWorkflow('widgets/load_animated_webp')
|
||||
|
||||
// Get position of the load animated webp node
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useEventListener } from '@vueuse/core'
|
||||
import { useElementBounding, useEventListener } from '@vueuse/core'
|
||||
import { CSSProperties, computed, onMounted, ref, watch } from 'vue'
|
||||
|
||||
import { useAbsolutePosition } from '@/composables/element/useAbsolutePosition'
|
||||
@@ -38,18 +38,16 @@ const emit = defineEmits<{
|
||||
|
||||
const widgetElement = ref<HTMLElement | undefined>()
|
||||
|
||||
/**
|
||||
* @note Do NOT convert style to a computed value, as it will cause lag when
|
||||
* updating the style on different animation frames. Vue's computed value is
|
||||
* evaluated asynchronously.
|
||||
*/
|
||||
const style = ref<CSSProperties>({})
|
||||
const { style: positionStyle, updatePosition } = useAbsolutePosition({
|
||||
useTransform: true
|
||||
})
|
||||
const { style: clippingStyle, updateClipPath } = useDomClipping()
|
||||
const style = computed<CSSProperties>(() => ({
|
||||
...positionStyle.value,
|
||||
...(enableDomClipping.value ? clippingStyle.value : {}),
|
||||
zIndex: widgetState.zIndex,
|
||||
pointerEvents:
|
||||
widgetState.readonly || widget.computedDisabled ? 'none' : 'auto',
|
||||
opacity: widget.computedDisabled ? 0.5 : 1
|
||||
}))
|
||||
|
||||
const canvasStore = useCanvasStore()
|
||||
const settingStore = useSettingStore()
|
||||
@@ -88,13 +86,28 @@ const updateDomClipping = () => {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @note mapping between canvas position and client position depends on the
|
||||
* canvas element's position, so we need to watch the canvas element's position
|
||||
* and update the position of the widget accordingly.
|
||||
*/
|
||||
const { left, top } = useElementBounding(canvasStore.getCanvas().canvas)
|
||||
watch(
|
||||
() => widgetState,
|
||||
(newState) => {
|
||||
updatePosition(newState)
|
||||
[() => widgetState, left, top],
|
||||
([widgetState, _, __]) => {
|
||||
updatePosition(widgetState)
|
||||
if (enableDomClipping.value) {
|
||||
updateDomClipping()
|
||||
}
|
||||
|
||||
style.value = {
|
||||
...positionStyle.value,
|
||||
...(enableDomClipping.value ? clippingStyle.value : {}),
|
||||
zIndex: widgetState.zIndex,
|
||||
pointerEvents:
|
||||
widgetState.readonly || widget.computedDisabled ? 'none' : 'auto',
|
||||
opacity: widget.computedDisabled ? 0.5 : 1
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Size, Vector2 } from '@comfyorg/litegraph'
|
||||
import { CSSProperties, computed, ref } from 'vue'
|
||||
import { CSSProperties, ref } from 'vue'
|
||||
|
||||
import { useCanvasPositionConversion } from '@/composables/element/useCanvasPositionConversion'
|
||||
import { useCanvasStore } from '@/stores/graphStore'
|
||||
@@ -23,13 +23,20 @@ export function useAbsolutePosition(options: { useTransform?: boolean } = {}) {
|
||||
lgCanvas
|
||||
)
|
||||
|
||||
const position = ref<PositionConfig>({
|
||||
pos: [0, 0],
|
||||
size: [0, 0]
|
||||
})
|
||||
/**
|
||||
* @note Do NOT convert style to a computed value, as it will cause lag when
|
||||
* updating the style on different animation frames. Vue's computed value is
|
||||
* evaluated asynchronously.
|
||||
*/
|
||||
const style = ref<CSSProperties>({})
|
||||
|
||||
const style = computed<CSSProperties>(() => {
|
||||
const { pos, size, scale = lgCanvas.ds.scale } = position.value
|
||||
/**
|
||||
* Compute the style of the element based on the position and size.
|
||||
*
|
||||
* @param position
|
||||
*/
|
||||
const computeStyle = (position: PositionConfig): CSSProperties => {
|
||||
const { pos, size, scale = lgCanvas.ds.scale } = position
|
||||
const [left, top] = canvasPosToClientPos(pos)
|
||||
const [width, height] = size
|
||||
|
||||
@@ -50,7 +57,7 @@ export function useAbsolutePosition(options: { useTransform?: boolean } = {}) {
|
||||
width: `${width * scale}px`,
|
||||
height: `${height * scale}px`
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the position of the element on the litegraph canvas.
|
||||
@@ -58,7 +65,7 @@ export function useAbsolutePosition(options: { useTransform?: boolean } = {}) {
|
||||
* @param config
|
||||
*/
|
||||
const updatePosition = (config: PositionConfig) => {
|
||||
position.value = config
|
||||
style.value = computeStyle(config)
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user