<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Arthur Khokhlov</title>
    <description>The latest articles on Forem by Arthur Khokhlov (@geliogabalus).</description>
    <link>https://forem.com/geliogabalus</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F860993%2Faa276dce-9f5c-4b6f-b76a-3a05973e1fa0.jpg</url>
      <title>Forem: Arthur Khokhlov</title>
      <link>https://forem.com/geliogabalus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/geliogabalus"/>
    <language>en</language>
    <item>
      <title>Build better Claude Code Playgrounds with JointJS</title>
      <dc:creator>Arthur Khokhlov</dc:creator>
      <pubDate>Mon, 13 Apr 2026 13:59:19 +0000</pubDate>
      <link>https://forem.com/geliogabalus/build-better-claude-code-playgrounds-with-jointjs-i6a</link>
      <guid>https://forem.com/geliogabalus/build-better-claude-code-playgrounds-with-jointjs-i6a</guid>
      <description>&lt;p&gt;&lt;a href="https://claude.com/plugins/playground" rel="noopener noreferrer"&gt;Claude Code Playground plugin&lt;/a&gt; is fantastic. It allows you to build HTML UI explorers and visualize complex concepts in an intuitive, straightforward way. It gives you visual controls to craft natural-language prompts that work perfectly with AI, and it can even help you build mental models of complex data structures.&lt;/p&gt;

&lt;p&gt;But here’s the honest truth. The diagrams you’ll build in Claude Code Playground are solid but quite limited in interactivity. With a proper, dedicated diagramming library, you can make them interactive, more visually appealing, and more intuitive, drastically improving the Playground UI.&lt;/p&gt;

&lt;p&gt;In this article, you’ll learn how to enhance Claude Code Playgrounds with JointJS to turn static diagrams into fully interactive visual tools—draggable nodes, smarter routing, animated transitions, and more.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Keep in mind that you can reuse the concepts and ideas shown here whenever you want to bridge text and UI. If you want a better visual way to instruct AI agents, especially when you’re structuring data, designing flows, or tackling complex coding problems, JointJS Claude Playground lets you do exactly that.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/GSYSbJo6ras"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;How JointJS makes Claude Code Playgrounds better&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Claude Code Playgrounds are great, practical, and useful, but severely limited in handling complex data flows, visualizing data relationships, and creating architecture diagrams. &lt;/p&gt;

&lt;p&gt;Here’s an example of a playground generated with Code Map of Claude Code Playground. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1lc6zmcfbqlg2foc2hl5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1lc6zmcfbqlg2foc2hl5.png" alt=" " width="800" height="538"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An example of a static diagram created with Claude Code Playground.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/jointjs-codemap-claude-code.html" rel="noopener noreferrer"&gt;It’s a nice visual overview.&lt;/a&gt; You can click nodes, add comments, and zoom in and out. But it’s still not a truly interactive diagram.&lt;/p&gt;

&lt;p&gt;You can’t drag a node to reposition it to better fit your use case and understanding. You can’t do anything with links, so when they get tangled and overlapped, you’re stuck with trying to decipher the relations yourself. And this is still a relatively simple diagram, let alone an enterprise-grade one.&lt;/p&gt;

&lt;p&gt;But if you enhance this demo with JointJS, you can get a real interactive diagram that’s not only more intuitive but also much more practical.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/1181915177" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;em&gt;An example of a codemap created with the JointJS Claude Playground plugin. If an image is worth a thousand words, how much is an interactive demo concept worth? → &lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/jointjs-codemap.html" rel="noopener noreferrer"&gt;Live demo&lt;/a&gt;&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;The generated Code Map is massively improved if we enhance it with JointJS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Animated transitions make preset and layer changes visually clear.
&lt;/li&gt;
&lt;li&gt;Automatic zooming maximizes the use of the canvas after toggling presets or layers.
&lt;/li&gt;
&lt;li&gt;Different routers realign the entire link structure of the diagram on the fly and make connections clear and more intuitive.
&lt;/li&gt;
&lt;li&gt;Draggable nodes allow manual grouping while still maintaining clear relationships among elements.
&lt;/li&gt;
&lt;li&gt;Reset and Fit View controls give fine control over state and diagram positioning.
&lt;/li&gt;
&lt;li&gt;Highlighted paths to selected or hovered elements surface relationships between different nodes instantly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is still a single HTML file that you can directly open in your browser or share with others. It’s using the open source version of JointJS, so you don’t have to install any dependencies, and there are no build steps—it just works. &lt;/p&gt;

&lt;p&gt;To give you all the tools you need to create your own JointJS-enhanced Claude Code Playgrounds, we built a plugin you can use however you want. &lt;/p&gt;

&lt;p&gt;Need precise prompts to visualize data structures and user flows? Want a visual SQL, Regex, Cron, or decision-tree builder? Install the JointJS Claude Playground plugin, enter your prompt, and you will get a much better, interactive code playground.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;How to use the JointJS Claude Playground plugin&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;JointJS Claude Playground plugin is available on GitHub. To install it, you’ll need to add JointJS Marketplace (a concept Claude Code uses for third-party plugins) to Claude Code: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;`/plugin marketplace add https://github.com/clientIO/jointjs-claude-marketplace`&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Enable auto-updates for plugin marketplace&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Plugins from third-party marketplaces, such as JointJS, are not automatically updated, so you’ll need to enable this to always get the latest and best versions, including new features, potential security updates, and bug fixes.&lt;/p&gt;

&lt;p&gt;In Claude Code, run &lt;code&gt;/plugin\&lt;/code&gt; then go into &lt;code&gt;Marketplaces\&lt;/code&gt; tab, select &lt;code&gt;jointjs\&lt;/code&gt; marketplace and toggle &lt;code&gt;Enable auto-update\&lt;/code&gt; command. That way, you will automatically get the latest updates to JointJS plugins.&lt;/p&gt;

&lt;p&gt;When you add the JointJS marketplace, install the JointJS Playground Plugin:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;`/plugin install jointjs-claude-playground@jointjs`&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When the installation finishes, run &lt;code&gt;`/reload-plugins`&lt;/code&gt; command to enable the newly installed plugin.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I found &lt;code&gt;`/reload-plugins`&lt;/code&gt; to be unreliable, so you might need to restart Claude Code in your terminal—exit it and launch it again using &lt;code&gt;claude\&lt;/code&gt; if you don’t see &lt;code&gt;/jointjs\&lt;/code&gt; after installing and reloading the plugins.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;A potential problem with installing Claude Code plugins&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Note that there’s a bug in Claude Code where installing a Claude Code Plugin fails if you don’t have SSH keys configured on your system for GitHub.&lt;/p&gt;

&lt;p&gt;When installing a plugin, Claude Code clones the repository via SSH (&lt;code&gt;`git@github.com:…`&lt;/code&gt;), so if your GitHub SSH keys aren’t configured properly, the installation will fail.&lt;/p&gt;

&lt;p&gt;Ideally, you should fix your GitHub SSH config, but as a workaround, before Claude Code resolves the problem, you can bypass SSH in your git config—run the following in your terminal:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git config --global url."https://github.com/".insteadOf git@github.com:&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you want to learn more about the bug in Claude Code, check the open issue on GitHub: &lt;a href="https://github.com/anthropics/claude-code/issues/26588" rel="noopener noreferrer"&gt;Marketplace plugin cloning should default to HTTPS instead of SSH&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you verify the plugin is installed, you can start using it. Any prompts that mention &lt;code&gt;“jointjs playground”&lt;/code&gt; will trigger it, using JointJS to enhance the diagrams and flowcharts.&lt;/p&gt;

&lt;p&gt;Example prompts that will trigger JointJS Claude Playgrounds.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Build a JointJS codemap playground for React.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Create an interactive JointJS website map playground of URL-TO-YOUR-WEBSITE.&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you specifically want to trigger a specific skill available in the plugin, invoke it manually with the command &lt;code&gt;/jointjs&lt;/code&gt;. This will give you an autocomplete list of all available JointJS Claude Playground templates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqvv3jz3brc51vwbi2nl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqvv3jz3brc51vwbi2nl.png" alt=" " width="800" height="476"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A screenshot of the &lt;code&gt;`/jointjs`&lt;/code&gt; command in Claude Code.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The skills currently available in the JointJS Claude Playground are namespaced to &lt;code&gt;`/jointjs`&lt;/code&gt;, but you can use them directly. If there are any other skills with the same names, you’ll differentiate them by the plugin name in parentheses &lt;em&gt;(jointjs-claude-playground)&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;`/canvas-builder&lt;/code&gt;` - Creates any interactive visual builder playground.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&lt;/code&gt; &lt;code&gt;/data-explorer&lt;/code&gt; &lt;code&gt;&lt;/code&gt; - Creates an interactive data explorer playground for any database schema, API data model, or entity-relationship diagram.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&lt;/code&gt; &lt;code&gt;/codemap&lt;/code&gt; &lt;code&gt;&lt;/code&gt; - Creates an interactive code map playground for any library or codebase architecture.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&lt;/code&gt; &lt;code&gt;/site-explorer&lt;/code&gt; &lt;code&gt;&lt;/code&gt; - Creates an interactive website map.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&lt;/code&gt; &lt;code&gt;/diff-review&lt;/code&gt; &lt;code&gt;&lt;/code&gt; - Creates an interactive PR/diff review tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that you don’t have to trigger specific skills manually. Describe what you want, specify that you want to build a JointJS playground, and AI will figure out which precise template to use.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;JointJS Claude Playground examples&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The possibilities, just as with standard Claude Code Playground, are endless, but to give you a few ideas, here’s what we built with the JointJS Claude Playground plugin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Codebase visualizers for React, Vue.js, Svelte, Express.js
&lt;/h2&gt;

&lt;p&gt;If you want to better understand a codebase, just ask Claude to create a JointJS code map. It uses the `&lt;code&gt;/codemap`&lt;/code&gt; skill to build a clear visualization of the most important concepts of a codebase, with relationships clearly defined, ready for you to explore. You can click any node, add comments, and then copy the prompt to create a custom learning path that will help you better understand the framework.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/1181915073" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;em&gt;React is probably the most popular and widely used framework today—with the JointJS React codemap, you can precisely pinpoint your knowledge gaps and get the right prompt to craft the exact learning plan to master it. → &lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/" rel="noopener noreferrer"&gt;Live demo&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We’ve also built code maps for &lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/vue-codemap.html" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt;, &lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/svelte-codemap.html" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt;, &lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/expressjs-codemap.html" rel="noopener noreferrer"&gt;Express.js&lt;/a&gt;, and even &lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/jointjs-codemap.html" rel="noopener noreferrer"&gt;JointJS&lt;/a&gt; itself, all using the same approach.&lt;/p&gt;

&lt;p&gt;Of course, you can apply this to any framework or to your local codebase, even if it’s something completely custom. &lt;/p&gt;

&lt;h2&gt;
  
  
  Visual builders
&lt;/h2&gt;

&lt;p&gt;You can use the &lt;code&gt;`/canvas-builder`&lt;/code&gt; skill to create a visual builder playground, which allows you to drag-and-drop nodes from a sidebar to build a structured output, ideal for building complex queries easily. You can create a tool for any domain, for SQL, regex, cron expressions, decision trees, API specs, pipelines, and more.&lt;/p&gt;

&lt;p&gt;A really practical example is a custom SQL Query Builder that lets you visually build queries by dragging and dropping tables from the sidebar, then connecting their properties to generate an intricate SQL query you can copy with a click of a button.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/1181915046" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/sql-query-builder.html" rel="noopener noreferrer"&gt;&lt;em&gt;SQL Query Builder&lt;/em&gt;&lt;/a&gt; &lt;em&gt;tool created using the JointJS Claude Playground plugin. It can help you structure complex SQL queries visually.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Another handy use case for the &lt;code&gt;`/canvas-builder`&lt;/code&gt; skill is a custom decision tree. &lt;/p&gt;

&lt;p&gt;You can generate visual flowcharts and map out various courses of action, potential outcomes, and their consequences. &lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/1181915112" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/decision-tree-builder.html" rel="noopener noreferrer"&gt;&lt;em&gt;Decision Tree Builder&lt;/em&gt;&lt;/a&gt; &lt;em&gt;tool, created with JointJS Claude Playground, can clarify your thinking about the decisions you need to make.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We built a few other demos to showcase how much simpler building complex expressions in a JointJS Claude Playground can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/regex-builder.html" rel="noopener noreferrer"&gt;Regex Builder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/cron-builder.html" rel="noopener noreferrer"&gt;Cron Builder&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The possibilities are wide-ranging, and you can easily generate GitHub Actions Builders, State Machine Builders, API Designers, and many more domain‑specific tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data &amp;amp; site explorers
&lt;/h2&gt;

&lt;p&gt;You can also use JointJS Claude Playground to visualize data architecture and website structures, or to build tools that will help you work through various data challenges, such as massive pull requests or diffs.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/1181915151" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;em&gt;An example of a Diff Review tool that not only showcases the file changes, but also the actual relationships between changed files.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can build interactive website maps to help you visualise your website structure and identify weak points or unintuitive site hierarchies—you should probably fix those if you want to rank better in Google Search or in LLMs. &lt;/p&gt;

&lt;p&gt;• &lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/jointjs-site-explorer.html" rel="noopener noreferrer"&gt;JointJS Site Explorer&lt;/a&gt; – visualize your site structure.&lt;br&gt;&lt;br&gt;
• &lt;a href="https://changelog.jointjs.com/gallery/jointjs-claude-playground/ecommerce-data-explorer.html" rel="noopener noreferrer"&gt;E‑commerce Data Explorer&lt;/a&gt; – map entities, relationships, and flows.&lt;/p&gt;

&lt;p&gt;Keep in mind that you can always plug any skill directly into your projects to build something specifically for your use case.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;How to build a custom JointJS Claude Playground&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;JointJS Claude Playground comes with a number of predefined skills, but the basis is very flexible, so you can, and should, think outside of the box when it comes to building interesting and useful JointJS Claude Playground.&lt;/p&gt;

&lt;p&gt;Unlike the standard Claude Code Playground, the version enhanced with JointJS allows you to create interactive flows and generate output, be it a prompt, code, or query, in a user-friendly, intuitive way.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Want to create a hero section, but don’t know how to structure it? Ask Claude to build a JointJS playground with the elements you want in the sidebar, and you can then drag-and-drop them onto the canvas to see exactly what they would look like.
&lt;/li&gt;
&lt;li&gt;You’re hiring for a role and want to prepare structured questions? Build a flowchart-style tool in which each node represents a question/answer branch.
&lt;/li&gt;
&lt;li&gt;Struggling with dependency conflicts in your &lt;code&gt;package.json&lt;/code&gt;? Create a Dependency Conflict Resolver that lets you paste a &lt;code&gt;package.json&lt;/code&gt; or requirements.txt file, renders the full dependency graph, highlights conflicting version ranges, and provides options to manually pin versions to resolve conflicts.
&lt;/li&gt;
&lt;li&gt;Want to build a PoC for a JointJS application? Generate a JointJS Claude Playground that mirrors the UI and logic of the app you want to build as a proof of concept.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pro tip: In JointJS Claude Playground, you’re still working with an AI Coding Agent, so you can quickly iterate on features, fix bugs in the generated code, or adapt the playground to new use cases. &lt;/p&gt;

&lt;p&gt;If you want to build something custom out of the box, just make sure you mention &lt;em&gt;“jointjs playground”&lt;/em&gt; in your prompt, and Claude Code should be able to build an interactive playground leveraging the JointJS library.&lt;/p&gt;

&lt;p&gt;All of this is built on the open‑source version of JointJS. If you need advanced, enterprise-level features, JointJS+ gives you even more power.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The Claude Code Playground plugin is great, but somewhat limited when it comes to creating truly interactive visual playgrounds that not only look good but are also more intuitive and usable. So whenever you need an interactive, visual component in the Claude Code Playground you’re building, reach for JointJS to enhance it.&lt;/p&gt;

&lt;p&gt;All you need is the JointJS Claude Playground plugin, and you’ll get immediate access to robust skills that will help you make even better playgrounds. Install the JointJS Claude Playground plugin from GitHub, and start your first jointjs playground prompt to see the difference.&lt;/p&gt;

&lt;p&gt;Written by: Zoran Jambor, Developer Advocate at JointJS&lt;/p&gt;

</description>
      <category>claude</category>
      <category>diagramming</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Interactive ROI calculator</title>
      <dc:creator>Arthur Khokhlov</dc:creator>
      <pubDate>Thu, 24 Aug 2023 16:05:08 +0000</pubDate>
      <link>https://forem.com/geliogabalus/interactive-roi-calculator-4dl2</link>
      <guid>https://forem.com/geliogabalus/interactive-roi-calculator-4dl2</guid>
      <description>&lt;p&gt;If you could travel back in time, what asset would you invest in? Gold, S&amp;amp;P500, Bitcoin?&lt;/p&gt;

&lt;p&gt;Check out our simplified ROI calculator to find out your potential profits or losses based on historical data and also what diagramming enthusiasts will appreciate, how &lt;a href="https://www.jointjs.com/?utm_source=dev.to&amp;amp;utm_medium=referral"&gt;JointJS&lt;/a&gt; handles the integration of HTML form elements directly into the shapes via foreign objects.&lt;/p&gt;

&lt;p&gt;As a bonus, this demo shows JointJS accessibility as it works well on screen readers. Check it out!&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jointjs/embed/oNazJme?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This demo was built with JointJS, a proven JavaScript diagramming library. If you are interested in enhancing your application with interactive diagrams, explore our gallery of pre-built diagraming applications and cut your development time to days: &lt;a href="https://www.jointjs.com/demos?utm_source=dev.to&amp;amp;utm_medium=referral"&gt;https://www.jointjs.com/demos&lt;/a&gt;&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>html</category>
    </item>
    <item>
      <title>Light &amp; Dark Mode for diagrams (flowchart)</title>
      <dc:creator>Arthur Khokhlov</dc:creator>
      <pubDate>Thu, 24 Aug 2023 16:05:00 +0000</pubDate>
      <link>https://forem.com/geliogabalus/light-dark-mode-for-diagrams-flowchart-13b8</link>
      <guid>https://forem.com/geliogabalus/light-dark-mode-for-diagrams-flowchart-13b8</guid>
      <description>&lt;p&gt;How to completely style a diagram in CSS? How to toggle the diagram's light and dark mode? How to design elements and links with bevelled edges?  How to keep the link anchor on the element boundary? How to write your own orthogonal router?  Check out this CodePen that gives you all the answers.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jointjs/embed/ExpqGBz?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This demo was built with JointJS, a proven JavaScript diagramming library. If you are interested in enhancing your application with interactive diagrams, explore our gallery of pre-built diagraming applications and cut your development time to days: &lt;a href="https://www.jointjs.com/demos?utm_source=dev.to&amp;amp;utm_medium=referral"&gt;https://www.jointjs.com/demos&lt;/a&gt;&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>webdev</category>
      <category>javascriptlibraries</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Marey Chart</title>
      <dc:creator>Arthur Khokhlov</dc:creator>
      <pubDate>Thu, 24 Aug 2023 16:04:51 +0000</pubDate>
      <link>https://forem.com/geliogabalus/marey-chart-874</link>
      <guid>https://forem.com/geliogabalus/marey-chart-874</guid>
      <description>&lt;p&gt;Marey diagrams or Marey charts are usually used to analyze transportation systems such as bus or train schedules. However, there are other uses for this type of diagram, one of which is workflow analysis.&lt;/p&gt;

&lt;p&gt;Below you can see an interactive example of a Marey diagram and feel free to &lt;a href="https://codepen.io/jointjs/pen/xxPqBmJ"&gt;study the source code&lt;/a&gt; to learn how to build one.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jointjs/embed/xxPqBmJ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Inspired by Mike Bostock D3 example: &lt;a href="https://bl.ocks.org/mbostock/5544008"&gt;&lt;/a&gt;&lt;a href="https://bl.ocks.org/mbostock/5544008"&gt;https://bl.ocks.org/mbostock/5544008&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This demo was built with JointJS, a proven JavaScript diagramming library. If you are interested in enhancing your application with interactive diagrams, explore our gallery of pre-built diagraming applications and cut your development time to days: &lt;a href="https://www.jointjs.com/demos?utm_source=dev.to&amp;amp;utm_medium=referral"&gt;https://www.jointjs.com/demos&lt;/a&gt;&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>javascriptlibraries</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to create isometric diagrams using SVG</title>
      <dc:creator>Arthur Khokhlov</dc:creator>
      <pubDate>Wed, 23 Aug 2023 08:37:33 +0000</pubDate>
      <link>https://forem.com/geliogabalus/how-to-create-isometric-diagrams-using-svg-52ep</link>
      <guid>https://forem.com/geliogabalus/how-to-create-isometric-diagrams-using-svg-52ep</guid>
      <description>&lt;p&gt;There are various methods of visualizing three-dimensional objects in two-dimensional space. For example, most 3D graphics engines use perspective projection as the main form of projection. This is because perspective projection is an excellent representation of the real world, in which objects become smaller with increasing distance. But when the relative position of objects is not important, and for a better understanding of the size of objects, you can use parallel projections. They are more common in engineering and architecture, where it is important to maintain parallel lines. Since the birth of computer graphics, these projections have been used to render 3D scenes when 3D rendering hardware acceleration was not possible. Recently, various forms of parallel projections have become a style choice for digital artists, and they are used to display objects in infographics and in digital art in general.&lt;/p&gt;

&lt;p&gt;The purpose of this article is to show how to create and manipulate isometric views in SVG, and how to define these objects using, in particular, the &lt;a href="https://www.jointjs.com/?utm_source=dev&amp;amp;utm_medium=referral"&gt;JointJS&lt;/a&gt; library. To illustrate SVG’s capabilities in creating parallel projections, we will use isometric projection as an example. This projection is one of the dominant projection types, because it allows you to maintain the relative scale of objects along all axes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isometric projection
&lt;/h2&gt;

&lt;p&gt;Let’s define what isometric projection is. First of all, it is a parallel type of projection in which all lines from a “camera” are parallel. It means that the scale of an object does not depend on the distance between the “camera” and the object. And specifically, in isometric (means “equal measure” in greek) projection, scaling along each axis is the same. This is achieved by defining equal angles between all axes.&lt;/p&gt;

&lt;p&gt;In the following image, you can see how axes are positioned in isometric projection. Keep in mind that in this article we will be using a left-handed coordinate system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cYcA6WE6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fezvrfs7icl7n28vxte8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cYcA6WE6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fezvrfs7icl7n28vxte8.png" alt="Image description" width="720" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the features of the isometric projection is that it can be deconstructed in three different 2D projections: top, side and front projections. For example, cuboid can be represented by three rectangles on each 2D projection and then combined into one isometric view. The next image represents separate projections of an object using the left-handed coordinate system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6OLCTvII--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqfcpvqc1i4xlklel034.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6OLCTvII--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqfcpvqc1i4xlklel034.png" alt="Image description" width="720" height="757"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we can combine them into one isometric view:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6EDyXJPk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bq9ee20hhp56m84kf534.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6EDyXJPk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bq9ee20hhp56m84kf534.png" alt="Image description" width="720" height="798"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The challenge with SVG is that it contains 2D objects which are located on one XY-plane. But we can overcome this by combining all projections in one plane, and then separately applying transformation to every object.&lt;/p&gt;

&lt;h2&gt;
  
  
  SVG isometric view transformations
&lt;/h2&gt;

&lt;p&gt;In 3D, to create an isometric view, we can move the camera to a certain position, but SVG is purely a 2D format, so we have to create a workaround to build such a view. We recommend reading &lt;a href="https://design.tutsplus.com/tutorials/how-to-create-advanced-isometric-illustrations-using-the-ssr-method--vector-1058"&gt;Cody Walker’s article&lt;/a&gt; that presents a method for creating isometric representations from 2D object views — top, side and front projections. Based on the article, we need to create transformations for each 2D projection of the object separately.&lt;/p&gt;

&lt;p&gt;First we need to rotate our plane by 30 degrees. And then we will skew our 2D image by -30 degrees. This transformation will align our axes with the axes of the isometric projection.&lt;/p&gt;

&lt;p&gt;Then we need to use a scale operator to scale our 2D projection down vertically by 0.8602. We need to do it due to the fact of isometric projection distortion.&lt;/p&gt;

&lt;p&gt;Let’s introduce some SVG features that will help us implement isometric projection. The SVG specification allows users to specify a particular transformation in the &lt;em&gt;transform&lt;/em&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform"&gt;attribute&lt;/a&gt; of an SVG element. This attribute helps us apply linear transformation to the SVG element. To transform 2D projection into an isometric view, we need to apply &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#scale"&gt;scale&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#rotate"&gt;rotate&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewx"&gt;skew&lt;/a&gt; operators.&lt;/p&gt;

&lt;p&gt;To represent the transformation in code, we can use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrixReadOnly"&gt;DOMMatrixReadOnly&lt;/a&gt; object, which is a browser API to represent the transformation matrix. Using this interface, we can create a matrix as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const isoMatrix = new DOMMatrixReadOnly()
    .rotate(30)
    .skewX(-30)
    .scale(1, 0.8602);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This interface allows building a transformation matrix using our values, and then we can apply the resulting value to the &lt;em&gt;transform&lt;/em&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform"&gt;attribute&lt;/a&gt; using the &lt;em&gt;matrix&lt;/em&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#matrix"&gt;function&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In SVG, we can present only one 2D space at a time, so for our conversion, we will be using top projection as a base projection. This is mostly because axes in this projection correspond with axes in a normal SVG viewport.&lt;/p&gt;

&lt;p&gt;To demonstrate SVG possibilities, we will be using the &lt;a href="https://www.jointjs.com/?utm_source=dev&amp;amp;utm_medium=referral"&gt;JointJS&lt;/a&gt; library. We defined a rectangular grid in the XY-plane with a cell width of 20. Let’s define SVG for the elements on the top projection from the example. To properly render this object, we need to specify two polygons for two levels of our object. Also, we can apply a translate transformation for our element in 2D space using DOMMatrix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Translate transformation for Top1 Element
const matrix2D = new DOMMatrixReadOnly()
    .translate(200, 200);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!--Top1 element--&amp;gt;
&amp;lt;polygon joint-selector="body" id="v-4" 
  stroke-width="2" stroke="#333333" fill="#ff0000" 
  fill-opacity="0.7" points="0,0 60,0 60,20 40,20 40,60 0,60" 
  transform="matrix(1,0,0,1,200,200)"&amp;gt;
&amp;lt;/polygon&amp;gt;

&amp;lt;!--Top2 element--&amp;gt;
&amp;lt;polygon joint-selector="body" id="v-6" 
  stroke-width="2" stroke="#333333" fill="#ff0000" 
  fill-opacity="0.7" points="0,0 20,0 20,40 0,40" 
  transform="matrix(1,0,0,1,240,220)"&amp;gt;
&amp;lt;/polygon&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NWikjIKo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p65npt4o893a879z1gnf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NWikjIKo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p65npt4o893a879z1gnf.png" alt="Image description" width="284" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we can apply our isometric matrix to our elements. Also, we will add a translate transformation to position elements in the right place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const isoMatrix = new DOMMatrixReadOnly()
    .rotate(30)
    .skewX(-30)
    .scale(1, 0.8602);

const top1Matrix = isoMatrix.translate(200, 200);
const top2Matrix = isoMatrix.translate(240, 220);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--br6aUQX6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k12e8ea34bzak3z14851.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--br6aUQX6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k12e8ea34bzak3z14851.png" alt="Image description" width="400" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For simplicity, let’s assume that our element’s base plane is located on the XY-plane. Therefore, we need to translate the top view, so it will be viewed as it is located on the top of the object. To do it, we can just translate the projection by its Z coordinate on the scaled SVG space as follows. Top1 element has elevation 80, so we should translate it by (-80, -80). Similarly, Top2 element has elevation 40. We can just apply these translations to our existing matrix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const top1MatrixWithHeight = top1Matrix.translate(-80, -80);
const top2MatrixWithHeight = top1Matrix.translate(-40, -40);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xvqzjw94--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7stywktpi0bhxag97bf7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xvqzjw94--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7stywktpi0bhxag97bf7.png" alt="Image description" width="300" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the end, we will have the following &lt;em&gt;transform&lt;/em&gt; attributes for &lt;em&gt;Top1&lt;/em&gt; and &lt;em&gt;Top2&lt;/em&gt; elements. Note that they differ only in the two last values, which represent the translate transformation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Top1 element
transform="matrix(0.8660254037844387,0.49999999999999994,-0.8165000081062317,0.47140649947346464,5.9,116.6)"

// Top2 element
transform="matrix(0.8660254037844387,0.49999999999999994,-0.8165000081062317,0.47140649947346464,26.2,184.9)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create an isometric view of side and front projections, we need to make a &lt;a href="https://en.wikipedia.org/wiki/Net_(polyhedron)"&gt;net&lt;/a&gt; so we can place all projections on 2D SVG space. Let’s create a net by attaching side and front views similar to the classic cube net:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U2QAre3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngnmmhenhnmvfs777ge7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U2QAre3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngnmmhenhnmvfs777ge7.png" alt="Image description" width="444" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we need to &lt;em&gt;skewX&lt;/em&gt; side and front projections by 45 degrees. It will allow us to align the Z axis for all projections. After this transformation, we will get following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xbVeYQDb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dybogsnb86npda2qbiuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xbVeYQDb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dybogsnb86npda2qbiuh.png" alt="Image description" width="440" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we can apply our isoMatrix to this object:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A1030uiK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/74nzb3tcvi0griylti9i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A1030uiK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/74nzb3tcvi0griylti9i.png" alt="Image description" width="406" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In every projection, there are parts that have a different 3rd coordinate value. Therefore, we need to adjust this depth coordinate for every projection as we did with the top projection and its Z coordinate. In the end, we will get the following isometric view:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TtexGWZv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/veax3wyhipo8972gi4fb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TtexGWZv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/veax3wyhipo8972gi4fb.png" alt="Image description" width="395" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using JointJS for the Isometric Diagram
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.jointjs.com/?utm_source=dev&amp;amp;utm_medium=referral"&gt;JointJS&lt;/a&gt; allows us to create and manipulate such objects with ease due to its elements framework and wide set of tools. Using JointJS, we can define and control isometric objects to build powerful isometric diagrams.&lt;/p&gt;

&lt;p&gt;Remember the basic isometric transformation from the beginning of the article?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const isoMatrix = new DOMMatrixReadOnly()
    .rotate(30)
    .skewX(-30)
    .scale(1, 0.8602);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the JointJS library, we can apply this transformation to the whole object which stores all SVG elements, and then simply apply the object-specific transformations on top of this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isometric grid rendering
&lt;/h2&gt;

&lt;p&gt;JointJS has great capabilities in the rendering of custom SVG markup. Utilizing JointJS, we can generate a path which is aligned to an untransformed grid, and have it transformed automatically with the grid thanks to the global paper transformation that we mentioned previously. You can see the grid, and how we interpret the coordinate system in the demo below. Note that we can dynamically change the paper transformation which allows us to change the view on the fly:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jointjs/embed/poQzZJZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a custom isometric SVG element
&lt;/h2&gt;

&lt;p&gt;Here we show an custom SVG Isometric shape in JointJS. In our example, we use the &lt;em&gt;isometricHeight&lt;/em&gt; property to store information about a third dimension, and then use it to render our isometric object. The following snippet shows how you can call the custom &lt;em&gt;createIsometricElement&lt;/em&gt; function to alter object properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const element = createIsometricElement({
    isometricHeight: GRID_SIZE * 3,
    size: { width: GRID_SIZE * 3, height: GRID_SIZE * 6 },
    position: { x: GRID_SIZE * 6, y: GRID_SIZE * 6 }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the following demo, you can see that our custom isometric element can be moved like an ordinary element on the isometric grid. You can change dimensions by altering parameters of the &lt;em&gt;createIsometricElement&lt;/em&gt; function in the source code (when you click “Edit on CodePen”):&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jointjs/embed/eYPxLgo?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Z-index calculation in isometric diagrams
&lt;/h2&gt;

&lt;p&gt;One of the problems with an isometric view is placing elements respective to their relative position. Unlike in a 2D plane, in an isometric view objects have perceived height and can be placed one behind the other. We can achieve this behavior in SVG by placing them into the DOM in the right order. To define the order in our case, we can use the JointJS &lt;em&gt;z&lt;/em&gt; attribute which allows sending the correct element to the background, so that it can be overlapped/hidden by the other element as expected. You can find more information about this problem in a great &lt;a href="https://mazebert.com/forum/news/isometric-depth-sorting--id775/"&gt;article by Andreas Hager&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We decided to sort the elements using the &lt;a href="https://en.wikipedia.org/wiki/Topological_sorting"&gt;topological sorting algorithm&lt;/a&gt;. The algorithm consists of two steps. First, we need to create a special graph, and then we need to use a depth-first search for that graph to find the correct order of elements.&lt;/p&gt;

&lt;p&gt;As the first step, we need to populate the initial graph — for each object we need to find all objects behind it. We can do that by comparing the positions of their bottom sides. Let’s illustrate this step with images — let’s, for example, take three elements which are positioned like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xgoOZRMC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u91sv3el8nvz75zgzcvi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xgoOZRMC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u91sv3el8nvz75zgzcvi.png" alt="Image description" width="720" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VoMyzt8K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/engumxj9csgqh5b4gcq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VoMyzt8K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/engumxj9csgqh5b4gcq1.png" alt="Image description" width="550" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have marked the bottom side of each object in the second image. Using this data, we will create a graph structure which will model topological relations between elements. In the image, you can see how we define the points on the bottom side — we can find the relative position of all elements by comparing &lt;em&gt;aMax&lt;/em&gt; and &lt;em&gt;bMin&lt;/em&gt; points. We define that if the &lt;em&gt;x&lt;/em&gt; and &lt;em&gt;y&lt;/em&gt; coordinates of point &lt;em&gt;bMin&lt;/em&gt; are less than the coordinates of point &lt;em&gt;aMax&lt;/em&gt; , then object &lt;em&gt;b&lt;/em&gt; is located behind object &lt;em&gt;a&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V0tUCS9D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q4geuya985sztoxabphu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V0tUCS9D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q4geuya985sztoxabphu.png" alt="Image description" width="720" height="667"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Comparing the three elements from our previous example, we can produce the following graph:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ioLifJHt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n3yvkmsbwl9oy6514oe7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ioLifJHt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n3yvkmsbwl9oy6514oe7.png" alt="Image description" width="391" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, we need to use a &lt;a href="https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search"&gt;variation of the depth-first search algorithm&lt;/a&gt; to find the correct rendering order. A depth-first search allows us to visit graph nodes according to the visibility order, starting from the most distant one. Here is a library-agnostic example of the algorithm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sortElements = (elements: Rect[]) =&amp;gt; {
    const nodes = elements.map((el) =&amp;gt; {
        return {
            el: el,
            behind: [],
            visited: false,
            depth: null,
        };
    });

    for (let i = 0; i &amp;lt; nodes.length; ++i) {
        const a = nodes[i].el;
        const aMax = aBBox.bottomRight();

        for (let j = 0; j &amp;lt; nodes.length; ++j) {
            if (i != j) {
                const b = nodes[j].el;
                const bMin = bBBox.topLeft();
                if (bMin.x &amp;lt; aMax.x &amp;amp;&amp;amp; bMin.y &amp;lt; aMax.y) {
                    nodes[i].behind.push(nodes[j]);
                }
            }
        }
    }

    const sortedElements = depthFirstSearch(nodes);
    return sortedElements;
};

const depthFirstSearch = (nodes) =&amp;gt; {
    let depth = 0;
    let sortedElements = [];

    const visitNode = (node) =&amp;gt; {
        if (!node.visited) {
            node.visited = true;

            for (let i = 0; i &amp;lt; node.behind.length; ++i) {
                if (node.behind[i] == null) {
                    break;
                } else {
                    visitNode(node.behind[i]);
                    delete node.behind[i];
                }
            }

            node.depth = depth++;
            sortedElements.push(node.el);
        }
    };

    for (let i = 0; i &amp;lt; nodes.length; ++i) {
        visitNode(nodes[i]);
    }

    return sortedElements;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method can be implemented easily using the JointJS library — in the following CodePen, we use a special JointJS event to recalculate z-indexes of our elements whenever the position of an element is changed. As outlined above, we use a special &lt;em&gt;z&lt;/em&gt; property of the element model to specify rendering order and assign it during the depth-first traversal. (Note that the algorithm’s behavior is undefined in the case of intersecting elements, due to the nature of implementation of isometric objects.)&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jointjs/embed/ZEqPyyX?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The JointJS demo
&lt;/h2&gt;

&lt;p&gt;We have created a JointJS demo which combines all of these methods and techniques, and also allows you to easily switch between 2D and isometric SVG markup. Crucially, as you can see, the powerful features of JointJS (which allow us to move elements, to connect them with links, and to create tools to edit them, among others) work just as well in the isometric view as they do in 2D.&lt;/p&gt;

&lt;p&gt;You can see the demo &lt;a href="https://www.jointjs.com/demos/isometric-diagram?utm_source=dev&amp;amp;utm_medium=referral"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--848AHZsE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eie6dwiwz6nr7nb53uj0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--848AHZsE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eie6dwiwz6nr7nb53uj0.png" alt="Image description" width="720" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Throughout this article, we used our open-source &lt;a href="https://www.jointjs.com?utm_source=dev&amp;amp;utm_medium=referral"&gt;JointJS&lt;/a&gt; library for illustration. However, since you were so thorough with your exploration, we would like to extend to you &lt;a href="https://www.jointjs.com/free-trial?utm_source=dev&amp;amp;utm_medium=referral"&gt;an invitation to our no-commitment 30-day trial of JointJS+&lt;/a&gt;, an advanced commercial extension of JointJS. It will allow you to experience additional powerful tools for creating delightful diagrams.&lt;/p&gt;

</description>
      <category>diagramming</category>
      <category>javascriptlibraries</category>
      <category>svg</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to write a simple JSON visualizer using JointJS+</title>
      <dc:creator>Arthur Khokhlov</dc:creator>
      <pubDate>Mon, 31 Oct 2022 16:09:34 +0000</pubDate>
      <link>https://forem.com/geliogabalus/how-to-write-a-simple-json-visualizer-using-jointjs-46o1</link>
      <guid>https://forem.com/geliogabalus/how-to-write-a-simple-json-visualizer-using-jointjs-46o1</guid>
      <description>&lt;p&gt;The JSON format - as a widely used form of data storage and representation - lacks a simple and convenient view of complex data, forcing developers to use external tools for data visualization and thus more productive work.&lt;/p&gt;

&lt;p&gt;At &lt;a href="https://www.jointjs.com/"&gt;JointJS&lt;/a&gt;, we decided to regularly share code samples to help you create visual applications faster and with less effort, and one of them is a &lt;strong&gt;simple JSON visualizer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This gives us the opportunity to connect with other developers and diagramming enthusiasts, hear their ideas and solve their pain points. We often hear them complain about the lack of an intuitive way to visualize their JSON data.&lt;/p&gt;

&lt;p&gt;That's why we created this simple demo application that demonstrates how to use a built-in automatic layout to position nodes and add table-like shapes to organize object properties into tables where values have different styles depending on their type.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jointjs/embed/WNJBMxQ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We release new demos every Wednesday to help developers get inspired and bring their ideas to life faster. If you want to learn with us, &lt;a href="https://codepen.io/jointjs"&gt;follow us on CodePen&lt;/a&gt; or &lt;a href="https://github.com/clientIO/joint/discussions"&gt;join the conversation on Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy diagramming!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>productivity</category>
      <category>codepen</category>
    </item>
  </channel>
</rss>
