Back

Category hierarchy layout mode

Documentation Open in JSFiddle
Start Free Trial Purchase

HTML

HTML
<script src="https://cdn.zoomcharts-cloud.com/1/nightly/zoomcharts.js"></script>
<div id="demo"></div>

CSS

CSS
//No CSS for this example 

JavaScript

JavaScript

var data = {
  "nodes": [ 
    { "id": "a1", "loaded": true, "style": { "label": "Node Label A1", "hierarchyCategory": "Category Applesauce", "fillColor": "red" } },
    { "id": "a2", "loaded": true, "style": { "label": "Node Label A2", "hierarchyCategory": "Category Applesauce", "fillColor": "red" } },
    { "id": "a3", "loaded": true, "style": { "label": "Node Label A3", "hierarchyCategory": "Category Applesauce", "fillColor": "red" } },
    { "id": "a4", "loaded": true, "style": { "label": "Node Label A4", "hierarchyCategory": "Category Applesauce", "fillColor": "red" } },
    { "id": "a5", "loaded": true, "style": { "label": "Node Label A5", "hierarchyCategory": "Category Applesauce", "fillColor": "red" } },
    { "id": "b1", "loaded": true, "style": { "label": "Node Label B1", "hierarchyCategory": "Category Biscuit", "fillColor": "green" } },
    { "id": "b2", "loaded": true, "style": { "label": "Node Label B2", "hierarchyCategory": "Category Biscuit", "fillColor": "green" } },
    { "id": "b3", "loaded": true, "style": { "label": "Node Label B3", "hierarchyCategory": "Category Biscuit", "fillColor": "green" } },
    { "id": "b4", "loaded": true, "style": { "label": "Node Label B4", "hierarchyCategory": "Category Biscuit", "fillColor": "green" } },
    { "id": "c1", "loaded": true, "style": { "label": "Node Label C1", "hierarchyCategory": "Category Cucumber", "fillColor": "blue" } },
    { "id": "c2", "loaded": true, "style": { "label": "Node Label C2", "hierarchyCategory": "Category Cucumber", "fillColor": "blue" } },
    { "id": "c3", "loaded": true, "style": { "label": "Node Label C3", "hierarchyCategory": "Category Cucumber", "fillColor": "blue" } },
    { "id": "c4", "loaded": true, "style": { "label": "Node Label C4", "hierarchyCategory": "Category Cucumber", "fillColor": "blue" } },
    { "id": "c5", "loaded": true, "style": { "label": "Node Label C5", "hierarchyCategory": "Category Cucumber", "fillColor": "blue" } },
    { "id": "d2", "loaded": true, "style": { "label": "Node Label D2", "hierarchyCategory": "Category Dessert", "fillColor": "yellow" } },
    { "id": "d3", "loaded": true, "style": { "label": "Node Label D3", "hierarchyCategory": "Category Dessert", "fillColor": "yellow" } },
    { "id": "d4", "loaded": true, "style": { "label": "Node Label D4", "hierarchyCategory": "Category Dessert", "fillColor": "yellow" } },
    { "id": "d5", "loaded": true, "style": { "label": "Node Label D5", "hierarchyCategory": "Category Dessert", "fillColor": "yellow" } },
    { "id": "d6", "loaded": true, "style": { "label": "Node Label D6", "hierarchyCategory": "Category Dessert", "fillColor": "yellow" } },
    { "id": "e4", "loaded": true, "style": { "label": "Node Label E4", "hierarchyCategory": "Category Egg", "fillColor": "orange" } },
    { "id": "e5", "loaded": true, "style": { "label": "Node Label E5", "hierarchyCategory": "Category Egg", "fillColor": "orange" } },
    { "id": "e6", "loaded": true, "style": { "label": "Node Label E6", "hierarchyCategory": "Category Egg", "fillColor": "orange" } },
  ],
  "links": [
    { "id": "l1", "from": "a1", "to": "a2" },
    { "id": "l2", "from": "a2", "to": "a3" },
    { "id": "l3", "from": "a3", "to": "a4" },
    { "id": "l4", "from": "a4", "to": "a5" },
    { "id": "l5", "from": "a1", "to": "b1" },
    { "id": "l6", "from": "b1", "to": "a2" },
    { "id": "l7", "from": "b2", "to": "b3" },
    { "id": "l8", "from": "b3", "to": "b4" },
    { "id": "l9", "from": "a3", "to": "b2" },
    { "id": "l10", "from": "b3", "to": "a5" },
    { "id": "l11", "from": "b1", "to": "b2" },
    { "id": "l12", "from": "c2", "to": "b2" },
    { "id": "l13", "from": "b2", "to": "d6" },
    { "id": "l14", "from": "a5", "to": "e6" },
    { "id": "l15", "from": "e6", "to": "b4" },
    { "id": "l16", "from": "c1", "to": "c2" },
    { "id": "l17", "from": "c2", "to": "c3" },
    { "id": "l18", "from": "c3", "to": "c4" },
    { "id": "l19", "from": "c4", "to": "c5" },
    { "id": "l20", "from": "d3", "to": "c3" },
    { "id": "l21", "from": "c3", "to": "d4" },
    { "id": "l22", "from": "d4", "to": "c4" },
    { "id": "l23", "from": "c5", "to": "d6" },
    { "id": "l24", "from": "d2", "to": "d3" },
    { "id": "l25", "from": "d3", "to": "d4" },
    { "id": "l26", "from": "d4", "to": "d5" },
    { "id": "l27", "from": "d5", "to": "d6" },
    { "id": "l28", "from": "a2", "to": "d3" },
    { "id": "l29", "from": "e4", "to": "e5" },
    { "id": "l30", "from": "e5", "to": "e6" },
    { "id": "l31", "from": "d3", "to": "e4" },
    { "id": "l32", "from": "e4", "to": "d4" },
    { "id": "l33", "from": "d5", "to": "e5" },
    { "id": "l34", "from": "e5", "to": "d6" },
    { "id": "l35", "from": "d6", "to": "e6" },
    { "id": "l36", "from": "d6", "to": "a1" },
    { "id": "l37", "from": "d6", "to": "c4" },
  ]
};

const cycleColors = ["red", "orange", "yellow", "green", "blue", "magenta"];
const cycleIDColorMap = {};
let nextCycleIndex = 0;
var chart = new NetChart({
  container: document.getElementById("demo"),
  data: { preloaded: data },
  layout: {
    mode: "categoryHierarchy",
    rotation: -90,
    scaleY: -1,
    // Nodes can be spaced to avoid overlap using these settings
    nodeSpacing: 30,
    rowSpacing: 60,
    categoryLabelStyle: {
      // Labels respect alignment settings
      align: "left",
      side: "right",
      positionX: "left",
      textStyle: {
        font: "12px Arial"
      },
      backgroundStyle: {
        fillColor: "white"
      }
    },
    onCycleDetect: (backlink, cycle) => {
      // This is naively marking every link involved in every cycle
      // detected. Can also e.g. only mark the backlinks or have
      // some method of handling overlapping cycles, or have special
      // additional styling for backlinks, etc. etc.

      const cycleID = backlink.id;
      for(let i = 0; i < cycle.length; i++) {
        let link = cycle[i];

        if(!link.extra) {
          link.extra = {};
        }
        link.extra.cycleID = cycleID;
      }

      if(!backlink.extra) {
        backlink.extra = {};
      }
      backlink.extra.isBacklink = true;

      if(!cycleIDColorMap.hasOwnProperty(cycleID)) {
        cycleIDColorMap[cycleID] = cycleColors[nextCycleIndex % cycleColors.length];
        nextCycleIndex++;
      }
    }
  },
  style:{
    multilinkAutoCurve: 1.0,
    multilinkSpacing: 10,
    node: {
      // Label should be inside the node with roundtext setting
      display: "roundtext",
    },
    link: { toDecoration: "arrow" },
    linkStyleFunction: (link) => {
      link.radius = 1;
      // Simple example of styling links that are part of a cycle
      if(link.extra && link.extra.cycleID) {
        link.fillColor = cycleIDColorMap[link.extra.cycleID];
        link.radius = 2;
      }
      if(link.extra && link.extra.isBacklink) {
        link.radius = 5;
      }
    },
    nodeStyleFunction: (node) => {
      // Example of applying styles to the node labels
      node.labelStyle.textStyle.fillColor = "black"
      node.labelStyle.textStyle.font = "12px Arial"
    }
  }
});

Data

Data
//No separate data for this example