DEV Community

Cover image for Getting Started: Building Your First Interactive JavaScript Diagram
Iva Panayotova
Iva Panayotova

Posted on • Originally published at mindfusion.dev

Getting Started: Building Your First Interactive JavaScript Diagram

In this guide, we'll walk through the steps to build a minimal but powerful JavaScript diagramming application from scratch. Here's a sneak peek at what you'll create:

An interactive JavaScript diagramming application

Our finished app will use the MindFusion JavaScript Diagram library to allow users to:

  • Create flowchart shapes with drag-and-drop.
  • Customize node and link colors in real-time.
  • Edit text directly within diagram elements.
  • Save the current diagram to a file and load it back.

Ready? Let's dive in!

Setting Up the Project

To save time, we'll build upon a ready-made starter project from MindFusion. It provides a solid foundation with a pre-configured vanilla JavaScript environment.

First, clone the project from GitHub and start the development server:

# Clone the repository
git clone https://github.com/MindFusionComponents/diagram-starter-vanilla

# Navigate into the project directory
cd diagram-starter-vanilla

# Install dependencies
npm install

# Start the local server
npm start
Enter fullscreen mode Exit fullscreen mode

Once running, you'll see the basic starter application, which includes a diagram canvas, an overview panel, a shape palette, and zoom controls.

The starter JavaScript diagram allication

The backend is a simple Express server (server.js) that serves the static files. Our main focus will be on the frontend in index.html and index.js.

Initializing the Diagram Components

The diagram and its related UI components are initialized in index.js. Each component is tied to an HTML element (a <canvas> or <div>) in index.html.

For example, the main DiagramView is created by associating it with a <canvas> element with the ID "diagram":

// create a DiagramView component that wraps the "diagram" canvas
var diagramView = MindFusion.Diagramming.DiagramView.create(document.getElementById("diagram"));
var diagram = diagramView.diagram; 
Enter fullscreen mode Exit fullscreen mode

Similarly, the Overview and Palette components are linked to their respective elements:

// create an Overview component
var overview = MindFusion.Diagramming.Overview.create(document.getElementById("overview"));
overview.diagramView = diagramView;

// The Palette component lets users create shapes via drag-and-drop
var palette = MindFusion.Diagramming.Controls.Palette.create(document.getElementById("palette"));
Enter fullscreen mode Exit fullscreen mode

We can easily add predefined shapes to the palette. The code below adds a "Flowchart Shapes" category and populates it with common shapes like Start, Input, Process, and Decision.

palette.addCategory("Flowchart Shapes");
var shapes = ["Start", "Input", "Process", "Decision"];
for (var i = 0; i < shapes.length; ++i) {
    var node = new MindFusion.Diagramming.ShapeNode();
    node.shape = shapes[i];
    palette.addItem(node, "Flowchart Shapes", shapes[i]);
}
Enter fullscreen mode Exit fullscreen mode

Implementing Save and Load

The library makes saving and loading straightforward with the toJson() and fromJson() methods. The onSaveClick function serializes the diagram content to a JSON string and prompts the user to save it as a file.

The function cleverly handles both modern browsers that support the File System API (window.showSaveFilePicker) and older ones by creating a temporary download link.

async function onSaveClick() {
    try {
        const json = diagram.toJson();

        // For modern browsers with File System API
        if (window.showSaveFileFilePicker) {
            const handle = await window.showSaveFilePicker({
                suggestedName: 'diagram.json',
                types: [{
                    description: 'JSON Files',
                    accept: { 'application/json': ['.json'] },
                }],
            });
            const writable = await handle.createWritable();
            await writable.write(json);
            await writable.close();
        } else {
            // Fallback for older browsers
            const blob = new Blob([json], { type: 'application/json' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'diagram.json';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        }
    } catch (err) {
        console.error(err.name, err.message);
    }
}
Enter fullscreen mode Exit fullscreen mode

When loading, you simply read the JSON file's content and pass the string directly to diagram.fromJson().

Real-Time Node and Link Styling

We added UI controls to index.html to handle real-time color changes. These are simple <input type="color"> elements that use the browser's built-in color picker.

Adjusting the color of nodes and links

We then listen for the change event on these inputs. When a new color is selected, we update a global variable and apply the new color to all currently selected nodes.

// New global variables for default styles
var defaultNodeBrushColor = '#e0e9e9';

// Get style control elements
const nodeColorPicker = document.getElementById('nodeColorPicker');

// Event listener for the node color picker
nodeColorPicker.addEventListener('change', (event) => {
    defaultNodeBrushColor = event.target.value;

    // Apply the new color to all selected nodes
    diagram.selection.nodes.forEach(node => {
        node.brush = defaultNodeBrushColor;
    });
});
Enter fullscreen mode Exit fullscreen mode

To ensure new nodes also use this color, we handle the nodeCreated event and assign the defaultNodeBrushColor to the newly created node.

// Handle the nodeCreated event to apply default styles
diagram.nodeCreated.addEventListener((sender, args) => {
    args.node.brush = defaultNodeBrushColor;
    // ... other style properties
});
Enter fullscreen mode Exit fullscreen mode

A pro-tip: handle the nodeCreating event as well. This provides a live preview of the node's appearance while the user is drawing it, creating a much smoother user experience.

Customizing Link Appearance

By default, the routeLinks property is enabled, which makes links automatically create perpendicular segments to avoid crossing nodes.

We can also control the link's head shape. In our app, a checkbox determines whether links have a "Triangle" arrowhead or not. We set the headShape property to null to remove it.

var defaultLinkHeadShape = 'Triangle';
const linkHeadCheckbox = document.getElementById('linkHeadCheckbox');

// Update the default shape when the checkbox is changed
linkHeadCheckbox.addEventListener('change', (event) => {
    defaultLinkHeadShape = event.target.checked ? 'Triangle' : null;

    // Apply the change to all selected links
    diagram.selection.links.forEach(link => {
        link.headShape = defaultLinkHeadShape;
    });
});
Enter fullscreen mode Exit fullscreen mode

Using Anchor Patterns for Clean Connections

To enforce cleaner-looking diagrams, we can restrict where links can connect to a node. This is done using an AnchorPattern. An anchor pattern is a set of AnchorPoint objects defined in relative coordinates (from 0 to 100) on the node's surface.

This pattern allows connections only at the center of each of the four sides:

var nodeAnchorPattern = new AnchorPattern([
    new AnchorPoint(50, 0, true, true),   // Center Top
    new AnchorPoint(100, 50, true, true), // Center Right
    new AnchorPoint(50, 100, true, true), // Center Bottom
    new AnchorPoint(0, 50, true, true)    // Center Left
]);

// ... later, when creating a node ...
node.anchorPattern = nodeAnchorPattern;
Enter fullscreen mode Exit fullscreen mode

With this pattern applied, links will snap cleanly to these connection points.

A node with AnchorPattern set in MindFusion JavaScript diagram library

Creating the Initial Diagram

To provide a good starting point for the user, we create a simple decision diagram in code when the page first loads. We use the diagram.factory object, which simplifies the creation of nodes and links.

var startNode = diagram.factory.createShapeNode(95, 10, 30, 15);
startNode.text = "Start";
startNode.shape = 'Ellipse';
startNode.brush = "#DB3955";
startNode.textColor = "#f0f0f0";
startNode.anchorPattern = nodeAnchorPattern;
Enter fullscreen mode Exit fullscreen mode

Nodes created with the factory are automatically added to the diagram's items collection.

Video Tutorial

This tutorial is also available as a video. Check it out here:

I truly hope this guide helps you kickstart your journey with interactive JavaScript diagrams! I crafted this tutorial to demystify the process and showcase how accessible powerful visualization tools can be. What kinds of diagrams are you looking to build for your projects? If you have any questions, encounter challenges, or simply want to share your thoughts, please don't hesitate to leave a comment below. I'd love to hear from you and spark some additional discussion!

Conclusion

And that's it! You've successfully built a feature-rich JavaScript diagramming application. We started with a basic template and added custom shapes, real-time styling, anchor points, and a predefined initial diagram.

You can download the final version of this project from this link: [https://mindfusion.dev/samples/javascript/diagram/diagram-starter-2026.zip]

Happy coding!


Further Resources:

Top comments (0)