GoJS 3.0
GoJS 3.0 brings a number of new features for advanced Diagram control, such as custom routing via Routers and data-bound theming with Themes. We have also rewritten some of the internals to take advantage of modern JavaScript, and rewritten the API to use clearer enumerations. These changes are largely backwards-compatible.
There are a number of other changes, detailed below.
New npm packages
For 3.0, the gojs
npm package contains only the release libraries, and no extensions, documentation or sample code. The documentation, sample, and extensions code can be downloaded separately, via npm create gojs-kit
.
Performance
GoJS 3.0 leverages modern JavaScript and more modern Canvas API features for increased performance. However, this also means dropping support for old browsers such as IE11, and there are a number of minor incompatibilities detailed below.
Diagram rendering is now generally faster, and Diagram heap size has been significantly reduced, especially for large graphs.
Routers
One has always been able to customize the computed paths for Links by setting properties on a Link or on its connected port elements, or by overriding methods on a custom Link subclass. There is now support for a separate routing phase where instances of Router can modify Links. See the intro page on routers for more information.
GoJS 3.0 introduces the AvoidsLinks Router, which attempts to separate parallel link segments, and can work alongside AvoidsNodes routing.
Theming
GoJS now provides functionality to define and manage themes, and GraphObjects can now be themed via theme bindings. This allows for applications to more easily provide multiple themes, especially light and dark mode. See the intro page in theming for more information.
Viewport Layers
There are two new default layers in each Diagram, "ViewportBackground"
and "ViewportForeground"
. These layers have the new property Layer.isViewportAligned set to true
. Parts in viewport aligned layers will not obey the Diagram.position or Diagram.scale properties, so as the user scrolls or pans or zooms they will remain fixed in the viewport.
Layers with Layer.isViewportAligned set to true
will automatically position and scale their Parts to be relative to the viewport, based on the Part's GraphObject.alignment and GraphObject.alignmentFocus values, not on its Part.location or GraphObject.position.
Enumerations
GoJS now uses Typescript enumerations to represent possible values for many properties. This enables autocompletion in some text editors. Some examples:
- Where one wrote:
new go.Panel({ stretch: go.GraphObject.Fill })
,
one can now write:new go.Panel({ stretch: go.Stretch.Fill })
. - Where one wrote:
new go.RowColumnDefinition({ column: 1, sizing: go.RowColumnDefinition.None })
,
one can now write:new go.RowColumnDefinition({ column: 1, sizing: go.Sizing.None })
. - Where one wrote:
new go.TreeLayout({ alignment: go.TreeLayout.AlignmentStart })
,
one can now write:new go.TreeLayout({ alignment: go.TreeAlignment.Start })
.
The original static EnumValue properties have been deprecated in favor of these new enumerations, but continue to exist for compatibility. So, for example: go.GraphObject.Fill === go.Stretch.Fill
. The never-documented EnumValue class has been removed from the library. The new enum values are numbers.
Other New Features
- Improved Rounded Rectangles: The commonly used
"RoundedRectangle"
Shape.figure now considers the Shape.parameter2 option to be a bit flag mask that determines which corners to round. 1: top-left, 2: top-right, 4: bottom-right, 8: bottom-left. This makes it easier to round only the bottom or top corners, or a single corner. For compatibility, the default flags value rounds all four corners. - Added the predefined
"Capsule"
figure, as yet another kind of rounded rectangle. See the Shapes sample for an example. - Added the predefined
"Borders"
figure, as yet another kind of rectangle where the Shape.parameter1 option is a bit flag mask that determines which sides are drawn. 1: top, 2: right, 4: bottom, 8: left. See the Shapes sample for an example. - Added methods GraphObject.bindModel, GraphObject.bindObject, and GraphObject.bindTwoWay, as convenience functions for adding a Binding to a GraphObject, which additionally call Binding.ofModel, Binding.ofObject, and Binding.makeTwoWay, respectively. The fourth argument to GraphObject.bind has been deprecated -- if you want a TwoWay Binding, call GraphObject.makeTwoWay, which is a clearer declaration of intent.
- The ForceDirectedLayout class has been rewritten, although the API remains compatible. For small to medium-sized simple graphs (up to around 1000 nodes), these changes should not be noticeable, however for large or complex graphs node placements should be better. Several properties have been added to ForceDirectedLayout -- look for names with "prelayout" in them.
- LayeredDigraphLayout has improved the routing of some links that go "backward" to form a cycle.
- Added static functions Point.stringifyFixed, Size.stringifyFixed, Rect.stringifyFixed, Margin.stringifyFixed, Spot.stringifyFixed, and Geometry.stringifyFixed to produce Binding.backConverters that reduce the size of the output JSON and to make it easier to read and compare. Added the property Model.pointsDigits to control how many decimal digits are written for the Link.points list by Model.toJson.
- Added the static function TextBlock.isValidFont to allow dynamically deciding whether a CSS font string is valid or not. This is like the existing Brush.isValidColor for checking CSS color strings.
- Added the read-only property Node.isTreeRoot as a quick way to decide whether a node is a "root" node, while ignoring links that are not Link.isTreeLink, ignoring reflexive links, and considering Diagram.isTreePathToChildren.
- Code that depends on a Group.placeholder or an Adornment.placeholder now also checks that the placeholder is GraphObject.isVisibleObject, to make it possible to dynamically control whether the placeholder determines the position and size of the Group or Adornment.
- Calls to Model.toIncrementalJson or Model.toIncrementalData no longer signal an error if the model is a GraphLinksModel and GraphLinksModel.linkKeyProperty is the empty string. Instead, it first modifies the model so that GraphLinksModel.linkKeyProperty is set to
"key"
, thereby assigning unique key values to all of the link data objects, before producing the resulting text or data. - Added the property LinkReshapingTool.resegmentingDistance, to control the distance from a straight line that two adjacent nearly straight segments should be combined into a single segment.
- Group animations such as group expansion and adding members have been improved.