- Overview
- Documents
xCharts is a JavaScript library for building beautiful and custom data-driven chart visualizations for the web using D3.js. Using HTML, CSS, and SVG, xCharts are designed to be dynamic, fluid, and open to integrations and customization.
Since xCharts use SVG, we are able to accomplish most of our styling of xCharts directly through CSS. This means you have quite a bit of control to handle the visualization however you want. The best way to style charts is to start with the included stylesheet, or use your browser’s element inspector to see each elements CSS class selectors that are available to use.
Quick Start
Download and include D3.js on your page.
Download and include xcharts.js and xcharts.css on your page.
Configure your data using xChart's Data Format.
Add an element with a defined width and height to your page to display your chart:
xCharts will fit to the given element's width and height. It's important to have these values set on the element or in a stylesheet. On window resize, if the element resizes, xCharts will resize accordingly, so that it can continue to fit in the allotted space.
xCharts uses its input data to instruct it on how the dataset should be drawn. By providing the following data, an xChart will be instructed to draw an ordinal bar chart with a linear scale, containing two ordinal ticks on the x-axis for "Pepperoni" and "Cheese". There will also be a secondary dotted-line component overlayed on top of the bars.13
xScale
Scale type to use along the x-axis (horizontal).
yScale
Scale type to use along the y-axis (vertical).
xMin
Minimum allowed value on the xScale. If null, uses the data's min value, logically padded for aesthetics. Does not affect ordinal scales.
xMax
Maximum allowed value on the xScale. If null, uses the data's max value, logically padded for aesthetics. Does not affect ordinal scales.
yMin
Minimum allowed value on the yScale. If null, uses the data's min value, logically padded for aesthetics. Does not affect ordinal scales.
yMax
Maximum allowed value on the yScale. If null, uses the data's max value, logically padded for aesthetics. Does not affect ordinal scales.
type optional
The vis type to force the main data to display with. If not provided, will use the last set vis type, or the one provided at xChart creation time.
main
An array of data sets to be drawn.
A unique CSS Selector of classes to use in identifying the elements on the chart.
It's doubly important to note that this should be unique per chart. xCharts uses this value to determine whether a visualization should be destroyed or updated when changing data. If you reuse this selector, the current displayed visualization using this selector will be transitioned to match the new data.
An array of objects containing the x and y values. This data will be converted to ascending sort by xCharts.
comp optional
An array of data sets to be used as comparisons to the main data set. This set differs from main in that each set must have its own independent vis type
Download D3.js
Download xCharts
Configure Your Data
Set Up Your Page
<figure style="width: 400px; height: 300px;" id="myChart"></figure>
Create Your Chart
var myChart = new xChart('bar', data, '#myChart');
Data Format
Example Data
{
"xScale": "ordinal",
"yScale": "linear",
"type": "bar",
"main": [
{
"className": ".pizza",
"data": [
{
"x": "Pepperoni",
"y": 12
},
{
"x": "Cheese",
"y": 8
}
]
}
],
"comp": [
{
"className": ".pizza",
"type": "line-dotted",
"data": [
{
"x": "Pepperoni",
"y": 10
},
{
"x": "Cheese",
"y": 4
}
]
}
]
}
{
"className": ".pizza",
"data": [
{
"x": "Pepperoni",
"y": 12
},
{
"x": "Cheese",
"y": 8
}
]
}
className
data
setData(data)
Change the data that for this chart and animate from the current display to the new data.
See Data Format for format and more information.
setType(type)
Change the vis type for this chart and animate the display.
The vis type to force the main data to display with. If not provided, will use the last set vis type, or the one provided at xChart creation time.
setScale(axis, type)
Update an axis' scale type.
The axis to change
Scale type to use along the y-axis (vertical).
Methods
mouseover
Callback behavior for a user mousing over a data point.
mouseout
Callback behavior for a user mousing off a data point.
click
Callback behavior for a user clicking a data point.
axisPaddingTop
Amount of space between the top of the chart and the top value on the y-scale.
axisPaddingRight
Amount of space between the right side of the chart and the highest value on the x-scale.
axisPaddingBottom
Amount of space between the bottom of the chart and the lowest value on the y-scale.
axisPaddingLeft
Amount of space between the left side of the chart and the lowest value on the x-scale.
xMin
Minimum allowed value on the xScale. If null, uses the data's min value, logically padded for aesthetics. Does not affect ordinal scales. May be overrided using the setData method with the xMin data format key.
xMax
Maximum allowed value on the xScale. If null, uses the data's max value, logically padded for aesthetics. Does not affect ordinal scales. May be overrided using the setData method with the xMax data format key.
yMin
Minimum allowed value on the yScale. If null, uses the data's min value, logically padded for aesthetics. Does not affect ordinal scales. May be overrided using the setData method with the yMin data format key.
yMax
Maximum allowed value on the yScale. If null, uses the data's max value, logically padded for aesthetics. Does not affect ordinal scales. May be overrided using the setData method with the yMax data format key.
paddingTop
Amount of space from the top edge of the svg element to the beginning of the axisPaddingTop.
paddingRight
Amount of space from the right edge of the svg element to the beginning of the axisPaddingRight.
paddingBottom
Allows space for the x-axis scale. Controls the amount of space from the bottom edge of the svg element to the beginning of theaxisPaddingBottom.
paddingLeft
Allows space for the y-axis scale. Amount of space from the left edge of the svg element to the beginning of the axisPaddingLeft.
tickHintX
The amount of ticks that you would like to have displayed on the x-axis. Note: this is merely a guide and your results will likely vary.
tickFormatX
Provide alternate formatting for the x-axis tick labels.
tickHintY
The amount of ticks that you would like to have displayed on the y-axis. Note: this is merely a guide and your results will likely vary.
tickFormatY
Provide alternate formatting for the y-axis tick labels.
dataFormatX
A method to pre-format the input data for the x-axis before attempting to compute a scale or draw.
dataFormatY
A method to pre-format the input data for the y-axis before attempting to compute a scale or draw.
sortX
Provide a method to custom-sort x-axis data. Must be a valid array comparator, returning -1, 0, or 1.
unsupported
A callback method that will be invoked if SVG is not supported in the viewer's browser.
noDataMainOnly
TODO: fix and remove this
empty
A callback method invoked when the data set provided was empty and there is nothing to draw.
notempty
The opposite of empty. Invoked if the data set provided was not empty.
timing
The amount of time, in milliseconds, to transition during draw/update.
interpolation
Line interpolation to use when drawing lines. See d3.js's line.interpolate for more information.
Chart Options
By default, xCharts includes four scale types: ordinal, linear, time, and exponential. However, you can create custom scale types very easily.
Custom Scales
function myScale(data, axis, bounds, extents) {
return d3.scale.linear()
.domain(extents)
.nice()
.rangeRound(bounds);
}
xChart.setScale('scale-name', myScale);
Arguments
Since xCharts (and D3.js) use SVG, we are able to accomplish most of our styling of xCharts directly through CSS. This means that, unlike many other charting libraries, you have quite a bit of control to handle the visualization however you want.
The best way to style charts is to start with the included stylesheet, or use your browser's element inspector to see each elements CSS class selectors that are available to use.
Each series in the chart is assigned a class, based on its index in your main and comp data sets: .color0 through .colorN. While there can be an infinite amount of colors, it is recommended that you never chart more than 10 series at a time. Thus, only 10 colors are included in the starter stylesheet.
Styling Your Chart
Series Colors
xCharts follows the "Enter, Update, Exit" methodology of D3.js. If you're unfamiliary with D3, a good starting reference point is Thinking With Joins.
To create your own vis type and make it available to xCharts, simply create an object of the necessary methods and define it for xCharts using the xChart.setVis(name, methods); method.
It can be useful, at times, to extend a base vis type. For example, if you'd like to create a vis type that uses logic from the line vis type, simply ask xChart for the methods and reuse them:
For a more detailed and working example, check out the Error Bars Custom Vis Type.
preUpdateScale(self, scaleData, mainData, compData)
Optional. Executed before the scales have been created for the given data sets.
In cumulative charts, before we create the scale, we need to actually convert our raw data into cumulative data.
This example is very barebones and for demonstration only. The actual process used by the cumulative vis type is much more involved and handles actually setting values and remembering original states.
postUpdateScale(self, scaleData, mainData, compData)
Optional. Executed after the scales have been created for the given data sets.
In bar charts, we need to create a second scale that will inform us how wide each bar series should be, and where they should be placed. For this, we use postUpdateScale to calculate a second ordinal scale, with reference to the first:
enter(self, storage, className, data)
As the first draw step, enter is used to create any elements that we need and bind the data information to each element.
update(self, storage, timing)
During update, we loop over every element and transition its appearance, based on any changes that may have been made to our data series.
Using our previous example from enter, we'll continue with updating our lines:
exit(self, storage, timing)
Called as the last step of updating a vis, in this method we hide any visual elements that are no longer being used–elements from a previous data series that no longer exist in the new series.
During the exit method, we merely provide instructions for hiding the visual elements:
destroy(self, storage, timing)
In the last step of our vis, we remove all displayed elements. This method is most called when xChart is instructed to change vis-types for the entire chart.
Since we'll be removing everything here, we'll transition the opacity to zero and then remove the elements:
Custom Vis Types
var myVis = {
preUpdateScale: function () { /*...*/ }, // optional
postUpdateScale: function () { /*...*/ }, // optional
enter: function () { /*...*/ },
update: function () { /*...*/ },
exit: function () { /*...*/ },
destroy: function () { /*...*/ }
};
xChart.setVis('myvis', MyVis);
Extending Base Vis Types
var line = xChart.getVis('line');
var myVis = {
enter: function (self, storage, className, data) {
line.enter.apply(this, arguments);
// Do your custom actions here
},
update: function (self, storage, timing) {
line.update.apply(this, arguments);
// Do your custom actions here
},
exit: function (self, storage, timing) {
line.exit.apply(this, arguments);
// Do your custom actions here
},
destroy: function (self, storage, timing) {
line.destroy.apply(this, arguments);
// Do your custom actions here
},
};
xChart.setVis('myvis', myVis);
Methods
function preUpdateScale(self, data, mainData, compData) {
mainData = accumulateData(mainData);
compData = accumulateData(compData);
}
function postUpdateScale(self, scaleData, mainData, compData) {
self.xScale2 = d3.scale.ordinal()
.domain(d3.range(0, mainData.length))
.rangeRoundBands([0, self.xScale.rangeBand()], 0.08);
}
function enter(self, storage, className, data, callbacks) {
// Create a basic SVG line, setting the x-values based on the xScale
var line = d3.svg.line()
.interpolate(self._options.interpolation),
container,
paths;
// Create a container for each series in the data set
// Notice how `className` is used here as a way to persist objects across updates
container = self._g.selectAll(selector + className)
.data(data, function (d) {
return d.className;
});
container.enter().insert('g', insertBefore)
.attr('data-index', zIndex)
.attr('class', function (d, i) {
var cl = _.uniq((className + d.className).split('.')).join(' ');
// Notice how we append both a vis-type class and the indexed color class to each
return cl + ' line color' + i;
});
// In each container, we create a line and apply the y-scale as necessary
paths = container.selectAll('path.line')
.data(function (d) { return [d.data]; });
paths.enter().append('path')
.attr('class', 'line')
.style('opacity', 0)
.attr('d', storage.line
.x(function (d) { return self.xScale(new Date(d.x)); })
.y(function (d) { return self.yScale(d.y); })
);
// We will want these later during the update method
storage.lineContainers = container;
storage.linePaths = paths;
storage.line = line;
}
function update(self, storage, timing) {
// Update each line
storage.linePaths.transition().duration(timing)
.style('opacity', 1)
.attr('d', storage.line
.x(function (d) { return self.xScale(new Date(d.x)); })
.y(function (d) { return self.yScale(d.y); })
);
}
function exit(self, storage, timing) {
storage.lineContainers.exit().transition().duration(timing)
.style('opacity', 0);
}
function destroy(self, storage, timing) {
storage.lineContainers.transition().duration(timing)
.style('opacity', 0)
.remove();
}