I have a circle shape node template. I want t o render a lottie animation at its center. is this possible in GOJS ?
I’m unfamiliar with Lottie animations. We’ll investigate it.
Here’s a demo:
This uses canvas rendering. There’s probably a more efficient solution when rendering as SVG, but I’m not sure how to get the Lottie engine to render in SVG.
<!DOCTYPE html>
<html>
<head>
<title>Minimal Lottie in GoJS Sample</title>
<!-- Copyright 1998-2025 by Northwoods Software Corporation. -->
</head>
<body>
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:400px"></div>
<script type="importmap">{"imports":{
"gojs":"https://cdn.jsdelivr.net/npm/[email protected]/release/go-module.js",
"lottie":"https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web/dist/index.js"
}}</script>
<script id="code" type="module">
import { DotLottie } from "lottie";
import * as go from "gojs";
const myDiagram =
new go.Diagram("myDiagramDiv", {
"undoManager.isEnabled": true
});
function convertFromLottie(src, pic) {
const diag = pic.diagram;
if (!diag || !diag.div) return null;
const cnv = Lotties.get(src);
if (cnv) return cnv;
const canvas = document.createElement("canvas");
canvas.style = "width: 100px; height: 100px; visibility: hidden; position: absolute; left: 0px; top: 0px;";
const dotLottie = new DotLottie({
autoplay: true,
loop: true,
canvas: canvas,
src: src
});
Lotties.set(src, canvas);
diag.div.appendChild(canvas);
return canvas;
}
const Lotties = new Map();
myDiagram.nodeTemplate =
new go.Node("Vertical")
.add(
new go.Picture({ name: "PIC", width: 100, height: 100 })
.bind("element", "src", convertFromLottie),
new go.TextBlock({ margin: 2 })
.bind("text")
);
myDiagram.model = new go.GraphLinksModel(
[
{ key: 1, text: "Alpha", color: "lightblue", src: "https://lottie.host/4db68bbd-31f6-4cd8-84eb-189de081159a/IGmMCqhzpt.lottie" },
{ key: 2, text: "Beta", color: "orange", src: "Animation1739540457740.lottie" },
{ key: 3, text: "Gamma", color: "lightgreen", src: "Animation1739540457740.lottie" },
{ key: 4, text: "Delta", color: "pink", src: "Animation1739540457740.lottie" },
],
[
{ from: 1, to: 2 },
{ from: 1, to: 3 },
{ from: 2, to: 2 },
{ from: 3, to: 4 },
{ from: 4, to: 1 }
]);
setInterval(() => myDiagram.nodes.each(n => {
const pic = n.findObject("PIC");
if (pic) pic.redraw();
}), 1000/30)
</script>
</body>
</html>
while this seems to work but its not quite what i am looking for.
Let me try explaining my scenario.
I am trying to make an api call using each node’s id.
While the api response is being fetched, I want to animate that particular node for the user to visually see which node is currently being processed.
I want to add an animation something like you see in the attached gif and i need the animation to be smooth which normally is achieved via lottie animations. But if you have a better workaround i am all ears.
Why won’t Walter’s solution work? Other than being a bit kludgey, you could add a go.Picture with a lottie animation to some adornment on the Node.
Though if this is for a temporary item only, it might be best to actually display an HTML element over the Diagram (containing the Lottie animation), and then remove it when its no longer needed.
This comes with other potential issues (will this thing be long lived? Does it need to move with the node?), so it may not be appropriate. But it might be a nice separation of concerns otherwise.
For example, look at the spinner shown when loading a large model: Virtualized Diagram no Layout | GoJS Diagramming Library
this is the part i am worried about, especially considering that my canvas could have anywhere between 50 - 200 nodes, probably more.
setInterval(() => myDiagram.nodes.each(n => {
const pic = n.findObject(“PIC”);
if (pic) pic.redraw();
}), 1000/30)
Moreover, i want the animation only while the api response is being fetched, once fetched, the lottie should stop and disappear and re-appear when the api request is again fired with the node’s id.
Again its not necessary to use a lottie, I can even use a gif like the one shared above, I am just not sure how I can do the above in GOJS.
How does the sample Virtualized Diagram no Layout | GoJS Diagramming Library not provide exactly what you are asking for?
Please see the recording at this link. This is exactly what i want to achieve
Assume your animated GIF is named “spin.gif” in the same directory as this page:
<!DOCTYPE html>
<html>
<head>
<title>Minimal Spinner for each Node</title>
<!-- Copyright 1998-2025 by Northwoods Software Corporation. -->
</head>
<body>
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:400px"></div>
<script src="https://cdn.jsdelivr.net/npm/gojs/release/go.js"></script>
<script id="code">
const myDiagram =
new go.Diagram("myDiagramDiv", {
renderer: "svg",
layout: new go.LayeredDigraphLayout(),
"undoManager.isEnabled": true
});
myDiagram.nodeTemplate =
new go.Node("Spot")
.add(
new go.Panel("Auto", { width: 50, height: 50 })
.add(
new go.Shape("Circle", {
fill: "white", stroke: "lightgray", strokeWidth: 2,
portId: ""
}),
new go.TextBlock({ textAlign: "center" })
.bind("text")
),
new go.Picture("spin.gif", { width: 72, height: 72 })
.bindObject("opacity", "isHighlighted", h => h ? 1 : 0)
);
myDiagram.linkTemplate =
new go.Link()
.add(
new go.Shape({ stroke: "blue", strokeWidth: 2 }),
new go.Shape({ toArrow: "OpenTriangle", stroke: "blue", strokeWidth: 2 })
);
myDiagram.model = new go.GraphLinksModel(
[
{ key: 1, text: "Alpha", color: "lightblue" },
{ key: 2, text: "Beta", color: "orange" },
{ key: 3, text: "Gamma", color: "lightgreen" },
{ key: 4, text: "Delta", color: "pink" }
],
[
{ from: 1, to: 2 },
{ from: 2, to: 3 },
{ from: 3, to: 4 },
]);
setInterval(() => {
myDiagram.nodes.each(node => node.isHighlighted = Math.random() < 0.25)
}, 1000);
</script>
</body>
</html>