Legends and Titles

Sometimes in addition to the nodes and links that are the subject of a diagram, one also wants to display a "legend" or "key" describing the different kinds of nodes or links. Perhaps one also wants there to be "title" for the diagram in large letters.

Outside of Diagram

First, you must consider whether titles or legends should be part of the diagram or not. You can create whatever you want in HTML outside of the diagram.

An HTML Title for a Diagram
Color key:
Purple nodes are juicy and sweet
Red nodes are very angry
White nodes sleep well at night

Note that anything in HTML will not automatically scroll and zoom along with the diagram's contents shown in the viewport. But HTML elements could be positioned in front of or behind the diagram's DIV element.

Unmodeled Parts

Second, you should consider whether the title or legend should be held in your data model. Do you need to save and load that data in your database?

If you do not want to these objects to be included in your application's data model, you can just create them as simple Parts and Diagram.add them to your diagram at explicitly defined Part.locations.

  setupForLegend(diagram);  // this creates a diagram just like the first example

    $(go.Part, { location: new go.Point(0, -40) },
      $(go.TextBlock, "A Title", { font: "bold 24pt sans-serif", stroke: "green" })));

If you do not assign a location or position for your Parts, and if your Diagram.layout (if any) does not assign any Part.location, then there might not be a real location for those parts and they might not appear anywhere in the diagram.

All of the predefined Layouts that make use of LayoutNetworks, including TreeLayout, do not operate on simple Parts but only on Nodes and Links. If you had added a Node to the diagram it would have been positioned as part of this diagram's normal tree layout, even though you explicitly set its location. Alternatively it could still be a Node if you set its Part.isLayoutPositioned property to false.

You will notice that the title is selectable and movable and copyable and deletable in the diagram above. You may want to set properties such as Part.selectable to false.

For an example showing a legend, see the Family Tree sample.

Modeled Parts

If on the other hand you do want to store your titles or legends in your model, you can do so using the normal mechanisms. Typically you will use node categories and template maps.

If you do not want your users to manipulate those objects, you will want to set Part.selectable to false. You may want to set Part.layerName to "Grid", so that it is always in the background behind everything else. (All Parts in the "Grid" Layer are automatically not selectable, because Layer.allowSelect is false for that Layer.)

Static Parts

Third, consider whether you want the title or legend to move or scale as the user scrolls or zooms the diagram. If you want to keep such a decoration at the same position in the viewport, it might be easiest to do so by implementing it as an HTML element that is superimposed with the diagram's DIV element.

However if you really want to implement it using a GoJS Part, you can do so by implementing a "ViewportBoundsChanged" DiagramEvent listener that continually resets the position and scale to values that make them appear not to move as the user scrolls or zooms.

  setupForLegend(diagram);  // this creates a diagram just like the first example

        layerName: "Grid",  // must be in a Layer that is Layer.isTemporary,
                            // to avoid being recorded by the UndoManager
        _viewPosition: new go.Point(0,0)  // some position in the viewport,
                                           // not in document coordinates
      $(go.TextBlock, "A Title", { font: "bold 24pt sans-serif", stroke: "green" })));

  // Whenever the Diagram.position or Diagram.scale change,
  // update the position of all simple Parts that have a _viewPosition property.
  diagram.addDiagramListener("ViewportBoundsChanged", function(e) {
    e.diagram.commit(function(dia) {
      // only iterates through simple Parts in the diagram, not Nodes or Links
      dia.parts.each(function(part) {
        // and only on those that have the "_viewPosition" property set to a Point
        if (part._viewPosition) {
          part.position = dia.transformViewToDoc(part._viewPosition);
          part.scale = 1/dia.scale;
    }, "fix Parts");

Note that as the user pans or scrolls or zooms the diagram, the title remains at the same viewport position at apparently the same effective size. This example makes use of the "Grid" Layer (see Intro to Layers), which is convenient for making sure the title (or legend) stays in the background and does not participate in selection or mouse events or the UndoManager.