GoJS for HTML5/Canvas 2.1.2
GoJS for HTML5/Canvas 2.1.2
GoJS makes it easy to construct interactive diagrams of Nodes, Links, and Groups, with customizable templates and layouts. GoJS supports graphical templates and data-binding of object properties to model data. Only the model, consisting of simple jаvascript objects, needs to be saved and restored. GoJS makes it easy to read and write models in JSON format. We provide comprehensive API documentation and in-depth overviews of GoJS concepts, with interactive examples. With over 90 samples, you'll find numerous examples of GoJS properties and methods.
Fully Interactive Diagrams
Extensible Layouts and Tool System
Data-Binding and Models
Transactional State and Undo-Management
Mobile Support
Lightning Fast Diagramming in the Browser
GoJS takes advantage of the HTML Canvas to support high-performance diagrams. For creating static documents and printable resources, GoJS supports exporting Diagrams to images and SVG.
GoJS supports all modern browsers (IE9+), including mobile browsers.
Diagrams and Models
The Nodes and Links of a Diagram are visualizations of data that is managed by a Model. GoJS has a model-view architecture, where Models hold the data (arrays of jаvascript objects) that describe nodes and links, and Diagrams act as views to visualize this data using actual Node and Link objects. Models, not Diagrams, are what you load and then save after editing. You add whatever properties you need for your app on the data objects in the model; you do not add properties to or modify the prototype of the Diagram and GraphObject classes.
The diagram displays the three nodes that are in the model. Some interaction is already possible:
Click and drag the background in the above diagram to pan the view.
Click a node to select it, or press down on and drag a node to move it around.
To create a selection box, click and hold on the background, then start dragging.
Use CTRL-C and CTRL-V, or control-drag-and-drop, to make a copy of the selection.
Press the Delete key to delete selected nodes. (Read about more Keyboard Commands.)
Since the undo manager was enabled, CTRL-Z and CTRL-Y will undo and redo moves and copies and deletions.
Styling Nodes
Nodes are styled by creating templates consisting of GraphObjects and setting properties on those objects. To create a Node, we have several building block classes at our disposal:
Shape, to display pre-defined or custom geometry with colors
TextBlock, to display (potentially editable) text in various fonts
Picture, to display images
Panel, containers to hold a collection of other objects that can be positioned and sized in different manners according to the type of the Panel (like tables, vertical stacks, and stretching containers)
All of these building blocks are derived from the GraphObject abstract class, so we casually refer to them as GraphObjects or objects or elements. Note that a GraphObject is not an HTML DOM element, so there is not as much overhead in creating or modifying such objects.
We want the model data properties to affect our Nodes, and this is done by way of data bindings. Data bindings allow us to change the appearance and behavior of GraphObjects in Nodes by automatically setting properties on those GraphObjects to values that are taken from the model data. The model data objects are plain jаvascript objects. You can choose to use whatever property names you like on the node data in the model.
Kinds of Models
With a custom node template our diagram is becoming a pretty sight, but perhaps we want to show more. Perhaps we want an organizational chart to show that Don Meow is really the boss of a cat cartel. So we will create a complete organization chart diagram by adding some Links to show the relationship between individual nodes and a Layout to automatically position the nodes.
In order to get links into our diagram, the basic Model is not going to cut it. We are going to have to pick one of the other two models in GoJS, both of which support Links. These are GraphLinksModel and TreeModel. (Read more about models here.)
In GraphLinksModel, we have model.linkDataArray in addition to the model.nodeDataArray. It holds an array of jаvascript objects, each describing a link by specifying the "to" and "from" node keys. Here's an example where node A links to node B and where node B links to node C:
Diagram Layouts
As you can see the TreeModel automatically creates the necessary Links to associate the Nodes, but it's hard to tell whose parent is who.
Diagrams have a default layout which takes all nodes that do not have a location and gives them locations, arranging them in a grid. We could explicitly give each of our nodes a location to sort out this organizational mess, but as an easier solution in our case, we will use a layout that gives us good locations automatically.
We want to show a hierarchy, and are already using a TreeModel, so the most natural layout choice is TreeLayout. TreeLayout defaults to flowing from left to right, so to get it to flow from top to bottom (as is common in organizational diagrams), we will set the angle property to 90.
GoJS 2.0
For 2.0, GoJS has been rewritten in TypeScript, with improvements to stability and documentation. All customers (with or without source code license) can take advantage of the TypeScript definitions .d.ts file, which is much more comprehensive in 2.0.
A source license will now include TypeScript source files as well as JavaScript sources, and examples of how to build the library into your project with Webpack or Browserify, should you wish to. This will allow you to remove unused modules from the source code, such as Layouts, Models, and Tools that you are not using. Note that unless you have strong minification, you may not see size improvements over the pre-built go.js library, which is highly optimized.
The size of the `go.js` library has been slightly reduced (both uncompressed and gzipped), from 1.8 versions.
The main library has been reduced by removing many of the uncommon figures. These are now an extension. (Figures.js)
GoJS can now be run DOM-less, in Node.
We have added the ability to create your own Panels, with the new PanelLayout class. See an example here.
Changes for 2.0
Build GoJS from TypeScript Source:
GoJS can be compiled from the TypeScript source files. Dynamically building GoJS this way allows unused modules/code to be removed. See the new Intro page on Building GoJS from TypeScript sources
GoJS now runs in DOM-less environments like Node:
GoJS can run in DOM-less environments, like Node, without any dependencies. See the new Introduction page on GoJS with Node.js.
GoJS cannot guarantee accurate Picture and TextBlock measuring in DOM-less environments, so if you do not set desiredSize (or width and height) on TextBlocks or Pictures, you may want to use GoJS inside of a headless browser project, like Chrome's Puppeteer. We detail how to use GoJS with Puppeteer in the Server Side Images Introduction page.
DOM-less environments can be used for server-side work, such as computing complex layouts. Headless environments such as Puppeteer can be used to do layout calculations or to make server-side images of Diagrams.
See the note about Diagram.viewSize below.
Reworked part-moving and added a new class: DraggingOptions:
DraggingOptions holds properties for Part-moving operations, and DraggingInfo holds relative positions of dragged objects, for use in snapping and cancellation. The DraggingTool has an instance of the DraggingOptions class, and setting properties like DraggingTool.isGridSnapEnabled modifies this instance. If the Diagram has no DraggingTool associated with it, it falls back to the default properties of the class. You can create your own to pass to part-moving methods. Typically you do not need to create an instance of this class.
Moving parts has been reworked. Diagram.moveParts, Diagram.computeMove, and CommandHandler.computeEffectiveCollection now accept an additional argument for a DraggingOptions instance. This allows fine-grained control over programmatic moving of nodes. Typically, these options are supplied by the DraggingTool.dragOptions instance.
DraggingTool.computeMove functionality has been moved to Diagram.computeMove, and DraggingTool.computeEffectiveCollection functionality has been moved to CommandHandler.computeEffectiveCollection. These methods remain on their original class for compatibility when overriding, but the main functionality has been moved to the Diagram class for tree-shaking reasons.
Diagram and Layer:
Added Diagram.mouseEnter and Diagram.mouseLeave to allow for functions to be called on mouseenter and mouseleave events on the Diagram's Canvas element.
When mouse leaves a Diagram, Diagram.lastInput is now set to the "mouseout" MouseEvent.
Added "GainedFocus" and "LostFocus" DiagramEvents, which allow functions to be called when the Diagram's canvas gains or loses focus, without having to access any of the DOM within the Diagram.div.
Added Diagram.findPartsAt, Diagram.findPartsIn and Diagram.findPartsNear as convenience functions. These functions call Diagram.findObjectsAt, Diagram.findObjectsIn or Diagram.findObjectsNear and only return Parts in non-temporary layers, rather than all GraphObjects.
Added Diagram.viewSize which can be used to set a viewport size in DOM-less environments. See the new Intro page on GoJS with Node.js.
Added Diagram.handlesDragDropForTopLevelParts which determines whether drag-and-drop events may be bubbled up to the diagram if not handled by a Part.
Diagram.moveParts, Diagram.copyParts, and Diagram.computePartsBounds now accept an Array of parts, in addition to their former iterable collection of Parts.
Diagram.makeImage and Diagram.makeImageData now accept callback and callbackTimeout options. If a callback function is provided, the methods will instead return null and image creation will wait until all Diagram Picture sources are loaded before creating the image and invoking the callback.
Models:
Added property Model.copiesKey which controls whether Model.copyNodeData and GraphLinksModel.copyLinkData copy any key property of the data. Setting this to false is useful in forcing copies from a Palette to get a new unique key. The default value is true for compatibility with version 1.*.
Improved Model.updateTargetBindings and Part.updateTargetBindings to update Panels that have Panel.itemArray data bound if the contents of the Array have changed. In version 1, the reference to the Array had to have changed -- the Panel.itemArray had to have been replaced. In version 2, the Panel.itemArray property setter checks to see if all of the Array items have corresponding Panels and that all child Panels correspond to Array items (i.e. Panel.data refers to the Array item), even if the new property value is a reference to the same Array that it had been before.
Parts:
Added Part.rotationSpot to control the Spot within the Part.rotateObject that the RotatingTool will pivot about.
Part.move and Part.moveTo now have an additional optional boolean argument to specify moving by location instead of position.
Panels and PanelLayout:
Spot Panels now allow child elements to stretch, which will match the size of the main element. See the Intro Page for an example.
It is now possible to create your own Panel layouts with the PanelLayout class. This is expected to be very uncommon, but may serve uncommon use cases. See the PanelLayout sample for an example. There is a new static function, Panel.definePanelLayout for this purpose.
When building from source, it is also possible to exclude many Panel types that you are not using, to make the resulting JS smaller. See the Intro page on building GoJS sources for details.
GraphObjects and Geometry:
GraphObject.cloneProtected is now documented. It functions in a similar fashion to Model.cloneProtected and Layout.cloneProtected, and is necessary for properly copying additional properties on custom subclasses of GraphObject.
Added properties Picture.flip and TextBlock.flip, which default to GraphObject.None, can be set to GraphObject.FlipHorizontal, GraphObject.FlipVertical, or GraphObject.FlipBoth to flip a Picture's or TextBlock's rendering.
Added properties Shape.graduatedSkip and TextBlock.graduatedSkip, which allow ticks/labels along a Graduated panel to be skipped, causing gaps. These properties take a function, and default to null meaning no ticks/labels will be skipped.
Added predefined builders for "ToolTip" and "ContextMenu" for ease of template creation. The definitions for these builders can be found in Buttons.js
Added TextBlock.WrapBreakAll as a value for TextBlock.wrap, which allows text to break at individual characters.
Added TextBlock.getBaseline, TextBlock.setBaseline, TextBlock.getUnderline, TextBlock.setUnderline, which give more control over the height to that lines of text and underlines are drawn.
Added GraphObject.getDocumentBounds, as a convenient way to avoid having to call GraphObject.getDocumentPoint on all four corner points of a rectangular area.
Layouts:
Documented CircularNetwork, ForceDirectedNetwork, LayeredDigraphNetwork, and TreeNetwork. These are the subclasses of LayoutNetwork for their respectively-named Layouts.
Added Layout.getLayoutBounds method and Layout.boundsComputation functional property, to support easier customization for how large the layout treats each node. This is convenient when your nodes have decorations or text that you do not want to consider during the layout, even if those objects might overlap other nodes.
Documented Layout.initialOrigin method, to be called by overrides of Layout.doLayout when used as a Group.layout that may want to account for the original location of the group when the group has a Group.placeholder.
Tools and Commands:
CommandHandler.scrollToPart has been extended to automatically expand any subtrees and subgraphs in order to make visible each Part that it scrolls to.
Added ClickCreatingTool.isGridSnapEnabled, which works like DraggingTool.isGridSnapEnabled and ResizingTool.isGridSnapEnabled.
Added RotatingTool.computeRotationPoint to control the point about which the object rotates. Added RotatingTool.rotationPoint to remember the result of RotatingTool.computeRotationPoint. Added RotatingTool.handleAngle and RotatingTool.handleDistance to determine where the rotation handle is placed relative to the rotation point in the Part.rotateObject. A custom RotatingTool is no longer needed to position the rotation handle above the object.
Improved LinkingBaseTool.copyPortProperties to better handle rotated ports when setting up a temporary port.
Brushes:
Added Brush.isDark instance and static methods, which determine whether a Brush or CSS color string is "dark", based on luminance. This can be useful in bindings to determine text colors.
Added Brush.mix to allow for the mixing of two CSS colors.
Samples and Extensions:
Many samples have been translated into TypeScript, in the samplesTS folder in the kit.
Added PanelLayout, demonstrating Panel.definePanelLayout.
Added extensionsTS/PackedLayout, which demonstrates a custom layout for packing nodes closely into a rectangular or elliptical area. (Source is TS only)
Added Wordcloud, which demonstrates a wordcloud using a PackedLayout.
Added samplesTS/minimalModule, which demonstrates using GoJS as an ES6 module. (Source is TS only)
Added OverviewResizing, which demonstrates the OverviewResizingTool, used for resizing an Overview.box. This has replaced functionality that used to be built-in. It is defined in both the "extension" and "extensionsTS" folders.
Added extensionsTS/ZoomSlider, which demonstrates an HTML slider that can zoom in/out of a GoJS diagram.
Incompatible 2.0 changes and removals
Many of the minor changes were made to order to increase the modularity of the implementation. Nevertheless we have tried to maintain API compatibility with version 1.*.
Most Predefined Shape figures
In order to shrink the size of the GoJS library we no longer define most predefined figures in the library. Instead, you can find all of their definitions in the Figures.js file. You can load this file or simply load only those figures that you want to use by copying their definitions into your code. For example, the Shapes sample loads this file.
A number of very common figures remain predefined in version 2.0. The figures that remain in 2.0 are: "Rectangle", "Square", "RoundedRectangle", "Border", "Ellipse", "Circle", "TriangleRight", "TriangleDown", "TriangleLeft", "TriangleUp", "Triangle", "Diamond", "LineH", "LineV", "BarH", "BarV", "MinusLine", "PlusLine", "XLine".
Note also that the definitions that are in the Figures.js file are not entirely the same as their definitions in version 1.*. A number of figures have been improved and some figure parameters have been added or changed meaning. To use the old predefined figures, you can load or copy from the "extensions/Figures.js" file of an earlier version of GoJS.
List, Set, and Map constructors no longer take type arguments, but are generic in TypeScript
The GoJS List, Set, and Map constructors no longer take type arguments and no longer do type checking in JavaScript. However, when using TypeScript these classes are now generic and will do type checking at compile time.
In JavaScript, instead of new go.List(go.Point), write new go.List(). For compatibility, you can still provide an element type argument, but it is not used and not checked.
In TypeScript, instead of new go.List(go.Point), write new go.List<go.Point>(), and the TypeScript compiler will enforce the List element typing.
All three constructors now take an optional Iterable or Array argument that provides the initial elements for the new collection.
In a future major version, we may replace go.Map and go.Set with enhanced ES6 Map and Set classes.
List.add, Set.add, and Map.add now all return the collection itself instead of a boolean. This is for increased compatibility with ES6 Map and Set collections.
Panel.type used to be of type EnumValue and now is of type PanelLayout.
This may affect data-bindings, in the uncommon case where a template binds Panel.type. You should make sure that any data bindings are returning possible type values such as go.Panel.Horizontal. Data binding Panel.type without using a conversion function will not work with old data, since the property has changed type.
For Spot Panels, the offsetX/offsetY of GraphObject.alignmentFocus has been reversed.
If you are using the offsetX/offsetY values in GraphObject.alignmentFocus, this may cause your panels to be arranged differently. You will need to flip the sign to retain compatibility.
This change is to rectify a design inconsistency with Spot Panel elements. The offsetX/offsetY values now correctly offset the alignment focal point, and not the Spot Panel's element itself.
CommandHandler.defaultScale has been moved to Diagram.defaultScale As with many of the other properties and methods that have been "moved" to other classes, this is to improve the ability to tree-shake code out of your app.
DiagramEvent.cancel
The only use for this property was with the "SelectionDeleting" DiagramEvent in order to prevent the user from deleting the selection. Where one might have written this Diagram listener:
"SelectionDeleting": function(e) {
if (e.diagram.selection.any(function(p) { return p.data.key.indexOf("e") >= 0; })) {
e.cancel = true;
}
}
one can write the equivalent functionality with this CommandHandler.canDeleteSelection method override:
"commandHandler.canDeleteSelection": function() {
return !this.diagram.selection.any(function(p) { return p.data.key.indexOf("e") >= 0; })
&& go.CommandHandler.prototype.canDeleteSelection.call(this);
}
Overriding the method supports the updating/enablement of commands that call CommandHandler.deleteSelection. Furthermore not having a "cancel" property on the DiagramEvent avoids any potential problems that might occur if there are multiple listeners for the "SelectionDeleting" event. The "SelectionDeleting" DiagramEvent remains useful, but not for controlling whether or not the deletion should happen.
Button styling
Updated the styling of buttons. Buttons are now rounded rectangles and have an effect when pressed. Some predefined buttons have increased a small amount in size:
TreeExpanderButton: 3 pixels wider and taller
SubGraphExpanderButton: 3 pixels wider and taller
PanelExpanderButton: 3 pixels wider and 5 pixels taller
Definitions for buttons can be found in the Buttons.js file.
Improved computation of Link.midPoint and Link.midAngle to be faster and changed some cases where labels fell on very small segments of a link. Orthogonal bezier links will also have more accurate label placement with the new methods.
Diagram.initialContentAlignment's default value of Spot.Default now acts like Spot.Center, instead of Spot.None. Basically, if you don't set Diagram.initialContentAlignment, the contents will now show up in the middle of the viewport rather than at the top-left corner.
Custom TextEditingTools (the values of TextEditingTool.currentTextEditor and TextBlock.textEditor) can no longer be set to HTML Elements. They must be an instance of HTMLInfo, which was introduced in version 1.7.
The ResizingTool, when computing a cell size ResizingTool.computeCellSize, no longer checks the DraggingTool's possible grid snapping cell size. As with many of the other properties and methods that have been "moved" to other classes, this is to improve the ability to tree-shake code out of your app.
Swapped the order of the RotatingTool and ResizingTool in the ToolManager.mouseDownTools list. This is to cause the RotatingTool's Adornment to be behind the ResizingTool's Adornment if both are present.
Moved the OverviewResizingTool, which had been completely internal, out of the core library into an extension. The Overview.box can no longer be resized unless OverviewResizingTool has been loaded.
Removed GraphObject.fromEndSegmentDirection and GraphObject.toEndSegmentDirection. One can override Link.getLinkDirection to achieve the same effects.
Changed Link.getLinkPoint to treat a GraphObject.fromSpot or GraphObject.toSpot with Spot.x and Spot.y exactly 0.5 (but with any Spot.offsetX and Spot.offsetY) as if it were Spot.None but focussing on that spot. This allows for links to stop at the edge of a shape while going towards a point other than the center of the port. In the past the link direction for spots at (0.5, 0.5) was always assumed to be zero, going rightwards to or from the port, which was not intuitive or useful.
The DiagramEvent.subject for "SelectionMoved" and "SelectionCopied" DiagramEvents is now a Set of the moved or of the newly copied Parts, not just the Diagram.selection. This makes it easier to find the unselected Parts that were moved or copied.
The LayoutNetwork constructor and constructors for subclasses of LayoutNetwork now require the Layout as the first argument. This was needed for better code, to avoid potential null references.
The LayoutVertex and LayoutEdge constructors and constructors for subclasses of LayoutVertex and LayoutEdge now require the LayoutNetwork as the first argument. This was needed for better code, to avoid potential null references.
Placeholders in Groups now take up zero size when collapsed, even when there is padding in the Placeholder. You can add a GraphObject.margin on the Placeholder or specify its GraphObject.minSize to make sure that has a size when collapsed. Placeholders in Groups now respect GraphObject.minSize.
Layout.isRealtime is now tri-state, with possible values being true, false, or null. The default is now null. A null value is treated as true for a Diagram.layout but false for a Group.layout. This reduces the number of situations where there can be surprising layout behavior when moving or resizing member nodes, while continuing to support explicit control of this property.
Diagram.scrollsPageOnFocus has changed its default value from true to false. This avoids an occasional end-user complaint.
Diagram.allowDrop has changed its default value from false to true. This helps avoid a common error when starting to use a Palette or a second Diagram.
Overviews now include the observed diagram's viewport bounds so the Overview.box will always be visible. This reduces confusion that some end-users experience.
Tool.doCancel now sets Tool.transactionResult to null before calling Tool.stopTool, in order to cause any call to Tool.stopTransaction to roll-back any transaction.
Only for V.I.P
Warning! You are not allowed to view this text.