Back

NetChart Value Axis enhancements

Documentation Open in JSFiddle
Start Free Trial Purchase

HTML

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

CSS

CSS
#demo {
	width: 100%;
	height: 100vh;
}

JavaScript

JavaScript
var data = {
  "nodes": [
    { "id": "n1", "className":"classB", "loaded": true, "style": { "label": "Node1" }, x: 50, y: 0 },
    { "id": "n2", "className":"classA", "loaded": true, "style": { "label": "Node2" }, x: 100, y: -100 },
    { "id": "n3", "className":"classB", "loaded": true, "style": { "label": "Node3" }, x: 200, y: 100 },
    { "id": "n4", "className":"classA", "loaded": true, "style": { "label": "Node4" }, x: 300, y: -50 },
    { "id": "n5", "className":"classB", "loaded": true, "style": { "label": "Node5" }, x: 350, y: -75 },
    { "id": "n6", "className":"classA", "loaded": true, "style": { "label": "Node5" }, x: 450, y: -125 },
    { "id": "n7", "className":"classB", "loaded": true, "style": { "label": "Node5" }, x: 600, y: -200 },
    { "id": "n8", "className":"classA", "loaded": true, "style": { "label": "Node5" }, x: -50, y: -125 },
    { "id": "n9", "className":"classA", "loaded": true, "style": { "label": "Node5" }, x: -100, y: -200 },
  ],
  "links": [
    { "id": "l1a", "from": "n1", "to": "n2", "style": { "label":
                                                       "", "fillColor": "red", "fromDecoration": "open arrow" } },
    { "id": "l1", "from": "n1", "to": "n2", "style": { "label": "", "fillColor": "red", "toDecoration": "arrow" } },
    { "id": "l2", "from": "n2", "to": "n3", "style": { "label": "", "fillColor": "green", "toDecoration": "arrow" } },
    { "id": "l2a", "from": "n2", "to": "n3", "style": { "label":
                                                       "", "fillColor": "green", "fromDecoration": "open arrow" } },
  ]
};

const addTooltipValue = (target, name, value, isLink, nameJoiner) => {
  const hasName = name !== null && name !== undefined;
  const hasValue = value !== null && value !== undefined;
  if(!nameJoiner) {
    nameJoiner = ":\u00A0";
  }

  if(hasName) {
    const nameElement = document.createElement("span");
    nameElement.classList.add("tooltipTitle");
    nameElement.setAttribute("style", "float: left; font-weight: bold;");
    const actualNameJoiner = hasValue ? nameJoiner : "";
    nameElement.appendChild(document.createTextNode(name + actualNameJoiner));
    target.appendChild(nameElement);
  }

  if(hasValue) {
    const valueElement = document.createElement("span");
    valueElement.classList.add("tooltipContent");
    valueElement.setAttribute("style", "float: left;");
    valueElement.appendChild(document.createTextNode(value));
    target.appendChild(valueElement);
  }

  target.appendChild(document.createElement("br"));
};

const formatRegVal = (x) => {
  const degree = x === 0 ? 0 : Math.floor(Math.log(Math.abs(x)) / Math.log(10));
  const factor = Math.pow(10, degree);
  const precision = 1000000;
  const newValue = factor * Math.round((x / factor) * precision) / precision;
  // Convert to string and back to ensure the number isn't rounded incorrectly e.g. 0.123456999999997.
  return parseFloat(newValue.toFixed(Math.max(5 - Math.min(degree, 0), 0)));
}

const regressionContents = (data, reg, asyncCallback, args, canSelect) => {
  const val = document.createElement("div");
  const sup = ["\u2070", "\u00B9", "\u00B2", "\u00B3", "\u2074", "\u2075", "\u2076", "\u2077", "\u2078", "\u2079", "\u00B9\u2070"];
  const sub = ["\u2080", "\u2081", "\u2082", "\u2083", "\u2084", "\u2085", "\u2086", "\u2087", "\u2088", "\u2089", "\u0081\u2080"];
  const subName = (i) => "a" + (i <= sub.length ? sub[i] : "_" + i);
  const eq = reg.model
  .map((x, i) => subName(i)
       + ((i === 0) ? ""
          : "x"
          + (i <= 1 ? ""
             : i <= sup.length ? sup[i] : "^" + i)))
  .reverse()
  .join(" + ");
  const joiner = "\u00A0=\u00A0";
  const stats = reg.stats;
  addTooltipValue(val, "f(x)", eq, false, joiner);
  for (let i = reg.model.length - 1; i >= 0; i--) {
    addTooltipValue(val, subName(i), formatRegVal(reg.model[i]), false, joiner);
  }
  const yVal = args.evalModel(reg.model, args.axisX);
  addTooltipValue(val, "x", formatRegVal(args.axisX), false, joiner);
  addTooltipValue(val, "y", formatRegVal(yVal), false, joiner);
  addTooltipValue(val, "n", formatRegVal(stats.n), false, joiner);
  addTooltipValue(val, "\u03C3", formatRegVal(stats.sd), false, joiner);
  addTooltipValue(val, "r\u00B2", formatRegVal(stats.r2), false, joiner);
  addTooltipValue(val, "Adjusted r\u00B2", formatRegVal(stats.ar2), false, joiner);
  val.style.padding = "6px 7px 4px 6px";
  if(canSelect) {
    val.style.userSelect = "text";
  }
  return val;
}

var chart = new NetChart({
  container: document.getElementById("demo"),
  data: { preloaded: data },
  valueAxis: {
    enabled: true,
    location: "zero",
    arrowSizeX: 5,
    arrowSizeY: 5,
    scale: 1.0,
    scaleX: 1,
    scaleY: -1,
    offsetX: 0,
    offsetY: 0,
    gridColorX: "rgba(0,255,255,0.1)",
    gridColorY: "rgba(0,255,255,0.1)",
    backgroundShapes: [
      { type: "ellipse", startX: -200, startY: 100, endX: -50, endY: 50, fillColor: "rgba(255,0,0,1.0)", lineColor: "rgba(192,92,64,0.5)", lineWidth: 4},
      { type: "rectangle", startX: 100, startY: -100, endX: 200, endY: -25, fillColor: "rgba(0,0,192,1.0)", lineColor: "rgba(0,128,255,0.5)", lineWidth: 4},
      { type: "ellipse", startX: 300, startY: -Infinity, endX: 500, endY: Infinity, fillColor: "rgba(0,0,192,1.0)", lineColor: "rgba(0,128,255,0.5)", lineWidth: 4},
    ],
    regressions: [
      { seriesID: "classB", lineColor: "green", lineWidth: 5, drawOrder: "back" },
      { degree: 2, lineWidth: 5, lineColor: "red" },
    ],
    regressionContentsFunction: (data, reg, callback, args) => regressionContents(data, reg, callback, args, false),
    valueLabelX: {
      textStyle: {
        font: "11px Arial"
      }
    },
    zeroLineX: {
      lineColor: "rgba(128, 128, 255, 1.0)",
      lineWidth: 4,
      lineDash: [6.5, 4],
      scaleWithZoom: true
    },
    zeroLineY: {
      lineColor: "rgba(255, 128, 128, 1.0)",
      lineWidth: 4,
      lineDash: [6.5, 4],
      scaleWithZoom: true
    },
    spikelineStyle: {
      lineWidth: 1
    },

    titleY: "Axis title Y",
    titleX: "Axis title X",
    titleYStyle: {
    },
    functionPlotStep: 2,
    functionPlotStyle: {
      lineColor: "purple",
      lineWidth: 3
    },
    thresholdsX: [
      {
        from: 100,
        to: 100,
        fromType: "first",
        toType: "last",
        position: "under",
        label: "Group X",
        labelStyle: {
          angle: -90
        },
        seriesID: "classB",
        style: {
          fillColor: "rgba(152,133,255,0.5)",
          lineColor: "rgb(0,0,0)",
          lineWidth: 1
        }
      }
    ],
    thresholdsY: [
      {
        fromType: "first",
        toType: "last",
        label: "Group Y",
        seriesID: "classB",
        style: {
          fillColor: "rgba(255,133,152,0.5)",
          lineColor: "rgb(0,0,0)",
          lineWidth: 1
        }
      }
    ]
  },
  style:{
    multilinkAutoCurve: 1.0,
    multilinkSpacing: 10,
    link: { isCurved: true, arcAmount: 30 },
    nodeClasses: [
      { className: "classA", style: { fillColor: "rgba(28,124,213,0.8)", lineColor: "cyan", lineWidth: 5, display: "circle" } },
      { className: "classB", style: { fillColor: "rgba(47,195,47,1)", lineColor: "yellow", lineWidth: 5, display: "circle" } },
    ],
  },
  layout: {
    mode: "static",
  },
  legend: {
    enabled: true,
    useTextColor: true,
    panel: {
      side: "bottom"
    }
  },
  toolbar: {
    enabled: true,
    extraItems: [
      { item: "lasso" }
    ]
  },
  interaction: {
    zooming: {
      shouldKeepGraphOnScreen: false,
      zoomOnSliderClick: false
    }
  },
  info: {
    enabled: true
  },
  regressionMenu: {
    contentsFunction: (data, reg, callback, args) => regressionContents(data, reg, callback, args, true)
  }
});

Data

Data
//No separate data for this example