Home Reference Source

src/svg/components/xAxis.js

import {isEven} from '../../utils/functions';
import {select, scaleTime, scaleLinear, scaleBand, axisBottom} from 'd3';

export class XAxis {
  constructor(xAxisType, config) {
    if (config === null) {
      throw new Error('No chart context specified for XAxis');
    }

    this.xAxis = this._initializeXAxis(xAxisType, config);
  }


  rescale(width, height) {
    this.xAxis.scale().range([0, width]);
  }

  _initializeXAxis(xAxisType = 'linear', config) {
    let x = null,
      xAxis = null;

    switch (xAxisType) {
      case 'time':
        x = scaleTime().range([0, config.width]);
        break;
      case 'linear':
        x = scaleLinear().range([0, config.width]);
        break;
      case 'categorical':
        x = scaleBand().rangeRound([0, config.width])
          .padding(0.1)
          .align(0.5);
        break;
      default:
        throw new Error('Not allowed type for XAxis. Only allowed "time",  "linear" or "categorical". Got: ' + xAxisType);
    }

    return axisBottom(x);
  }

  transition(svg, time = 200) {
    svg.selectAll('.x.axis').transition().duration(time).call(this.xAxis).on('end', this.xStyle);
  }

  xStyle() {
    select(this).selectAll('g.tick text')
      .style('font', '1.4em Montserrat, sans-serif')
      .style('fill', (d, i) => !isEven(i) || i === 0 ? '#5e6b70' : '#1a2127')
      .style('fill', (d) => '#1a2127')


    select(this).selectAll(['path', 'line'])
      .attr('stroke', 'gray')
      .attr('stroke-width', .3)

  }

  /**
   * This function is used when both x and y dial update their domains by x and y max/min values, respectively.
   */
  updateDomainByBBox(b) {
    let x = this.xAxis.scale();
    x.domain([b[0], b[1]]);
  }

  /**
   * Used when x domain is caterogial (a set of keys) and y domain is linear.
   */
  updateDomainByKeys(keys, yBbox) {
    let x = this.xAxis.scale();
    x.domain(keys);
  }

  render(svg, config) {
    let xAxis = this.xAxis,
      width = config.width,
      height = config.height;
    svg
      .append('g')
      .attr('class', 'x axis')
      .attr('transform', 'translate(0,' + config.height + ')')
      .call(xAxis);

    svg
      .append('text')
      .attr('class', 'xaxis-title')
      .attr("text-anchor", "middle")
      .attr('x', width / 2)
      .attr('y', height + 40)
      .text(config.xAxisLabel)
      .style('font', '0.8em Montserrat, sans-serif');

    this.svg = svg;
  }
}