Charts

A reference of generic charts implemented with Javascript and D3.js

rowchart(context, data, options)

imagen

  • context: Mandatory. HTML selector where to insert chart. Ej: #rowchart
  • data: Mandatory. JSON object to be depicted.
    • The input object, must be an array of key-value objects. Sample:
[
  {
    "key": "Baird Hampton",
    "value": 24
  },
  {
    "key": "Holmes Mckay",
    "value": 83
  },
  ...
]
  • options: Optional. Custom configurations
    • itemHeight: Row height. Number (default: 50)
    • gutter: Base padding. Number (default: 20)
    • margins: Set custom SVG margins. Based on gutter value. Object (default: { top: gutter / 1.5, right: gutter, bottom: gutter * 1.5, left: gutter })
    • xTickFormat: how to format the X-axis ticks. Function (default: d => d)
    • yTickFormat: how to format the Y-axis ticks. Function (default: d => d)
    • tooltipContainer: where is placed the tooltip. String selector, e.g. "#some", ".some" (default: body)
    • tooltipContent: what to render inside the tooltip. String or Object
      • If it's an object, it means it going to be evaluated. So the expression is: { eval: "STRING_TO_BE_EVALUATED" }
  • usage:
<!-- The chart size is determined by its parent container-->
<div id="rowchart" class="rowchart"></div>
$.getJSON("data/rowchart.json", (data) => {

  // prepare the data BEFORE the call, e.g. order higher to lower
  data.sort((a, b) => a.value - b.value)

  // Append any custom option you wish
  let opts = {
    itemHeight: 20
  }

  $(".rowchart").each((i, container) => {
    rowchart(`#${container.id}`, data, opts)
  })
});

punchcard(context, data, options)

imagen

  • context: Mandatory. HTML selector where to insert chart. Ej: #punchcard
  • data: Mandatory. JSON object to be depicted.
    • The input object, must be an array of key-value objects which value is, as well, another array of key-value objects. Sample:
[
  {
    "key": "Unia",
    "value": [
      {
        "key": "2017/12/04",
        "value": 110
      },
      {
        "key": "2017/07/14",
        "value": 159
      },
      ...
    ]
  },
  {
    "key": "Grupoli",
    "value": [
      {
        "key": "2018/03/18",
        "value": 39
      },
      ...
    ]
  },
  ...
]
  • options: Optional. Custom configurations
    • itemHeight: Row height. Number (default: 50)
    • gutter: Base padding. Number (default: 20)
    • margins: Set custom SVG margins. Based on gutter value. Object (default: { top: gutter * 1.5, right: gutter, bottom: gutter * 1.5, left: gutter * 15 })
    • xTickFormat: how to format the X-axis ticks. Function (default: d => d)
    • yTickFormat: how to format the Y-axis ticks. Function (default: d => d)
    • tooltipContainer: where is placed the tooltip. String selector, e.g. "#some", ".some" (default: body)
    • tooltipContent: what to render inside the tooltip. String or Object
      • If it's an object, it means it going to be evaluated. So the expression is: { eval: "STRING_TO_BE_EVALUATED" }
  • usage:
<!-- The chart size is determined by its parent container-->
<div id="punchcard" class="punchcard"></div>
$.getJSON("data/punchcard.json", (data) => {

  // prepare the data BEFORE the call, e.g. group by month
  for (var i = 0; i < data.length; i++) {
    let nest = d3.nest()
      .key(d => d3.timeMonth((new Date(d.key))))
      .rollup(d => _.sumBy(d, 'value'))
      .entries(data[i].value)
      .map(g => {
        g.key = d3.timeMonth(new Date(d3.timeFormat("%Y/%m/%d")(new Date(g.key))))
        return g
      })

    // update original data
    data[i].value = nest
  }

  // Append any custom option you wish
  let opts = {
    title: 'Cool Punchcard',
    xTickFormat: (d, i, arr) => ((arr.length + i) % 3) ? null : d3.timeFormat("%b %y")(d)
  }

  $(".punchcard").each((i, container) => {
    punchcard(`#${container.id}`, data, opts)
  })
});

Sparkline(context, data, options)

  • context: Mandatory. HTML selector where to insert chart. Ej: #sparkline
  • data: Mandatory. JSON object to be depicted.
    • The input object, must be an array of date-value objects. Sample:
[{
    date: "2018",
    value: 24
}, {
    date: "2017",
    value: 20
}]
  • options: Optional. Custom configurations
    • margins: Set custom SVG margins. Based on gutter value. Object (default: { top: 5, right: 5, bottom: 5, left: 5 })
  • usage:
<!-- The chart size is determined by its parent container 
       or set by HTML style attribute -->
<div id="sparkline" class="sparkline"></div>
let chart = new Sparkline(`#${container.id}`, data, options)
chart.render()

VisBubbles(divId, budgetCategory, data)

  • divId: Mandatory. HTML selector where to insert chart. Ej: #bubbles
  • budgetCategory: Accepts only two values: expense | income
  • data: Mandatory. JSON object to be depicted.
    • The input object, must be an array of objects. Sample:
[{
    "budget_category": "expense",
    "id": "15",
    "pct_diff": {
      "2016": 33.02,
      "2017": 20,
      "2018": 0
    },
    "values": {
      "2016": 503597216,
      "2017": 604335087,
      "2018": 604335087
    },
    "values_per_inhabitant": {
      "2016": 159.09,
      "2017": 189.86,
      "2018": 189.86
    },
    "level_2_es": "Vivienda y urbanismo",
    "level_2_ca": "Habitatge i urbanisme"
  }]
  • usage:
let chart = new VisBubbles('.vis-bubbles-expense', 'expense', data)
chart.render()

VisSlider(divId, data)

  • divId: Mandatory. HTML selector where to insert chart. Ej: #slider
  • data: Mandatory. JSON object to be depicted.
    • The input object, must be an array of objects. Sample:
[{
    "budget_category": "expense",
    "id": "15",
    "pct_diff": {
      "2016": 33.02,
      "2017": 20,
      "2018": 0
    },
    "values": {
      "2016": 503597216,
      "2017": 604335087,
      "2018": 604335087
    },
    "values_per_inhabitant": {
      "2016": 159.09,
      "2017": 189.86,
      "2018": 189.86
    },
    "level_2_es": "Vivienda y urbanismo",
    "level_2_ca": "Habitatge i urbanisme"
  }]
  • usage:
new VisSlider('.timeline', data)

VisTreemap(divId, size, clickable)

  • divId: Mandatory. HTML selector where to insert chart. Ej: #treemap
  • size: Aspect ratio. String. Only one value: big
  • clickable: Boolean Mandatory. JSON object to be depicted.
    • The input object, must be an array of objects. Sample:

Once initializated, data is passed through a parameter in the render function.It must be a valid URL

  • usage:
let expenseTreemap = new VisTreemap('#expense-treemap', 'big', true);
expenseTreemap.render($('#expense-treemap').data('functional-url'));

Areachart(props)

Display a value throughout the time. So then, the key must be a Date

  • props.ctx: Mandatory. HTML Node or String selector
  • props.data: Mandatory. Array to be depicted
  • props.maxWidth: Optional. Number. Maximum width of the chart. Default = 1440
  • props.minHeight: Optional. Number. Minimum height of the chart. Default = 50;
  • props.aspectRatio: Optional. Number. Aspect ratio. Default = 4;
  • props.circleSize: Optional. Number. Size of the points. Default = 3;
  • props.minValue: Optional. Number. Minimum value of the Y axis. Default = 0;
  • props.tooltip: Optional. Function. Define a callback for a custom tooltip.
  • props.xTickFormat: Optional. Function. Define how to display the Axis-X ticks. Default: "mmm YY"
  • props.marginTop: Optional. Number. Default = 10,
  • props.marginRight: Optional. Number. Default = 10,
  • props.marginBottom: Optional. Number. Default = 10,
  • props.marginLeft: Optional. Number. Default = 10

JSON data item sample

{
  key: new Date()
  value: 33
}
  • usage:
      new Areachart({
        ctx,
        data: data.map(d =>  d.values),
        tooltip,
        minValue: -5,
        marginLeft: 5,
        marginRight: 5,
        marginBottom: 0
      })

AmountDistributionBars(options)

imagen

Displays a distribution of amounts of money depending of a custom range passed as an option and a dimension of an array of Objects.

These are the options that must be provided:

  • options.containerSelector: The css selector for the HTML element where the chart will be placed. For instance, "#amount-distribution-bars"
  • options.dimension: The result of a .dimension to a crossfilter. For instance:
const ndx = crossfilter(arrayOfData);
const dimension = ndx.dimension(element => element.attribute)

Please refer to the Crossfilter API for more information.

  • options.range: An Object defining the ranges the distribution will use. For the sample image above the range must be defined as:
const amountRange = {
  domain: [501, 1001, 5001, 10001, 15001],
  range: [0, 1, 2, 3, 4, 5]
};

Please notice you don't need to define the first element (1€, in the example) in the domain since that will always be the starting value.

  • options.labelMore: A String for the label of the last element of the distribution. In the example above the value is "Más de ".

  • options.labelFromTo: A String for the header labels in the charts. In the example above the value is "Desde A Nº. Contr.".

  • options.onFilteredFunction: A Function that will be triggered after the chart has been filtered. It receives the arguments chart and filter, chart being the dc.js object and filter being the last filter applied.

usage

const renderOptions = {
  containerSelector: "#amount-distribution-bars",
  dimension: dimension,
  range: amountRange,
  labelMore: "Más de",
  labelFromTo: "Desde A Nº. Contr.",
  onFilteredFunction: (chart, filter) => {
    // do something after filtered
  }
}

const amountDistributionBars = new AmountDistributionBars(renderOptions);

The chart will be automatically rendered on initializing. Initializing it will return a AmountDistributionBars object. With that, you can access directly to the dc.js chart with:

amountDistributionBars.container

This object will also have a function setContainerSize() that will resize the chart according to the current dimension of its HTML element. This might be helpful if you initialize the chart without the HTML being visible. This module, by default, will automatically resize the chart accordingly on initializing, but if the target element is not visible the size calculations will not work properly. Using amountDistributionBars.setContainerSize() you may resize it at any later moment when is visible.