{"id":3133,"date":"2026-02-19T14:08:07","date_gmt":"2026-02-19T14:08:07","guid":{"rendered":"https:\/\/mindfusion.dev\/blog\/?p=3133"},"modified":"2026-02-20T08:27:54","modified_gmt":"2026-02-20T08:27:54","slug":"creating-an-interactive-engineering-diagram-app-with-mindfusion-diagramming-for-javascript","status":"publish","type":"post","link":"https:\/\/mindfusion.dev\/blog\/creating-an-interactive-engineering-diagram-app-with-mindfusion-diagramming-for-javascript\/","title":{"rendered":"Creating an Interactive Engineering Diagram App in JavaScript"},"content":{"rendered":"\n<p>In this post, we&#8217;ll walk through the process of building a web-based electrical diagram application. This tool allows users to create, modify, and save circuit and home appliance diagrams. We&#8217;ll use the<a href=\"https:\/\/mindfusion.dev\/javascript-diagram.html\">.Diagramming for JavaScript<\/a>,  and its ability to support SVG images in modes, various arrow head shapes on links, save and load of flowcharts to\/from various formats.<\/p>\n\n\n\n<p>The final application will feature:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A diagram view that supports pan and zoom.<\/li>\n\n\n\n<li>A palette of pre-defined SVG nodes representing various engineering components, separated into logical sections.<\/li>\n\n\n\n<li>The ability to save the current diagram to a JSON file and load it back.<\/li>\n\n\n\n<li>Real-time style customization for text, links, and more.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2026\/02\/electricity_schema.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"429\" src=\"https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2026\/02\/electricity_schema.webp\" alt=\"A circuit schema created with MindFusion Diagramming library for JavaScript\" class=\"wp-image-3136\" srcset=\"https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2026\/02\/electricity_schema.webp 800w, https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2026\/02\/electricity_schema-300x161.webp 300w, https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2026\/02\/electricity_schema-768x412.webp 768w, https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2026\/02\/electricity_schema-500x268.webp 500w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><\/figure>\n\n\n<p><!--more--><\/p>\n\n\n<h2 class=\"wp-block-heading\">Project Setup<\/h2>\n\n\n\n<p>First, let&#8217;s set up the project structure. We need a simple web server to serve our HTML, JavaScript, and asset files.<\/p>\n\n\n\n<p><strong>File Structure:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\n|-- index.html\n|-- index.js\n|-- server.js\n|-- package.json\n|-- icons\/\n|   |-- resistor.svg\n|   |-- capacitor.svg\n|   |-- ... (and other component SVGs)\n|-- scripts\/\n|   |-- diagramming.js\n|   |-- ... (MindFusion library files)\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">1. The Server (<code>server.js<\/code>)<\/h3>\n\n\n\n<p>We&#8217;ll use a basic Express.js server with <code>nodemon<\/code> and <code>reload<\/code> for live-reloading, which is great for development.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ server.js\nconst express = require('express');\nconst open = require('open');\nvar reload = require('reload')\n\nconst app = express();\nconst port = 3000;\n\napp.use(express.static(__dirname));\n\nreload(app).then(function () {\n  app.listen(port, function () {\n   console.log(`Server listening at http:\/\/localhost:${port}`);\n  })\n}).catch(function (err) {\n  console.error('Reload could not start, could not start server\/sample app', err)\n})\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. Dependencies (<code>package.json<\/code>)<\/h3>\n\n\n\n<p>Our <code>package.json<\/code> defines the dependencies and a convenient start script.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"name\": \"engineering-diagram-app\",\n  \"version\": \"1.0.0\",\n  \"scripts\": {\n    \"start\": \"start http:\/\/localhost:3000 &amp;&amp; nodemon -e js,html server.js\"\n  },\n  \"dependencies\": {\n    \"express\": \"^4.17.1\",\n    \"open\": \"^8.4.0\"\n  },\n  \"devDependencies\": {\n    \"nodemon\": \"^3.1.10\",\n    \"reload\": \"^3.4.2\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>To get started, run <code>npm install<\/code> to download the dependencies, then <code>npm start<\/code> to launch the server. The application shall be accessible on port 3000 at localhost.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Building the UI (<code>index.html<\/code>)<\/h2>\n\n\n\n<p>The HTML file lays out the different components of our application. We define <code>div<\/code> and <code>canvas<\/code> elements that will host the main diagram, an overview panel, a palette, a zoom control, and the ruler component. The size and position of the elements determine the size and position of the diagram controls &#8211; that&#8217;s how the diagram library renders its UI.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- index.html --&gt;\n&lt;div id=\"content\"&gt;\n    &lt;div style=\"... width: 250px ...\"&gt;\n        &lt;!-- The Overview component --&gt;\n        &lt;canvas id=\"overview\" width=\"200\" height=\"200\"&gt;&lt;\/canvas&gt;\n        &lt;!-- The Palette component --&gt;\n        &lt;div id=\"palette\"&gt;&lt;\/div&gt;\n    &lt;\/div&gt;\n    &lt;div id=\"ruler\"&gt;\n        &lt;!-- The DiagramView component --&gt;\n        &lt;canvas id=\"diagram\" width=\"2100\" height=\"2100\"&gt;&lt;\/canvas&gt;\n    &lt;\/div&gt;\n    &lt;!-- The ZoomControl component --&gt;\n    &lt;div style=\"... top: 20px; right: 35px ...\"&gt;\n        &lt;canvas id=\"zoomer\"&gt;&lt;\/canvas&gt;\n    &lt;\/div&gt;\n&lt;\/div&gt;\n<\/code><\/pre>\n\n\n\n<p>We also include input controls for style customization, such as color pickers for text and links, and a number input for link thickness. When the value of an input control changes, the change is reflected on the given properties of the diagram elements.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Initializing the Diagram (<code>index.js<\/code>)<\/h2>\n\n\n\n<p>All our application logic resides in <code>index.js<\/code>. We start by initializing the <code>DiagramView<\/code> and <code>Diagram<\/code> objects when the DOM is loaded.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ index.js\nvar DiagramView = MindFusion.Diagramming.DiagramView;\nvar Diagram = MindFusion.Diagramming.Diagram;\n\nvar diagram = null;\n\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n    \/\/ create a DiagramView component that wraps the \"diagram\" canvas\n    var diagramView = DiagramView.create(document.getElementById(\"diagram\"));\n    diagram = diagramView.diagram;\n    diagram.allowUnconnectedLinks = true;\n\n    \/\/ ... other initial settings ...\n});\n\n<\/code><\/pre>\n\n\n\n<p>We need to get the DOM elements that represent the diagram controls and for that we use the getElementById method. Then we call the respective diagram methods to create the objects.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating a Rich Palette with SVG Nodes<\/h2>\n\n\n\n<p>The <a href=\"https:\/\/mindfusion.dev\/docs\/javascript\/diagramming\/T_MindFusion_Diagramming_Controls_Palette.htm\">Palette control<\/a> is crucial for a great user experience. Our <code>initPalette<\/code> function populates the palette with different categories of <a href=\"https:\/\/mindfusion.dev\/docs\/javascript\/diagramming\/CC_T_MindFusion_Diagramming_DiagramItem_0.htm\">DiagramItem<\/a> instances that can be dragged and dropped. They are separated in groups and the diagram API allows us to specify for each section if it appears initially expanded or collapsed.<\/p>\n\n\n\n<p><strong>1. SVG Nodes:<\/strong><br> We use <code><a href=\"https:\/\/mindfusion.dev\/docs\/javascript\/diagramming\/T_MindFusion_Diagramming_SvgNode_Members_0.htm\">SvgNode<\/a><\/code> to create nodes from our external SVG files. We iterate through a list of filenames and create a node for each, adding it to the &#8220;Electrical Circuit&#8221; or &#8220;Home Appliances&#8221; category.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ index.js\nfunction initPalette(palette) {\n    var SvgNode = MindFusion.Diagramming.SvgNode;\n    var SvgContent = MindFusion.Diagramming.SvgContent;\n\n    palette.addCategory(\"Electrical Circuit\");\n    var shapeFileNames = &#91;\"resistor.svg\", \"capacitor.svg\", \"inductor.svg\", ...];\n    var elCircuitNames = &#91;\"resistor\", \"capacitor\", \"inductor\", ...];\n\n    for (var i = 0; i &lt; shapeFileNames.length; ++i) {\n        var node = new SvgNode(diagram);\n        node.transparent = true;\n        \n        var svg = new SvgContent();\n        svg.parse(\"icons\" + shapeFileNames&#91;i]);\n        node.content = svg;\n        palette.addItem(node, \"Electrical Circuit\", elCircuitNames&#91;i]);\n    }\n    \/\/ ... similar loop for \"Home Appliances\" ...\n\n        \/\/ expand the first accordion item (Electrical Circuit category)\n\tpalette.collapseItems(palette.items.item(2));\n\tpalette.expandItems(palette.items.item(3));\n\tpalette.expandItems(palette.items.item(0));\n}\n<\/code><\/pre>\n\n\n\n<p>Note that the DiagramNode-s are created <a href=\"https:\/\/mindfusion.dev\/docs\/javascript\/diagramming\/P_MindFusion_Diagramming_ShapeNode_transparent_0_1.htm\">transparent<\/a> with the help of the same-name property.<\/p>\n\n\n\n<p><strong>2. Link Nodes:<\/strong><br>\nWe can also add pre-styled links to the palette. Here, we create several types of electrical connectors.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ index.js -&gt; initPalette\npalette.addCategory(\"Electrical Connectors\");\nvar linkHeadShapes = &#91;\"\", \"Circle\", \"Triangle\"];\n\nfor(var i = 1; i &lt;= linkHeadShapes.length; i++)\n{\n    var link = new MindFusion.Diagramming.DiagramLink();\n    link.headShape = linkHeadShapes&#91;i-1];\n    \/\/ ... other styling ...\n    palette.addItem(link, \"Electrical Connectors\", \"connector \" + i);\n}\n<\/code><\/pre>\n\n\n\n<p>The diagram links by default are created only between nodes. In order to have links freely on the diagram we need to set the <a href=\"https:\/\/mindfusion.dev\/docs\/javascript\/diagramming\/P_MindFusion_Diagramming_Diagram_allowUnconnectedLinks_0_1.htm\">allowUnconnectedLinks<\/a> property to true:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ index.js -&gt; settings for the diagram\n\ndiagram.allowUnconnectedLinks = true;\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Save and Load Functionality<\/h2>\n\n\n\n<p>To persist users&#8217; work, we provide &#8220;Save&#8221; and &#8220;Load&#8221; buttons.<\/p>\n\n\n\n<p><strong>Saving a Diagram:<\/strong><br> The <code>onSaveClick<\/code> function serializes the diagram&#8217;s state into a JSON string using <code><a href=\"https:\/\/mindfusion.dev\/docs\/javascript\/diagramming\/M_MindFusion_Diagramming_Diagram_toJson_0.htm\">diagram.toJson()<\/a><\/code>. It then uses the browser&#8217;s File System Access API (<code>showSaveFilePicker<\/code>) to let the user save the JSON to a local file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ index.js\nasync function onSaveClick() {\n    const json = diagram.toJson();\n    \n    if (window.showSaveFilePicker) {\n        const handle = await window.showSaveFilePicker({\n            suggestedName: 'diagram.json',\n            types: &#91;{\n                description: 'JSON Files',\n                accept: { 'application\/json': &#91;'.json'] },\n            }],\n        });\n        const writable = await handle.createWritable();\n        await writable.write(json);\n        await writable.close();\n    }\n    \/\/ ... fallback for older browsers ...\n}\n<\/code><\/pre>\n\n\n\n<p><strong>Loading a Diagram:<\/strong><br>Conversely, <code>onLoadClick<\/code> allows the user to select a JSON file, reads its text content, and uses <code><a href=\"https:\/\/mindfusion.dev\/docs\/javascript\/diagramming\/M_MindFusion_Diagramming_Diagram_fromJson_1_String.htm\">diagram.fromJson()<\/a><\/code> to restore the diagram state.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ index.js\nasync function onLoadClick() {\n    if (window.showOpenFilePicker) {\n        const &#91;handle] = await window.showOpenFilePicker(\/* ... *\/);\n        const file = await handle.getFile();\n        const content = await file.text();\n        diagram.fromJson(content);\n    }\n    \/\/ ... fallback for older browsers ...\n}\n<\/code><\/pre>\n\n\n\n<p>Note something important: the .fromJson() method expects a plain string as input, you should not parse the JSON beforehand.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Loading the Initial Diagram<\/h2>\n\n\n\n<p>To provide a default view, we automatically load a diagram from a <code>diagram.json<\/code> file on startup. We use the <code>fetch<\/code> API to get the file content as a string and load it using the diagram&#8217;s <code>fromJson<\/code> method.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ index.js, inside DOMContentLoaded\nfetch('diagram.json')\n    .then(response =&gt; response.text())\n    .then(data =&gt; {\n        diagram.fromJson(data);\n    })\n    .catch(error =&gt; {\n        console.error('Error loading diagram.json:', error);\n    });\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Dynamic Style Customizations<\/h2>\n\n\n\n<p>Finally, we empower users to customize the look of their diagrams. We have UI controls for text color, link color, and link thickness.<\/p>\n\n\n\n<p>Event listeners on these controls update default style variables and apply changes to the currently selected items in the diagram.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ index.js\nconst linkColorPicker = document.getElementById('linkColorPicker');\n\nlinkColorPicker.addEventListener('change', (event) =&gt; {\n    defaultLinkStrokeColor = event.target.value;\n    \/\/ Apply to all selected links\n    diagram.selection.links.forEach(link =&gt; {\n        link.stroke = defaultLinkStrokeColor;\n        link.headStroke = defaultLinkStrokeColor;\n    });\n});\n<\/code><\/pre>\n\n\n\n<p>Furthermore, we use the diagram&#8217;s <code><a href=\"https:\/\/mindfusion.dev\/docs\/javascript\/diagramming\/P_MindFusion_Diagramming_Events_nodeCreated_0.htm\">nodeCreated<\/a><\/code> and <code><a href=\"https:\/\/mindfusion.dev\/docs\/javascript\/diagramming\/P_MindFusion_Diagramming_Events_linkCreated_0.htm\">linkCreated<\/a><\/code> events to ensure that any new items drawn by the user automatically get the currently selected default styles.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ index.js\ndiagram.linkCreated.addEventListener(\n    (sender, args) =&gt;\n    {\t\t\n        args.link.stroke = defaultLinkStrokeColor;\n        args.link.strokeThickness = defaultStrokeThickness;\n        \/\/ ... and so on\n    });\n<\/code><\/pre>\n\n\n\n<p><h2 class=\"wp-block-heading\">Source Code Download<\/h2><\/p>\n\n\n\n<p class=\"has-text-align-center\"><a href=\"https:\/\/mindfusion.dev\/samples\/javascript\/diagram\/engineering.zip\">Interactive Electrical Circuit Diagram App in JavaScript &#8211; Full Source Code Download<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>With<a href=\"https:\/\/mindfusion.dev\/javascript-diagram.html\"> MindFusion.Diagramming for JavaScript<\/a>, we&#8217;ve built a feature-rich engineering diagram application with a surprisingly small amount of code. We&#8217;ve seen how to set up a project, create a palette of complex SVG nodes, handle serialization to and from JSON, and implement dynamic styling. This foundation can be easily extended with more components, features, and integrations.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post, we&#8217;ll walk through the process of building a web-based electrical diagram application. This tool allows users to create, modify, and save circuit and home appliance diagrams. We&#8217;ll use the.Diagramming for JavaScript, and its ability to support SVG &hellip; <a href=\"https:\/\/mindfusion.dev\/blog\/creating-an-interactive-engineering-diagram-app-with-mindfusion-diagramming-for-javascript\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[95,513,74],"tags":[750,751,749,4,80,654],"class_list":["post-3133","post","type-post","status-publish","format-standard","hentry","category-diagramming-2","category-javascript","category-sample-code","tag-circuit-diagram","tag-electricity-schema","tag-engineering","tag-flowchart","tag-javascript","tag-tutorial"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3RlKs-Ox","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/3133","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/comments?post=3133"}],"version-history":[{"count":11,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/3133\/revisions"}],"predecessor-version":[{"id":3145,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/3133\/revisions\/3145"}],"wp:attachment":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/media?parent=3133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/categories?post=3133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/tags?post=3133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}