A reusable and configurable chart to track performance against targets. Based on the common bullet chart, this simplified presentation is easily digestible for presentations and regular kpi updates. Can also be used as a more data-to-ink dense replacement of a dial chart.
Features:
Supports D3 v6 and v7
The css is not strictly required. It provides the base styles for the demo and is a useful starting point for your own charts. pacingchart-starter.css
Each row of data creates a single subchart. There is no limit on the number of subcharts that you can render at once. Each one will be treated as a flex-box div within a parent flexbox div for all the subcharts.
Required columns
NOTE: There is no required naming for the columns, they can be named anything you wish, and you can also include a human-readable name when loading the data.
Optional columns:
The makePacingChart() function takes an object map. The following data is required:
For example: targetCols = [["col1","Initial Target"],["col2","Final Target"]]
Formatting options:
If rendering multiple charts from similar data, you can templatize the settings to keep the initialization cleaner. Using the “set” method allows you to update any chart settings after initialization.
Example - Without settings template:
let chart_1 = makePacingChart({
data:dataset1,
selector: '#chart-pacing-1',
targetsCols: [['RED_THRESHOLD','Red'],['YELLOW_THRESHOLD','Yellow'],'TARGET'],
targetsMarkersCols: ['PREV_PROJECTED_AMOUNT'],
resultsCols: ['AMOUNT', ['PROJECTED_AMOUNT','Projected'],'FINAL_PROJECTED_AMOUNT'],
resultMarkersCols: ['PREV_AMOUNT'],
titleCols: ['Type'],
}).render();
let chart_2 = makePacingChart({
data:dataset2,
selector: '#chart-pacing-2',
targetsCols: [['RED_THRESHOLD','Red'],['YELLOW_THRESHOLD','Yellow'],'TARGET'],
targetsMarkersCols: ['PREV_PROJECTED_AMOUNT'],
resultsCols: ['AMOUNT', ['PROJECTED_AMOUNT','Projected'],'FINAL_PROJECTED_AMOUNT'],
resultMarkersCols: ['PREV_AMOUNT'],
titleCols: ['Type'],
}).render();
Example - With Template Settings:
let settings = {
targetsCols: [['RED_THRESHOLD','Red'],['YELLOW_THRESHOLD','Yellow'],'TARGET'],
targetsMarkersCols: ['PREV_PROJECTED_AMOUNT'],
resultsCols: ['AMOUNT', ['PROJECTED_AMOUNT','Projected'],'FINAL_PROJECTED_AMOUNT'],
resultMarkersCols: ['PREV_AMOUNT'],
titleCols: ['Type']
}
let chart_1 = makePacingChart(settings)
.set({data:dataset1,selector:'#chart-pacing-1'})
.render();
let chart_2 = makePacingChart(settings)
.set({data:dataset2,selector:'#chart-pacing-2'})
.render();
Any of the settings parameters can be updated and functions modified (see the tooltips and formatting sections) up until render() is called.
Almost every element of these charts can be styled using css.
Classes:
Example:
<svg class="performance fy23q3" id="g0-09bdc25fd13fb">
// classes match title + subtitle
<g>
<text class="title">Performance</text>
<text class="subtitle">FY23Q3</text>
</g>
<g class="targets">
// Object types are organized into their own <g> elements
<svg class="target s0 w0 w25 w50 w75 w100 w125 w150 w175 w200 w225 red-threshold red">
<rect class="target s0 w0 w25 w50 w75 w100 w125 w150 w175 w200 w225 red-threshold red"></rect>
<text class="target text s0 red-threshold red">17.8M</text>
</svg>
</g>
<g class="results">
<svg class="result s0 w0 p0 amount">
// result = type
// s0 = first bar
// w0 = 0+ pixels
// p0 = 0% width (less than 10%)
// amount = name of bar
<rect class="result s0 w0 p0 amount"></rect>
<text class="result text s0 amount">1.8M</text>
</svg>
<svg class="result s1 w0 w25 p0 p10 projected-amount projected">
// result = type
// s1 = first bar
// w0 = 0+ pixels
// w25 = 25+ pixels
// p0 = 0% width
// p10 = 10%+ width (less than 20%)
// projected-amount = column name
// projected = display name
<rect class="result s1 w0 w25 p0 p10 projected-amount projected" width="100%" height="100%"></rect>
<text class="result text s1 projected-amount projected">5.1M</text>
</svg>
<g class="results-markers">
<line class="marker s0 p0 prev-amount"></line>
</g>
</svg>
By default, targets and results are cumulative. This means that the largest target or result encompasses all the smaller ones.
Example:
You can set targets and results to additive which then means all the metrics are added on top of each other:
Example:
Setting results to additive is useful if you want to show multiple elements that make up the total performance. Such as the performance of two different teams added against a single goal.
Summary bars can be added above the target or results bars. This is a single bar that is the full width of the total target or result. It makes it easier to interpret performance when multiple elements are combined into a single result or target.
The tooltip format can be modified by providing a custom chart.tooltipGenerator() function. This function can be overwritten:
chart.tooltipGenerator = function(chartObj,eventTarget) {return chartObj.title}
The function takes two parameters:
And returns a text string that is injected into the tooltip div on hover.
Pacing chart provides three formatting functions:
All three of these can be overwritten before rendering the chart. They each take a single parameter, a number to format and return a formatted string.