animated-bars
v0.2.4
Published
A library for creating animated bar and column charts.
Downloads
14
Maintainers
Readme
animated-bars
animated-bars is a JavaScript library for creating animated bar and column charts in webpages. The library exports two classes, AnimatedBarChart
and AnimatedColumnChart
, which differ in the orientation of their bars but which are functionally identical.
Create a chart by providing some data and a configuration object. When you update
a chart with new data, it animates a transition to the new values given the settings in the configuration. A chart can be run
so that it steps through a sequence of different values at fixed intervals by providing an ES6 generator that yields new data each time it is called.
The library uses D3 to make the charts, but provides a high level interface so that you can use it on its own. However, the D3 selections used to create and run the chart are exposed in the chart object, so you can easily extend a chart's behaviour using D3 if you wish.
Please note that while the library is functional it is not yet 1.0. Until then, its interfaces may evolve in response to feedback.
Installation
Install the library with npm
for transpiling and bundling.
npm install --save-dev animated-bars
Then import the classes you need in your code.
import { AnimatedColumnChart } from "animated-bars";
// Define config and data then ...
const chart = new AnimatedColumnChart(data, config);
Alternatively, you can use the browser library directly in a webpage. Load animated-bars.min.js
in a <script>
tag to make the library available as a global object called animatedBars
.
<script src="animated-bars.min.js"></script>
<script>
// Define config and data then ...
const chart = new animatedBars.AnimatedColumnChart(data, config);
</script>
The browser library can be found in the dist
directory.
Core principles
The library aims to provide a simple and flexible interface to easily create and update animated bar and column charts. The interface is organised around some core ideas.
Animated charts are instatiated with two components: some initial data and a config.
data is an array of objects representing data points, each of which must contain a key and a value property. These data point objects can optionally have other properties which specify how the chart should present indiviudal values. New
data
that is used to update a chart must have the same keys as thedata
that was used to create it. See the section on data below for full details of data points and their properties.config is an object whose properties are used to configure the chart. The
config
object supports a number of properties that govern the chart's behaviour, but you only need to explicitly define properties that differ from the defaults. See configuration below for full details of the properties that can be set in theconfig
object, their default values, and the behaviour they control.
The axes of a chart are described in terms of keys and values rather than x and y: there is a keyAxis and a valueAxis. This approach allows you to describe the structure of a chart independently of which way its bars are oriented. The same data and configuration will work for both bar and column charts, although different configurations may be more appropriate for one type than the other.
Example usage
A detailed set of examples showing how to use the library can be found in the example
directory. You can see these examples running on the web here. The walkthrough below shows the basic steps needed to create, update, and animate a chart.
Create a chart
Let's create a simple animated column chart. The following example assumes you are working with npm
but can be quickly adapted to work in the browser by following the slightly different setup instructions shown above. A version of this code using the browser library can be found in the walkthrough
directory in example
.
Create a <div>
element for the chart in your html.
<div id="example-column-chart"></div>
Import the chart you need from the package (or load the browser library in a <script>
tag), define or load some data, then define a config for the chart. The element
property of the config
identifies the id of the target element in your html.
import { AnimatedColumnChart } from "animated-bars";
// The data object is an array of key/value pairs
const data = [
{key: "A", value: -30},
{key: "B", value: -20},
{key: "C", value: -10},
{key: "D", value: 10},
{key: "E", value: 20},
{key: "F", value: 30}];
// Settings in the config object will override the defaults
const config = {
element: "example-column-chart",
dimensions: {
width: 700,
height: 500
},
valueMin: -40,
valueMax: 40
};
// Instantiate the chart object
const chart = new AnimatedColumnChart(data, config);
// Call the chart's create method to render it in the DOM
chart.create();
Update a chart
Let's update the chart with new data in response to an event. We can trigger the update when the chart is clicked by calling update
inside the click handler for the chart's svg
selection (you can read more about selections below). This is just a simple way to trigger the update for this example: you can update the chart in response to any event by calling update
with new data.
// New data must use the same keys as the initial data
const newData = [
{key: "A", value: 30},
{key: "B", value: -20},
{key: "C", value: 40},
{key: "D", value: -10},
{key: "E", value: -25},
{key: "F", value: 15}];
// Trigger the update on click using the svg selection
chart.selections.svg.on("click", () => chart.update(newData));
The chart's bars will transition to the new values over an interval of time that is given by the transitionTime
in the chart's config
object. We didn't specify a transitionTime
in our configuration but the default is one second. You can also set the transition time for an individual transition as an optional second argument to update
. The transition time is always set in milliseconds.
// A five second transition
chart.update(newData, 5000);
Animate a chart with a generator
You can update a chart to show new values at fixed intervals using an ES6 generator. The generator should yield new values for the chart's keys each time it is called. Call a chart's run
method with a generator to animate the chart through the sequence of values the generator yields. The chart will transition between the values using the transitionTime
and pauseTime
values set in the config
: the pause follows the transition.
Define a generator, then change the click-handler to call the chart's run
method with the generator.
// Define a generator that yields random values for this chart
function* randomGenerator() {
const keys = ["A", "B", "C", "D", "E", "F"];
while (true) {
const nextData = keys.map(d => {
return {key: d, value: Math.random() * 80 - 40};
});
yield nextData;
}
}
// Call the chart's run method with the generator on click
chart.selections.svg.on("click", () => chart.run(randomGenerator()));
You can check if a chart is currently running a generator through its running
property, and you can stop a chart with its stop
method. We could update our click handler to start and stop the chart animating random values.
chart.selections.svg.on("click", () => {
if (chart.running) {
chart.stop();
chart.update(data);
} else {
chart.run(randomGenerator());
}
});
You can find out more about the methods and properties of charts below.
Constructors
AnimatedBarChart(data, config) AnimatedColumnChart(data, config)
See the data and configuration sections below for details of the constructor arguments.
Data
Animated bar and column charts must be instantiated, and can be updated, with a data
object. This is an array of data point objects, each of which must contain the following properties:
key - A unique string identifying the data point. The key is used as the label for the data point on the chart's keyAxis.
value - A number representing a value for the data point. This will determine the length of the bar representing the data point on the chart. The value should fall between the lowest and highest values on the valueAxis, which are specified by the valueMin and valueMax properties of the
config
object. If the value is below or above this range, the chart will show the valueMin or valueMax respectively for the data point, and a warning will be shown on the console.
The data point items may optionally contain the following properties:
posRgb A string representing an RGB color value for the color of the bar if the value of the data point is positive e.g.
"#55bbee"
, or"rgb(85, 187, 283)"
.negRgb A string representing an RGB color value for the color of the bar if the value of the data point is negative e.g.
"#ee5599"
, or"rgb(238, 85, 153)"
.delay A number of milliseconds to delay the transition for this data point. By giving different length delays to different data points you can create various visual effects as the chart updates. See the section on transitions below for further information on the timing of transitions.
If these optional values are not set, posRgb and negRgb default to the equivalent values set in the config
object, and delay defaults to zero milliseconds.
Configuration
The default configuration values for both the AnimatedBarChart
and AnimatedColumnChart
are shown below.
{
element: "chart",
dimensions: {
width: 800,
height: 450
},
margins: {
top: 80,
right: 80,
bottom: 80,
left: 80
},
colors: {
posRgb: "#55bbee",
negRgb: "#ee5599"
},
background: "",
title: "",
titleSize: 22,
titleColor: "#000000",
titleOffsetX: 20,
titleOffsetY: 40,
subtitle: "",
subtitleSize: 17,
subtitleColor: "#000000",
subtitleOffsetX: 20,
subtitleOffsetY: 30,
keyLocation: "min",
keyTitle: "Key title",
keyTitleSize: 11,
keyTitleColor: "#000000",
keyTitleOffset: 50,
keyTextSize: 11,
keyTextColor: "#000000",
keyLineColor: "#000000",
keyTickSizeInner: 6,
keyTickSizeOuter: 6,
keyTickPadding: 3,
valueLocation: "start", // "start" or "end" depending on the class
valueTitle: "Value title",
valueTitleSize: 11,
valueTitleColor: "#000000",
valueTitleOffset: 50,
valueMin: -100,
valueMax: 100,
valueTextSize: 11,
valueTextColor: "#000000",
valueLineColor: "#000000",
valueTicks: 5,
valueTickSizeInner: 6,
valueTickSizeOuter: 6,
valueTickPadding: 3,
valueFormat: "",
valuePaddingInner: 0.1,
valuePaddingOuter: 0.1,
shapeRendering: "auto",
transitionTime: 1000,
pauseTime: 1000
}
There is one property that has a different default value for each class, which is the valueLocation property. For an AnimatedBarChart
the default is "end"
, while for an AnimatedColumnChart
the default is "start"
.
The properties are:
element - A string containing the id of the html element within which the SVG of the chart will be created. This should normally be a
<div>
. Note that a leading hash symbol is not necessary.dimensions - An object containing width and height properties. These are the dimensions of the SVG for the chart.
margins - An object containing top, right, bottom and left properties. These are the widths of the margins for the chart according to the D3 margin convention. Note that the plot area of the chart is equal to the dimensions minus the margins. In other words, the larger the margins, the smaller the plot area. These margins should be made large enough to accommodate the labels specified elsewhere in the configuration, such as the title, the subtitle, the axis titles, and the tick labels. The default values for the margins are large enough to accomodate the axis titles and the tick labels at standard font-sizes, but you may need to increase or reduce them to suit your needs.
colors - An object containing posRgb and negRgb properties. These two properties should contain strings representing RGB color values, such as
"#55bbee"
, or"rgb(238, 85, 153)"
. posRgb defines the color of bars that show positive values. negRgb defines the color of bars that show negative values. If you want all bars to have the same color irrespective of whether they are positive or negative, set these to the same value.background - A string representing an RGB color value for the chart background. If this string is set, a
rect
element is added to the chart as a background layer, filling the entire svg with the given background color. If the string is empty, arect
element is not appended as a background layer.title - A string containing the title for the chart. This can be set to
null
if a title is not needed.titleSize - An integer specifying the font-size of the title. You can control this value using styles but it is provided as a configuration option so that you can scale the text based on the size of the chart's container.
titleColor - A string representing an RGB color value for the title.
titleOffsetX - A number specifying the distance of the title from the left-hand edge of the chart.
titleOffsetY - A number specifying the distance of the title from the top edge of the chart.
subtitle - A string containing the subtitle for the chart. This can be set to
null
if a subtitle is not needed.subtitleSize - An integer specifying the font-size of the subtitle. You can control this value using styles but it is provided as a configuration option so that you can scale the text based on the size of the chart's container.
subtitleColor - A string representing an RGB color value for the subtitle.
subtitleOffsetX - A number specifying the distance of the subtitle from the left-hand edge of the chart.
subtitleOffsetY - A number specifying the distance of the subtitle from the title.
keyLocation - A string specifying the location of the keyAxis. The keyLocation is defined in relation to the values on the valueAxis. Valid locations are:
min
- The keyAxis is located at the minimun value of the valueAxis.zero
- The keyAxis is located at the zero value of the valueAxis.max
- The keyAxis is located at the maximum value of the valueAxis.
keyTitle - A string containing the title for the keyAxis. This can be set to
null
if a keyTitle is not needed.keyTitleSize - An integer specifying the font-size of the keyTitle. You can control this value using styles but it is provided as a configuration option so that you can scale the text based on the size of the chart's container.
keyTitleColor - A string representing an RGB color value for the keyTitle.
keyTitleOffset - A number specifying the distance of the keyTitle from the keyAxis. The optimum distance will depend on font-sizes, tick labels, margins etc.
keyTextSize - An integer specifying the font-size of the tick labels on the keyAxis. You can control this value using styles but it is provided as a configuration option so that you can scale the text based on the size of the chart's container.
keyTextColor - A string representing an RGB color value for the tick labels on the keyAxis.
keyLineColor - A string representing an RGB color value for the axis line and ticks on the keyAxis.
keyTickSizeInner - A number specifying the length of the tick lines associated with the tick labels on the keyAxis.
keyTickSizeOuter A number specifying the length of the tick lines at either end of the keyAxis. Setting this to zero removes the tick lines that bookend the keyAxis.
keyTickPadding - A number specifying the distance between the ticks and the tick labels on the keyAxis.
valueLocation - A string specifying the location of the valueAxis. The valueLocation is defined in relation to the keyAxis. Valid locations are:
start
- The valueAxis is located at the start of the keyAxis.end
- The valueAxis is located at the end of the keyAxis.
valueTitle - A string containing the title for the valueAxis. This can be set to
null
if a valueTitle is not needed.valueTitleSize - An integer specifying the font-size of the valueTitle. You can control this value using styles but it is provided as a configuration option so that you can scale the text based on the size of the chart's container.
valueTitleColor - A string representing an RGB color value for the valueTitle.
valueTitleOffset - A number specifying the distance of the valueTitle from the valueAxis. The optimum distance will depend on font-sizes, tick labels, margins etc.
valueMin - A number specifying the minimum value of the valueAxis.
valueMax - A number specifying the maximum value of the valueAxis.
valueTextSize - An integer specifying the font-size of the tick labels on the valueAxis. You can control this value using styles but it is provided as a configuration option so that you can scale the text based on the size of the chart's container.
valueTextColor - A string representing an RGB color value for the tick labels on the valueAxis.
valueLineColor - A string representing an RGB color value for the axis line and ticks on the valueAxis.
valueTicks - A number specifying the suggested number of ticks for the valueAxis. Note that because the domain of the valueAxis is set explicitly with valueMin and valueMax, the exact number of ticks given by this argument may not be honoured exactly. D3 aims for evenly spaced ticks on round, readable values, and the valueTicks argument is treated as a hint towards this end. The desired number of ticks are typically shown if they create intervals that are multiples of 2, 5 or 10 on the valueAxis. The animated bar and column charts have methods for removing individual tick lines and labels from both axes, which can help with more advanced tick formatting requirements if valueTicks doesn't give you exactly what you want on its own.
valueTickSizeInner - A number specifying the length of the tick lines associated with the tick labels on the valueAxis.
valueTickSizeOuter A number specifying the length of the tick lines at either end of the valueAxis. Setting this to zero removes the tick lines that bookend the valueAxis. Note that there may be both inner and outer ticks at the ends of the valueAxis, so to remove all ticks in these positions you may need to set both valueTickSizeInner and valueTickSizeOuter to zero, or use the removeValueAxisTicks method of the chart to selectively remove the inner ticks at the ends of the valueAxis. See methods below for further details.
valueTickPadding - A number specifying the distance between the ticks and the tick labels on the valueAxis.
valueFormat - A string representing a D3 format specifier for the valueAxis. This allows you to present values on the valueAxis as percentages, currency, using a comma separator for thousands etc.
valuePaddingInner - A number specifying the size of the padding to insert between the bars in the chart.
valuePaddingOuter - A number specifying the size of the padding to insert between the bars and the edges of the chart.
shapeRendering - A string that represents the value passed to the
shape-rendering
attribute of therect
elements used to draw the bars on the chart. Valid values are "auto", "optimizeSpeed", "crispEdges", and "geometricPrecision". The default value is "auto", which is fine in most cases. Using "geometricPrecision" can be useful if you want the most even spacing between the bars, while "crispEdges" is useful when you have no gaps between the bars or when you want to animate all the bars dropping to zero.transitionTime - A number specifying the default duration in milliseconds of the transition from one value to the next when a chart is updated with new data. See the section on transitions for further information on the timing of transitions.
pauseTime - A number specifying the default duration in milliseconds of the pause between updates to a chart when a chart is run with a generator. See the section on transitions for more information about the timing of transitions.
Methods
create()
Creates the animated chart as an object in the DOM. The chart is rendered inside the html element with the id specified in config.element
.
update(nextData, transitionTime = config.transitionTime)
Updates the chart to show the data in nextData
. nextData
must be a data
object with same keys that were contained in the data
object used to initialise the chart. The transitionTime
argument specifies the length of the transition in milliseconds. transitionTime
is an optional argument. If it is not set explicitly in a call to update
the chart will use the transitionTime
provided by the config
when the chart was initialised.
run(generator, callback = () => {}, callbackDelay = 0)
Updates the chart with values drawn from the generator
at fixed intevals. The total interval between updates is equal to the charts transitionTime
, plus its pauseTime
, plus the longest delay specified for a data point in the data
object returned from the generator.
The final value returned by the generator (the value returned when done
is true
) is not used to update the chart. In other words, your generator should yield
data and return
when there is no more data to yield.
The run
method can optionally take a callback
which is called at the start of each update. The default callback
is an empty function i.e. it does nothing, but you can provide a callback in order to update other parts of your data visualisation in lock-step with updates to the chart.
The callbackDelay
is an optional argument that specifies a time in milliseconds to delay the callback from the start of each update. This can be used to help visually synchronise changes made by the callback with changes to the animated bars.
stop()
Stops the chart updating from a generator.
removeKeyAxisTicks(tickNums, options = {lines: true, labels: true})
removeValueAxisTicks(tickNums, options = {lines: true, labels: true})
Removes the specified ticks from the keyAxis or valueAxis. tickNums
is an array of numbers specifying the indexes of the ticks to be removed. The options
argument is an optional argument that controls which elements of the ticks are removed. By default both the tick lines and the tick labels are removed for the selected ticks, but setting either option to false
means those elements of the selected ticks are retained. This can be useful if you wish to remove some labels, while leaving all the ticks in place. Note that as these functions work by removing the tick elements from the DOM, they can only be called after the chart is created.
keepKeyAxisTicks(tickNums, options = {lines: true, labels: true})
keepValueAxisTicks(tickNums, options = {lines: true, labels: true})
Removes the unspecified ticks from the keyAxis or valueAxis. These functions have the same effect as the functions used to remove ticks, but in these functions the tickNums
argument specifies the ticks to retain, rather than the ticks to remove. These functions are a convenience for when the number of ticks you wish to remove is larger than the number of ticks you wish to retain. Note that as these functions work by removing the tick elements from the DOM, they can only be called after the chart is created.
Properties
The AnimatedBarChart
and AnimatedColumnChart
classes have a set of properities that correspond to each of those in the config
object. In addition, there are a handful of other properties that may be useful when working with these charts.
height - The height of the plot area. This is equal to
dimensions.height
-margins.top
-margins.bottom
.width - The width of the plot area. This is equal to
dimensions.width
-margins.left
-margins.right
.created - A boolean indicating whether the chart's
create
method has been called.running - A boolean indicating whether the chart's
run
method is in the process of updating the chart from a generator.selections - An object containing the D3 selections used to build the chart. See selections below for further information.
Transitions
When a chart's update
method is called with new data
, the chart's bars will begin transitioning to the new values. The duration of the transition is controlled by the transitionTime
. A default transitionTime
is set in the chart's config
but the duration of an individual transition can also be set with an optional second argument to update
.
The data
passed to update
may optionally specify a delay to the start of the transition for each data point. This means that the total amount of time between update
being called and all consequent transitions completing is equal to the tranistionTime
plus the longest delay specified for any of the data points.
When a chart is run
with a generator, update
is called repeatedly. The timing of the next call to update
is equal to the tranistionTime
, plus the longest delay specified for a data point, plus the pauseTime
.
The run
method can optionally take a callback
so that you can trigger changes to other parts of the user interface in lock-step with changes to the chart. This function is called after callbackDelay
, which specfies the number of millisecods after update
that the callback
is called. The default callbackDelay
is zero.
The chart's stop
method will cancel the next scheduled update
but will not interrupt the current transition or cancel a scheduled callback
. This ensures that update
and callback
are called the same number of times if you keep starting and stopping the chart.
The library does not currently support specifying a different transitionTime
for each data point, only a different delay
. I can't see a use case for this but would consider implementing it if there is sufficient interest.
Selections
This library uses D3 to create animated charts. Some of the most important D3 selections used to build the charts are exposed in each chart's selections
property. These selections are:
svg - The selection that holds a reference to the SVG element containing the chart.
dataGroup - The selection that holds a reference to the group element for the chart's plotting area i.e. the region of the chart inside the margins.
keyAxisGroup - The selection that holds a reference to the group element for the keyAxis.
valueAxisGroup - The selection that holds a reference to the group element for the valueAxis.
You can use these selections to do further chart customisaton using D3 functions. For example, if you wish to add a line or a label to a chart you can append a path or text element to the dataGroup.
One example of additional customisation you may wish to do is more advanced formatting of the axes. For instance, this library does not currently provide an interface for rotating the text of axis tick labels. But you can control the rotation of this text using the D3 selections in the following way.
// Use a selection to rotate the keyAxis labels
chart.selections.keyAxisGroup
.selectAll("text")
.attr("y", 0)
.attr("x", -10)
.attr("dy", ".35em")
.attr("transform", "rotate(270)")
.style("text-anchor", "end");
To do this kind of additional customisation you may sometimes need to import additional functions from D3 into your script, depending on exactly what you want to do. This is not needed for the tick label rotation shown above.
Styling
The library adds classes to some chart elements, which you can use to style parts of the chart with CSS. All of the classes are prefixed ab-
to denote they were added by animated-bars. Classes you can safely target to style different parts of the chart are:
.ab-title
- Add styles to the text of the title..ab-subtitle
- Add styles to the text of the subtitle..ab-key-axis
- Add styles to the text of the keyAxis..ab-key-title
- Add styles to the text of the keyAxisTitle..ab-value-axis
- Add styles to the text of the valueAxis..ab-value-title
- Add styles to the text of the valueAxisTitle.
One style you may wish to apply globally to the chart is to turn off pointer-events for text elements of the SVG. This stops the cursor from turning into an insertion point as you mouse over text within the chart.
text {
pointer-events: none;
}