Nodes/ComfyUI_FunCode/Canvas Editor FunCode
ComfyUI Node

Canvas Editor FunCode

A real image editor sitting inside your workflow

By kaiery·Created 8 months ago·Updated about a month ago· 0
Canvas Editor FunCode
  • canvas_data
  • image

Most nodes process pixels automatically and hand you the result. Canvas Editor FunCode is the exception: it opens an actual image editor inside ComfyUI - a fabric.js canvas where you grab layers, drag them, scale, rotate, even warp them - and then hands the composite back to your graph as a normal image. It's a stop for the "I'll just nudge that into place by hand" step that no automatic pipeline gets right.

It's the second half of a two-node duo: Canvas Data FunCode packs a background and up to ten overlays into a canvas_data JSON blob, and this node opens that blob for editing. No Canvas Data upstream? The node still works - you get an empty black canvas and can add layers manually. But the intended flow is generated-or-loaded images in, hand-finished composite out.

How it works

The mechanism is a handshake between backend and browser. When the node runs, it posts the canvas payload to the frontend via ComfyUI's sync channel, which pushes it into the editor widget (or opens the editor) on your open tab. The node then waits up to 30 seconds for you to edit and click export. When you do, the frontend POSTs the canvas as a base64 PNG to /funcode/canvas_export, the backend decodes it into a tensor, and that tensor comes out the image socket.

The clever bit is IS_CHANGED: the node returns the canvas's last_update timestamp, so ComfyUI re-runs it - and pulls a fresh composite through your downstream Save/Preview nodes - whenever you edit the canvas, without you touching the Run button. That's the always-dirty idiom done right, used on purpose.

You can also save a canvas to ComfyUI/input/FunCodeCanvas/ and import saved ones back, so a composition survives between sessions.

Inputs and output

  • canvas_data (optional) - the JSON from Canvas Data FunCode. Leave it disconnected for a blank canvas.
  • Output: image, an IMAGE tensor you feed to a Preview, Save, or any downstream node. This is an output node, so the editor is what actually runs the graph.

There are also three layer-replacement policies that matter once you re-run with changed inputs: reset (default, new content resets the layer's transform), preserve_transform (keep position/scale even when content changes), and preserve_visual_size (keep the layer looking the same size when the canvas dimensions shift). If your layers keep snapping back to default after a re-run, preserve_transform is the switch you want.

Installing

cd ComfyUI/custom_nodes
git clone https://github.com/kaiery/ComfyUI_FunCode

Restart ComfyUI, and this lands under FunCode/Canvas. No model downloads; the one pip dependency in the pack (color-matcher) is unrelated to this node. The frontend half (the editor) is bundled in the pack's js/ folder and loads automatically - no separate install.

Common issues

  • Node returns nothing / no image - the 30-second wait expired. The editor needs your browser tab open and you need to actually export. If you run the workflow and walk away, this node times out and passes None downstream.
  • Canvases saved to "nowhere" - saved files go to ComfyUI/input/FunCodeCanvas/, not your downloads folder. Look there.
  • Layer jumps back after re-run - you're on the reset policy and the content changed. Switch to preserve_transform in the editor.
  • Cached, stale composite - if the node isn't re-firing after edits, check that you clicked export; the re-run is driven by the export updating last_update.

It's a fiddly node in the sense that it demands your attention - you can't fire-and-forget it like a KSampler. But for compositing jobs where you'd otherwise re-roll a generation until the layers happen to look right, a 30-second manual fix beats a tenth re-gen every time.

CategoryFunCode/Canvas

Inputs (1)

NameTypeDefaultDescription
canvas_dataoptCANVAS_DATA

Outputs (1)

NameTypeDescription
imageIMAGE