Reference Source

src/components/AxisChart.js

import { min, max } from 'd3-array';
import { select } from 'd3-selection';
import { scaleLinear, scaleBand } from 'd3-scale';
import Chart from './Chart';
import Key from './Key';
import Axis from './Axis';

/**
* Create AxisChart from the supplied data, based on the supplied JSON config.
*
* @class AxisChart
* @extends {Chart}
* @constructor
*/
export default class AxisChart extends Chart {

  /**
  * The d3 object for the chart's group
  *
  * @property d3ChartGroup
  * @type {Object}
  */
  d3ChartGroup;

  /**
  * The d3 object for the chart's axis
  *
  * @property d3AxisGroup
  * @type {Object}
  */
  d3AxisGroup;

  /**
  * The chart's axis object
  *
  * @property oAxis
  * @type {Object}
  */
  oAxis;

  /**
  * The chart's key object
  *
  * @property oKey
  * @type {Object}
  */
  oKey;

  /**
  * Constructor function supersedes parent class.
  *
  * @method constructor
  * @param {Object} oParams same as Chart
  */
  constructor(oParams = {}) {
    super(oParams);
    this.jPadding = { l: 45, r: 15, t: 25, b: 90 };
    this.oScaleY = scaleLinear();
    this.oScaleX = scaleBand().padding(0.2);
  }

  /**
  * Supersede the parent method to update local scaling objects
  *
  * @method setDimensions
  */
  setDimensions() {
    super.setDimensions();
    const bTrim = this.jConfig.bTrim;
    let iMinValue = bTrim ? min(this.aData, d => min(d.aValues)) : 0;
    let iMaxValue = max(this.aData, d => max(d.aValues));
    const iSection = Math.ceil(iMaxValue / 15);
    if (bTrim) {
      const iLowerSection = iMinValue > iSection ? iMinValue - iSection : 0;
      iMinValue = iMinValue > 0 ? iLowerSection : iMinValue;
      iMinValue = iMinValue < 0 ? iMinValue - iSection : iMinValue;
      iMaxValue += iSection;
    }
    this.oScaleX
      .domain(this.aData.map(d => d.sLabel))
      .range([0, this.iInnerWidth]);
    this.oScaleY
      .domain([iMinValue, iMaxValue])
      .range([this.iInnerHeight, this.jPadding.t]);
    this.iMinValue = iMinValue;
    this.iMaxValue = iMaxValue;
    this.iSection = iSection;
  }

  /**
  * Render the chart including axes and labels
  *
  * @method renderChart
  */
  renderChart() {
    const { aAxisLabels, iTruncate = 15 } = this.jConfig;
    const { iInnerWidth, iInnerHeight, oScaleX, oScaleY, jPadding } = this;

    // Add chart scale axes
    this.d3AxisGroup = this.d3AxisGroup || this.d3Svg.append('g').attr('class', 'axes-g');
    this.oAxis = new Axis({
      d3Container: this.d3AxisGroup,
      iTruncate,
      aAxisLabels,
      oScaleX,
      oScaleY,
      jPadding,
      iWidth: iInnerWidth,
      iHeight: iInnerHeight,
      oTooltip: this.oTooltip }).render();

    // Add chart container group
    this.d3ChartGroup = this.d3ChartGroup || this.d3Svg.append('g').attr('transform', `translate(${this.jPadding.l}, 0)`);

    // Render the key for the data
    this.oKey = new Key({
      d3Container: select(this.dSvg),
      aValues: this.jConfig.aValues,
      iOffsetX: (this.iInnerWidth / 2) + this.jPadding.l,
      iOffsetY: this.iHeight - 20
    }).render();
  }

}

module.exports = AxisChart;