-
|
Hi, I want to save the react flow diagram as a png file. Wondering if anyone has suggestions? Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 7 comments 12 replies
-
|
Hi @gpalrepo i was also trying to implement something like that can you please share any suggestion if you have made any progress in that ! |
Beta Was this translation helpful? Give feedback.
-
|
I've created a "Download Image" example that uses html-to-image. |
Beta Was this translation helpful? Give feedback.
-
|
@moklick Hi, I am currently trying to download whole flow as png or pdf but wasnt able to make it work in a way that everything is inside even nodes outside of viewport. I am using html-to-image to convert reactflow ref to canvas. My lastest try contains code below: Is it possible to make this work? Thanks! |
Beta Was this translation helpful? Give feedback.
-
|
I didn't see anyone come out and fully lay out an example that works that also captures the entire viewport in case you have a big reactflow instance. Here's what worked for me: import { useState, useEffect } from "react";
import { getRectOfNodes, getTransformForBounds, useReactFlow } from "reactflow";
import { toPng } from "html-to-image";
function DownloadFlow() {
const [previewImage, setPreviewImage] = useState<string | null>(null);
const { getNodes } = useReactFlow();
useEffect(() => {
const nodesBounds = getRectOfNodes(getNodes());
const imageWidth = nodesBounds.width + 200;
const imageHeight = nodesBounds.height + 200;
const transform = getTransformForBounds(
nodesBounds,
imageWidth,
imageHeight,
0.5,
2,
);
toPng(document.querySelector(".react-flow__viewport") as HTMLElement, {
backgroundColor: Colors.neutral200,
width: imageWidth,
height: imageHeight,
style: {
width: String(imageWidth),
height: String(imageHeight),
transform: `translate(${transform[0]}px, ${transform[1]}px) scale(${transform[2]})`,
},
}).then((dataUrl) => {
setPreviewImage(dataUrl);
});
}, [getNodes]);
function handleActualDownload() {
if (previewImage) {
downloadImage(previewImage, name);
emitEventOnDownload();
onClosed();
}
}
return <button onClick={handleActualDownload}>Download</button>;
}
function downloadImage(dataUrl: string, name?: string) {
const now = new Date();
const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(
2,
"0",
)}-${String(now.getDate()).padStart(2, "0")}`;
const timeStr = `${String(now.getHours()).padStart(2, "0")}${String(
now.getMinutes(),
).padStart(2, "0")}${String(now.getSeconds()).padStart(2, "0")}`;
const fileNamePrefix = name ? `${name}_` : "reactflow_";
const fileName = `${fileNamePrefix}${dateStr}_${timeStr}.png`;
const a = document.createElement("a");
a.setAttribute("download", fileName);
a.setAttribute("href", dataUrl);
a.click();
} |
Beta Was this translation helpful? Give feedback.
-
|
Hey guys, I came across this discussion when trying to debug my download functionality as well. As a quick heads up, it appears that using the nodeOrigin prop on the ReactFlow component causes the downloaded image to be offset and for a portion of the left side and the top of the image to be cropped. My ReactFlow component : <ReactFlow
nodes={nodes}
edges={edges}
...
nodeOrigin={[0.5, 0.5]}
...
>
<Background />
<Controls />
</ReactFlow>And my download functionality : const screenshot = () => {
const nodesBounds = getNodesBounds(getNodes())
const imageWidth = 1024
const imageHeight = 768
const transform = getViewportForBounds(
nodesBounds,
imageWidth,
imageHeight,
0,
2
)
toPng(document.querySelector('.react-flow__viewport') as HTMLElement, {
filter: node =>
!(
node?.classList?.contains('react-flow__minimap') ||
node?.classList?.contains('react-flow__controls')
),
backgroundColor: '#fff',
width: imageWidth,
height: imageHeight,
style: {
transform: `translate(${transform.x}px, ${transform.y}px) scale(${transform.zoom})`,
},
}).then(dataUrl => {
const a = document.createElement('a')
a.setAttribute('download', 'reactflow.png')
a.setAttribute('href', dataUrl)
a.click()
})
}It feels like getNodesBounds or getViewportForBounds (or both?) doesn't take the nodeOrigin into account. Can anybody confirm this ? Should this require a fix ? Or does anybody have an idea for a workaround ? Much appreciated ! |
Beta Was this translation helpful? Give feedback.
-
|
How can we take image of a group Node only instead of full flow? As in download-image example its using .react-flow__viewport class to take an image of all nodes in the flow. |
Beta Was this translation helpful? Give feedback.
-
|
I solved this using dom-to-svg instead of html-to-image because I was having a lot of issues with html-to-image not rendering edges and the output SVG had a ton of unnecessary attributes that made the output file ~20MB where the PNG variant was ~400K. |
Beta Was this translation helpful? Give feedback.
I've created a "Download Image" example that uses html-to-image.