mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-04 07:00:23 +00:00
(feature) animateToNode method
This commit is contained in:
@@ -115,6 +115,14 @@ export interface LGraphCanvasState {
|
||||
readOnly: boolean
|
||||
}
|
||||
|
||||
/** Easing functions for canvas animations */
|
||||
const easeFunctions = {
|
||||
linear: (t: number) => t,
|
||||
easeInQuad: (t: number) => t * t,
|
||||
easeOutQuad: (t: number) => t * (2 - t),
|
||||
easeInOutQuad: (t: number) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t)
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is in charge of rendering one graph inside a canvas. And provides all the interaction required.
|
||||
* Valid callbacks are: onNodeSelected, onNodeDeselected, onShowNodePanel, onNodeDblClicked
|
||||
@@ -3291,6 +3299,71 @@ export class LGraphCanvas {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Centers the camera on a given node (animated version)
|
||||
* @method animateToNode
|
||||
**/
|
||||
animateToNode(node: LGraphNode, duration: number = 350, zoom: number = 0.75, easing: string = 'easeInOutQuad') {
|
||||
let animationId = null
|
||||
const startTimestamp = performance.now()
|
||||
const startX = this.ds.offset[0]
|
||||
const startY = this.ds.offset[1]
|
||||
const startScale = this.ds.scale
|
||||
const cw = this.canvas.width / window.devicePixelRatio
|
||||
const ch = this.canvas.height / window.devicePixelRatio
|
||||
|
||||
let targetScale = startScale
|
||||
let targetX = startX
|
||||
let targetY = startY
|
||||
|
||||
if (zoom > 0) {
|
||||
const targetScaleX = (zoom * cw) / Math.max(node.size[0], 300)
|
||||
const targetScaleY = (zoom * ch) / Math.max(node.size[1], 300)
|
||||
|
||||
// Choose the smaller scale to ensure the node fits into the viewport
|
||||
// Ensure we don't go over the max scale
|
||||
targetScale = Math.min(targetScaleX, targetScaleY, this.ds.max_scale)
|
||||
targetX = -node.pos[0] - node.size[0] * 0.5 + (cw * 0.5) / targetScale
|
||||
targetY = -node.pos[1] - node.size[1] * 0.5 + (ch * 0.5) / targetScale
|
||||
} else {
|
||||
targetX = -node.pos[0] - node.size[0] * 0.5 + (cw * 0.5) / targetScale
|
||||
targetY = -node.pos[1] - node.size[1] * 0.5 + (ch * 0.5) / targetScale
|
||||
}
|
||||
|
||||
const easeFunction = easeFunctions[easing] || easeFunctions.linear
|
||||
|
||||
const animate = (timestamp: number) => {
|
||||
const elapsed = timestamp - startTimestamp
|
||||
const progress = Math.min(elapsed / duration, 1)
|
||||
const easedProgress = easeFunction(progress)
|
||||
|
||||
this.ds.offset[0] = startX + (targetX - startX) * easedProgress
|
||||
this.ds.offset[1] = startY + (targetY - startY) * easedProgress
|
||||
|
||||
if (zoom > 0) {
|
||||
this.ds.scale = startScale + (targetScale - startScale) * easedProgress
|
||||
}
|
||||
|
||||
this.setDirty(true, true)
|
||||
|
||||
if (this.onPositionChanged) {
|
||||
this.onPositionChanged({
|
||||
x: this.ds.offset[0],
|
||||
y: this.ds.offset[1]
|
||||
})
|
||||
}
|
||||
|
||||
if (progress < 1) {
|
||||
animationId = requestAnimationFrame(animate)
|
||||
} else {
|
||||
cancelAnimationFrame(animationId)
|
||||
}
|
||||
}
|
||||
|
||||
animationId = requestAnimationFrame(animate)
|
||||
}
|
||||
|
||||
/**
|
||||
* adds some useful properties to a mouse event, like the position in graph coordinates
|
||||
**/
|
||||
|
||||
Reference in New Issue
Block a user