Can a GraphObject bind to diagram scale?

I have a need to tweak my node renderers when zoomed out, to emphasize only what’s important – mainly make them a solid state color. Is there an easy and cheap way to do this?


No, a Diagram cannot be a binding source. (Nor can any Tool or the CommandHandler or any Layout.)

It sounds like you want to implement a “ViewportBoundsChanged” DiagramEvent listener:

$(go.Diagram, . . .,
  { . . .,
    "ViewportBoundsChanged": e => {
      if (e.subject.scale !== e.diagram.scale) {  // see if the Diagram.scale changed
        e.diagram.commit(d => {
          d.nodes.each(n => ...);  // modify each Node appropriately, if desired
        }, null);  // skipsUndoManager

The question is how you want to modify each Node. You could just call Panel.findObject and just modify some properties.

Or you could define another template and just set the Node.category property. The latter does impose more overhead, since it has to make a copy of Node and that might result in a new layout.

Awesome! Thanks, I’ll give that a shot.

If anyone finds this question later and wants just a little more help, this worked well for me. It’s basically what Walter said, but with some performance tweaks.

this.addDiagramListener('ViewportBoundsChanged', e=> {
            if ((e.subject.scale >= 0.25 && e.diagram.scale < 0.25) ||
                (e.subject.scale <= 0.25 && e.diagram.scale > 0.25)) {
                e.diagram.commit(d => {
                    d.nodes.each(n => {
                        const rightSide: Shape = n.findObject('rightSide') as Shape;
                        if (rightSide) {
                            if (e.diagram.scale < 0.25) {
                                rightSide.fill =;
                            } else {
                                rightSide.fill = 'white';
                    });  // modify each Node appropriately, if desired
                }, null);  // skipsUndoManager

It only loops over the nodes when the threshold, in this case 0.25, is crossed. Of course the 0.25 should probably be a constant somewhere instead of repeated, but the general idea is sound.

when diagram increaseZoom or decreaseZoom set:
diagram.model.commit(m => m.set(m.modelData, “scale”, diagram.scale));

node template:
new go.Binding(“fill”, “scale”, function(scale, obj) {
var part = obj.part;
if(scale < 0.25) {
return ‘white’;