mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 06:20:11 +00:00
[backport core/1.40] fix: cache canvas cursor style to avoid redundant DOM writes (#9604)
Backport of #9171 to `core/1.40` Automatically created by backport workflow. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9604-backport-core-1-40-fix-cache-canvas-cursor-style-to-avoid-redundant-DOM-writes-31d6d73d36508107ad71fc0ced9541e7) by [Unito](https://www.unito.io) Co-authored-by: Christian Byrne <cbyrne@comfy.org>
This commit is contained in:
@@ -11,6 +11,7 @@ import { forEachNode } from '@/utils/graphTraversalUtil'
|
||||
|
||||
import { CanvasPointer } from './CanvasPointer'
|
||||
import type { ContextMenu } from './ContextMenu'
|
||||
import { createCursorCache } from './cursorCache'
|
||||
import { DragAndScale } from './DragAndScale'
|
||||
import type { AnimationOptions } from './DragAndScale'
|
||||
import type { LGraph } from './LGraph'
|
||||
@@ -363,6 +364,8 @@ export class LGraphCanvas implements CustomEventDispatcher<LGraphCanvasEventMap>
|
||||
this.canvas.dispatchEvent(new CustomEvent(type, { detail }))
|
||||
}
|
||||
|
||||
private _setCursor!: ReturnType<typeof createCursorCache>
|
||||
|
||||
private _updateCursorStyle() {
|
||||
if (!this.state.shouldSetCursor) return
|
||||
|
||||
@@ -385,7 +388,7 @@ export class LGraphCanvas implements CustomEventDispatcher<LGraphCanvasEventMap>
|
||||
cursor = 'grab'
|
||||
}
|
||||
|
||||
this.canvas.style.cursor = cursor
|
||||
this._setCursor(cursor)
|
||||
}
|
||||
|
||||
// Whether the canvas was previously being dragged prior to pressing space key.
|
||||
@@ -1910,6 +1913,7 @@ export class LGraphCanvas implements CustomEventDispatcher<LGraphCanvasEventMap>
|
||||
this.pointer.element = element
|
||||
|
||||
if (!element) return
|
||||
this._setCursor = createCursorCache(element)
|
||||
|
||||
// TODO: classList.add
|
||||
element.className += ' lgraphcanvas'
|
||||
@@ -2969,7 +2973,7 @@ export class LGraphCanvas implements CustomEventDispatcher<LGraphCanvasEventMap>
|
||||
}
|
||||
|
||||
// Set appropriate cursor for resize direction
|
||||
this.canvas.style.cursor = cursors[resizeDirection]
|
||||
this._setCursor(cursors[resizeDirection])
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
59
src/lib/litegraph/src/cursorCache.test.ts
Normal file
59
src/lib/litegraph/src/cursorCache.test.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { createCursorCache } from './cursorCache'
|
||||
|
||||
function createMockElement() {
|
||||
let cursorValue = ''
|
||||
const setter = vi.fn((value: string) => {
|
||||
cursorValue = value
|
||||
})
|
||||
|
||||
const element = document.createElement('div')
|
||||
Object.defineProperty(element.style, 'cursor', {
|
||||
get: () => cursorValue,
|
||||
set: setter
|
||||
})
|
||||
|
||||
return { element, setter }
|
||||
}
|
||||
|
||||
describe('createCursorCache', () => {
|
||||
it('should only write to DOM when cursor value changes', () => {
|
||||
const { element, setter } = createMockElement()
|
||||
const setCursor = createCursorCache(element)
|
||||
|
||||
setCursor('crosshair')
|
||||
setCursor('crosshair')
|
||||
setCursor('crosshair')
|
||||
|
||||
expect(setter).toHaveBeenCalledTimes(1)
|
||||
expect(setter).toHaveBeenCalledWith('crosshair')
|
||||
})
|
||||
|
||||
it('should write to DOM when cursor value differs', () => {
|
||||
const { element, setter } = createMockElement()
|
||||
const setCursor = createCursorCache(element)
|
||||
|
||||
setCursor('default')
|
||||
setCursor('crosshair')
|
||||
setCursor('grabbing')
|
||||
|
||||
expect(setter).toHaveBeenCalledTimes(3)
|
||||
expect(setter).toHaveBeenNthCalledWith(1, 'default')
|
||||
expect(setter).toHaveBeenNthCalledWith(2, 'crosshair')
|
||||
expect(setter).toHaveBeenNthCalledWith(3, 'grabbing')
|
||||
})
|
||||
|
||||
it('should skip repeated values interspersed with changes', () => {
|
||||
const { element, setter } = createMockElement()
|
||||
const setCursor = createCursorCache(element)
|
||||
|
||||
setCursor('default')
|
||||
setCursor('default')
|
||||
setCursor('grab')
|
||||
setCursor('grab')
|
||||
setCursor('default')
|
||||
|
||||
expect(setter).toHaveBeenCalledTimes(3)
|
||||
})
|
||||
})
|
||||
8
src/lib/litegraph/src/cursorCache.ts
Normal file
8
src/lib/litegraph/src/cursorCache.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export function createCursorCache(element: HTMLElement) {
|
||||
let lastCursor = ''
|
||||
return function setCursor(cursor: string) {
|
||||
if (cursor === lastCursor) return
|
||||
lastCursor = cursor
|
||||
element.style.cursor = cursor
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user