Using Flexbox Layout to Arrange Diagram Components in React

This tutorial demonstrates how to use the flexbox layout to arrange the various diagram controls that come with the diagram library for React. The controls we will arrange are DiagramView , NodeListView , Ruler , Overview, Zoomer and Ruler. This is a screenshot of the final application:

We build our project using the React framework and MindFusion diagram library for React available from

I. Initial Project Setup

We open a terminal and navigate to the folder where we want to create our application. We use create-react-app to initialize an empty React application:

npx create-react-app flex-diagram

As you we have named our application flex-diagram. Once the initial React setup is complete, we install the diagram:

npm install diagram-library-react

Once we are done with that we can start coding our application. We add a new JavaScript file, which we name DiagramApp.js. In it we first import the default React namespace and declare a member import of the Component class. Then we declare default import of MindFuson’s diagram library under the name ‘mf’. Finally, we declare member imports of the control classes we intend to use: DiagramView, Overview, NodeListView, ZoomControl and Ruler:

import React, { Component } from 'react';
import mf from 'diagram-library';
import { DiagramView, Overview, NodeListView, ZoomControl, Ruler } from 'diagram-library-react';

Then we can create our class DagramApp, which extends component. We will need a constructor, so we declare one. In it we create an instance of the Diagram class, which represents the diagram. Note that this is not the DiagramView for React class, which renders the diagram. This is the interactive, diagram, which is actually rendered by DiagramView.

class DiagramApp extends Component {
  constructor(props) {

    // create the diagram
    var diagram = new mf.Diagramming.Diagram();

Then we create an array of ShapeNode instances, which will be used by the NodeListView control. Again, the NodeListView is a UI component that renders the nodes, but it does not create them. They are provided to it as a parameter.

var nodes = [];
    var shapes = ["Actor", "RoundRect", "Triangle", "Decision"];
    for (var i = 0; i < shapes.length; ++i) {
      var node = new mf.Diagramming.ShapeNode(diagram);


We create an array just with the id-s of the ShapeNode -s, which we will use as labels for them as well. You can check the id-s of the available predefined ShapeNode -s at

Finally, we need to store the diagram, together with the nodes and the shape id-s in the React state. We will need them when we create the HTML for our application. In React, the way to access class variables is to store them in the state.

    this.state = {
      diagram: diagram,
      nodes: nodes,
      captions: shapes

II. Arranging the UI with CSS and the Flexbox Layout

Our flexbox layout has this structure:

We have colored the different areas of the page in different colors to show you the sections in the flexbox layout. The main container takes 100% of the space e.g. the whole page. We fix its height to be at least 500px. The layout of the flexbox is row without wrap, which means that the elements will not be rearranged in severa rows by resize. That is exactly what we need. Here is the code of the container style:

  display: flex;
  flex: 1 1 100%;
  min-height: 500px;
  flex-flow: row nowrap;
  background-color: azure;

The first item in the container is the vertical column where we want to place the Overview and NodeListView controls under each other. This column needs to stay fixed size. We do not want it resized when the user resizes the page. It is the diagram in the middle that must be resized when the available space changes. We call the column “left-sidebar” and set its ‘flex-flow’ to column. We use again no wrap to stop the layout placing the two controls next to each other, if the available space gets too short. We also fix the width of this element to 200 pixels, which suits our controls fine.

  flex: 0 0 200px;
  display: flex;
  flex-flow: column nowrap;
  background-color: beige;

There is difference in how we want the Overview an NodeListView controls to take space. The overview requires fixed amount of space. We want the extra space to be given to the NodeListView. That is why we add one more style to be applied to it:

.item {
  align-self: stretch;
  flex: 1 1 300px;  

We give 1 as a value to flex-grow and flex-shrink, indicating that we expect this element to get resized rather than the other items in the right column.

We are ready to deal with the diagram now, which is in the middle. Here it is important to indicate that this element will stretch to take all the available place. Moreover, when the space gets smaller, it is this item that must shrink:

.center-area {
     align-self: stretch;
     flex: 10 10 500px;
     max-height: 800px;
     overflow: hidden;

We set big values to the flex-grow and ‘flex-shrink’ attributes and set the flex-basis to 500 px. We must restrict the height of the diagram to 800px, because it could get really long. Important attribute it ‘align-self’, which is applied to items arranged by flexbox containers, not to the container itself. Here we use this attribute to tell the diagram to stretch itself, when space is available. The overflow attribute is hidden to avoid rendering of needless scrollbars in large diagrams.

Finally, the right sidebar will host the Zoom control. It is similar to the left sidebar, but it does not have a ‘special’ item such as the NodeListView. The Zoom control is a UI control with fixed size and does not need special handling. We just need to make sure no extra space is diverted to it, if the window gets too big:

  flex: 0 0 50px;
  background-color: lavender;  

And that was the last style for the last element that we need to define. Now we are ready to apply those styles to the real React components and arrange them.

III. The ‘render’ Method

The first thing we declare in the ‘render’ method of our new DiagramApp React component are some properties:

 var props = {
      "id": "diagram1",
      "linkHeadShapeSize": 2,
      "routeLinks": true,
      "roundedLinks": true,
      "backBrush": "#e0e9e9"

These are properties for the Diagram instance and we will provide them through the JavaScrpt spread operator. Then in the return statement we first declare the container div element. Its style is “container”. In it we declare the left sidebar, which will hold the overview and the NodeListView. We declare them as well:

return (      

        <div className="container">
            <div className="left-sidebar">
              <Overview diagram={this.state.diagram}></Overview>  
  		<NodeListView className="item" 



The Overview is bound to the diagram, which we keep in the state object. The NodeListView requires list with the nodes and captions, if we want to have captions over nodes. We want and we have stored the nodes and the captions in state as well.

After that is turn for the diagram. It will take the central area and its class is ‘center-area’. In addition to Diagram, we will use the Ruler control as well. We place it first and nest the diagram inside it. We use the spread operator to assign to the diagram the properties, which we have initialize at the beginning of the method.

<div className="center-area">              
            <Ruler style={{ width: "100%", height:"800px" }}>
                <DiagramView diagram={this.state.diagram} 

Finally, we declare the right sidebar, which contains the Zoom control. The Zoom control also needs to be bound to a diagram instance and we use state to get reference to our diagram:

          <div className="right-sidebar">
          <ZoomControl diagram={this.state.diagram}></ZoomControl>        

With that our component is ready. We need only to place it in index.js instead of the default App Component:

import DiagramApp from './DiagramApp';


We can run the sample with

npm start

Then you can see your application on port 3000 on localhost.

You can download the full code structured as npm project from this link:

Download Full Source Code

For technical question, please use the JS Diagram forum:

About Diagramming for JavaScript: This native JavaScript library provides developers with the ability to create and customize any type of diagram, decision tree, flowchart, class hierarchy, graph, genealogy tree, BPMN diagrams and much more. The control offers rich event set, numerous customization options, animations, graph operations, styling and themes. You have more than 100 predefined nodes, table nodes and more than 15 automatic layout algorithms. Learn more about Diagramming for JavaScript at

The CanvasLayer in JavaScript Maps

In this blog post we are going to use the CanvasLayer of the JavaScript map library to build a web page that renders a city map with overlay polygons of the districts, covered by various couriers of a company. Each area is a separate in different color. Here is the final result:

Canvas Layer in MindFusion Map Control

Continue reading

Pan and Zoom Programmatically in a JavaScript Diagram

We will build a diagram with 50 random nodes and we will zoom and pan this diagram programmatically. Here is a screenshot of the final diagram, which is a link to the sample:

We will use the MindFusion Diagramming library for JavaScript.

I. Project Setup

We add a reference to the MindFusion.Diagramming.js and MindFusion.Common.js files. We also add a reference to another file called MouseEvents.js. This is our code-behind file.

<script src="MindFusion.Common.js" type="text/javascript"></script>
<script src="MindFusion.Diagramming.js" type="text/javascript"></script>
<script src="MouseEvents.js" type="text/javascript"></script>

In the BODY of the web page we create a Canvas element, to which we assign an id. This is important, because we will refer to the Canvas in code:

<div style="width: 100%; height: 100%; overflow: auto;">
    <canvas id="diagram_canvas" width="2100" height="2100">
        This page requires a browser that supports HTML 5 Canvas element.

II. Diagram Settings

In the code-behind file that we called MouseEvents.js we use the DOMContentLoaded event to initialize the diagram.

document.addEventListener("DOMContentLoaded", function ()
    // create a Diagram component that wraps the "diagram_canvas" canvas
    diagram = MindFusion.AbstractionLayer.createControl(Diagram, null, null, null, document.getElementById("diagram_canvas"));
    diagram.setBounds(new Rect(5, 5, 2000, 1000));

We use the createControl method of the AbstractionLayer class to create an instance of the Diagram class. The setBounds method determines the size of the diagram’s drawing area. If this size is bigger than the size of the Canvas, the diagram automatically shows scrollbars. Note that only if the diagram’s area is larger than the canvas we can use panning.

We use some settings of the Diagram class to customize the application:


The links will be routed and rounded and no grid will be rendered.

III. Diagram Items

We create the diagram nodes with the createShapeNode method of the Factory class. The Factory class as an instance is available through the getFactory() method:
for(var i = 0; i < 50; i++)

        var colorIndex = Math.floor(Math.random() * 3);  
        var shape = diagram.getFactory().createShapeNode(new Rect(136, 36, 20, 10));
        shape.setBrush({ type: 'SolidBrush', color: colors[colorIndex] });
        if(i % 3   == 0)
        if( i % 7 == 0)
            shape.setBounds(new Rect(136, 36, 16, 8));	
        shape.setText("Node " + (i + 1).toString());

We make each third shape Ellipse and we choose the brush on a random principle out of three brushes, that we initialized in an array. Each seventh shape is slightly smaller – that is set with the setBounds method, which takes as an argument a Rect, that is slightly smaller than the Rect instance that we use when we create the shape nodes.

The connectors among the nodes are created with the createDiagramLink method of Factory . We cycle through all 50 nodes and connect each one of them with a randomly taken node from the diagram nodes collection. This collection is available through the nodes proeprty of the Diagram class:

    var nodeIndex = Math.floor(Math.random() * 50);  

    var node2 = diagram.nodes[nodeIndex];
    var link = diagram.getFactory().createDiagramLink(node, node2);

We customize the appearance of the link through the setHeadShape method. We choose the ‘Circle’ shape as a head to each link.

We have created the diagram items with the same bounds, which means they are on top of each other. The best way to arrange them is with one of the automatic layout algorithms, available with the JsDiagram. They are members of the MindFusion.Graphs namespace – you can check the rest. In our sample we’ve chosen the LayeredLayout ,which provides quite nice result. We set its direction to LayoutDirection .There a few other properties that we’ve set that regulate the node distance, the layer distance and more:

var layout = new MindFusion.Graphs.LayeredLayout();
layout.direction = MindFusion.Graphs.LayoutDirection.LeftToRight;
layout.siftingRounds = 0;
layout.nodeDistance = 8;
layout.layerDistance = 8;

All layouts are applies through the arrange method of the Diagram that takes an instance of the layout as an argument.

IV. Pan and Zoom

We will implement pan and zoom by handling standard DOM events. The first one is the “wheel” event, which we attach to the diagram canvas element:

var dgrm = document.getElementById('diagram_canvas');

dgrm.addEventListener('wheel', function(e)
    var zoom = diagram.getZoomFactor();
    zoom -= e.deltaY / 10;
    if (zoom > 10)

    e.preventDefault(); // do not scroll

We use the getZoomFactor and setZoomFactor methods of the Diagram , to manipulate the zoom ratio. The zoom step is calculated based on the deltaY value of the event args. You can command the amount of zoom by dividing by a smaller or a larger number. It is important that we call preventDefault() on the event arguments, to surpass the default response of the canvas to the wheel event.

The panning is implemented by handling the mousedown and mouseup DOM events of the Canvas.

/* events fired on the draggable target */
dgrm.addEventListener('mousedown', function(e)
 if( e.ctrlKey)
}, false);

dgrm.addEventListener('mouseup', function(e)
 if( e.ctrlKey)
}, false);

If we want to make the Diagram pan we need simply to change the diagram’s behavior with the setBehavior method. The options are members of the Behavior enumeration. When the user clicks on the Diagram and the Ctrl key is pressed, we change the diagram’s behavior to “Pan”. When the mouse is up, but the Ctrl key is pressed, we rest the behavior back to LinkShapes. This is the default behavior, where dragging with the mouse creates new shapes, while dragging between existing DiagramShape -s, creates DiagramLink -s.

With that our sample is ready. You can download the source code from this link:

Download the Mouse Events Sample with JavaScript Diagram

Technical support is available through MindFusion forum here.

About Diagramming for JavaScript: This native JavaScript library provides developers with the ability to create and customize any type of diagram, decision tree, flowchart, class hierarchy, graph, genealogy tree, BPMN diagrams and much more. The control offers rich event set, numerous customization options, animations, graph operations, styling and themes. You have more than 100 predefined nodes, table nodes and more than 15 automatic layout algorithms. Learn more about Diagramming for JavaScript at

Tree with Nodes that Have Multiple Parents

Most tree structures are built as hierarchies: the number of nodes increases at each level. In our sample we will look at a tree, where not all branches have a higher number of nodes than their predecessors. In our tree some nodes will have multiple parents e.g. there are nodes that have several ancestors.

You can try the sample online:

In order to build this application we use MindFusion Diagramming for JavaScript library.

I. General Settings

In a web page we add the code that initializes a Canvas. We give the Canvas an id:

<div style="overflow: visible; height: 100%; margin: 1px; padding: 0px;">
    <canvas id="diagram" width="2100" height="2500">
        This page requires a browser that supports HTML 5 Canvas element.

We add references to the two JavaScipt files that provide the diagramming functionality: MindFusion.Diagramming and MindFusion.Common. We also add a reference to a code-behind file that contains the JavaScript code for our application:

<script src="Scripts/MindFusion.Common.js" type="text/javascript"></script>
<script src="Scripts/MindFusion.Diagramming.js" type="text/javascript"></script>
<script src="MultipleParentNodes.js" type="text/javascript"></script>

We have placed those files in a subfolder called Scripts, which is located in our main application folder.

II. Diagram Settings

We create the diagram in the window.onload event handler. We want to be sure that all scripts are loaded:

window.onload = function(e)
    var diagramEl = document.getElementById('diagram');
    // create a Diagram component that wraps the "diagram" canvas
    diagram = AbstractionLayer.createControl(Diagram, null, null, null, diagramEl);
    diagram.setBounds(new Rect(0, 0, 2000,2500));

We create the Diagram using a reference to the DOM element of the Canvas from the web page. We set its allowInplaceEdit property to true, which lets users edit interactively nodes and links. We use showGrid to render a background grid that helps to align nodes and links. We setRoundedLinks and give the diagram a big work are with the setBounds method.

II. Creating the Diagram Nodes

We create the DiagramNode -s in a separate method, which we call after the control is created and all settings are made:

function onLoaded()
    var nodes = {};

    for(var i = 0; i < 5; i++)
        nodes[i] = diagram.getFactory().createShapeNode(new Rect(20, 20, 20, 12));
        nodes[i].setBrush({ type: 'SolidBrush', color: '#567939' });

We initialize a list, where we will store dynamically those nodes that we want to have reference to. At first we create 5 ShapeNode -s that are the first level of the tree. We use the createShapeNode method of Factory to create the ShapeNode -s and DiagramLink -s. Note that we will create all nodes with equal bounds. We don’t have to worry about their location because we will apply an automatic layout at the end.

Factory is available through the getFactory method of Diagram You do not usually create the class but get an instance of it through the Diagram instance.

We use setShape to provide the id af the diagram shape that we want the node to take. A list with the diagram shapes available, together with their id-s can be found in the online help.

We also use setBrush to specify the fill of the ShapeNode . In our case we use a SolidBrush ,but there are other options to choose from.

We create then a single ShapeNode that will be the next level:

var node5 = diagram.getFactory().createShapeNode(new Rect(20, 20, 20, 12 ));
node5.setBrush({ type: 'SolidBrush', color: '#6f9c49' });

We color it in a slightly lighter shade of green than the nodes at the first level. We then use the Factory class once again to create the DiagramLink -s between the 5 nodes at the first level and this one single node at the second level:

    for(var i = 0; i < 5; i++)
        var link = diagram.getFactory().createDiagramLink(nodes[i], node5);	
        link.setHeadBrush({ type: 'SolidBrush', color: '#7F7F7F' });

The setText and setHeadShape methods of the DiagramLink class allow us to specify the label of the link and its shape at the end. There is also setBaseShape that allows us the specify the shape at the start of the DiagramLink.

The lovely thing about the Factory class is that it adds automatically the newly created DiagramItem -s, such as nodes and links, to the items collection of the diagram. You can find the newly created DiagramNode -s and DiagramLink -s also as members of the nodes and links collections respectively.

Now we have 5 links coming from all 5 nodes from the first level that point to the second level:

Node with Multiple Parents

We go on doing the rest of the diagram in the same way. We create ShapeNode -s with Factory and then bind the nodes with Factory .

III. Layout

We use the LayeredLayout to arrange all nodes of the diagram. Since the diagram is not a typical tree, we prefer the LayeredLayout to the TreeLayout

var lLayout = new MindFusion.Graphs.LayeredLayout();

It is really easy to apply any other algorithm on the diagram – you just need to create an instance of it and call the arrange method of your diagram to apply this instance. You can quickly change layouts and experiment to see which one provides the best result.

In our case the LayeredLayout looks fine and with this we are done building the tree.

You can download the sample together with all libraries used from the following link:

A JavaScript Graph with Nodes that Have Multiple Parents

Technical support is available through MindFusion forum here.

About Diagramming for JavaScript: This native JavaScript library provides developers with the ability to create and customize any type of diagram, decision tree, flowchart, class hierarchy, graph, genealogy tree, BPMN diagrams and much more. The control offers rich event set, numerous customization options, animations, graph operations, styling and themes. You have more than 100 predefined nodes, table nodes and more than 15 automatic layout algorithms. Learn more about Diagramming for JavaScript at