Best way to make blinking text in a node template?

i’m facing a simple task: i need to include a TextBlock in a node template that will display a blinking text, changing color each second, red -> white -> red -> white…

having no better solution in mind, i have introduced a binding:

tb.bind(new go.Binding("stroke", "currentColorOfBlinkingText"));

i have set up a timer that changes the currentColorOfBlinkingText variable each second and updates the bindings for each of the relevant nodes:

goNode.updateTargetBindings("currentColorOfBlinkingText");

i have a hunch, that there is a more efficient way of doing this in GoJS.
any ideas?

If that’s what you want, that’s a reasonable way of doing it. Chances are, though, that you don’t need to save the state in the model, do you?

If you don’t need to be able to save and load the current blinking state, it would be slightly more efficient not to use a property in the model data and thus not use a Binding. Just modify the TextBlock.stroke property directly in the diagram. Be sure to temporarily turn off Diagram.skipsUndoManager, to avoid recording those changes in the UndoManager, if it is enabled.

myDiagram.commit(function(diag) {
    // for each TextBlock that you want to modify, set its stroke property
}, null);  // null means skipsUndoManager

If you don’t want blinking but some more gradual animation, you could set up a custom animation:
https://gojs.net/latest/intro/animation.html#AnimationTriggerClass

thank you for your answer. and wow! i think i have just experience the fastest developer support ever :)

you are absolutely right about saving the state. it is important that the text is blinking, but it is absolutely NOT important whether the actual color is red or white.

so yes, i think your suggestion of directly changing the stroke of the textboxes for those nodes where the model indicates that it should be blinking is a better way to go.

if i understand correctly, it is ok, that i’m taking care of the one-second timer cycle myself, but instead of a model change + target binding update, i could use diagram.commit skipping the UndoManager.

regarding the animation trigger, do i understand correctly that i can “transparently” add that on top of the above solution? when i commit the stroke color change the animation defined in the template will do a smooth transition? this would be brilliant!

is there a way i can control the speed and dynamics of the transition?

That’s described in the documentation. Here’s a complete sample:

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Sample</title>
  <!-- Copyright 1998-2021 by Northwoods Software Corporation. -->
  <script src="https://unpkg.com/gojs"></script>
  <script id="code">
  function init() {
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
        {
          "animationManager.duration": 250,
          "undoManager.isEnabled": true
        });

    myDiagram.nodeTemplate =
      $(go.Node, "Auto",
        $(go.Shape,
          { fill: "white", strokeWidth: 0, portId: "", fromLinkable: true, toLinkable: true, cursor: "pointer" },
          new go.Binding("fill", "color")),
        $(go.TextBlock,
          { name: "TB", margin: 8, editable: true },
          new go.Binding("text").makeTwoWay(),
          new go.AnimationTrigger("stroke")
        )
      );

    myDiagram.model = new go.GraphLinksModel(
    [
      { key: 1, text: "Alpha", color: "lightblue" },
      { key: 2, text: "Beta", color: "orange", blinking: true },
      { key: 3, text: "Gamma", color: "lightgreen" },
      { key: 4, text: "Delta", color: "pink", blinking: true }
    ],
    [
      { from: 1, to: 2 },
      { from: 1, to: 3 },
      { from: 2, to: 2 },
      { from: 3, to: 4 },
      { from: 4, to: 1 }
    ]);
  }

  function loop() {
    setTimeout(function() {
      myDiagram.commit(function(diag) {
        diag.nodes.each(function(n) {
          if (n.data.blinking) {
            var tb = n.findObject("TB");
            if (tb) {
              tb.flag = !tb.flag;
              tb.stroke = tb.flag ? "red" : "black";
            }
          }
        });
      }, null);
      loop();
    }, 1000);
  }

  loop();  // start animation right away
  </script>
</head>
<body onload="init()">
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
</body>
</html>

But remember that having any animation necessarily uses a lot more CPU than not having any animation.

Walter, i’m much obliged!
this is exactly what i needed. perfect!