Introducing Britecharts: Eventbrite’s Reusable Charting Library Based on D3

The usual workflow when developing interactive data visualizations with D3.js is based on the significant number of examples that the D3 community provides. They are broad and useful, but they are still not ideal. Most of the time, they require a lot of effort to integrate into your code and to make them production-ready.

In a previous series of posts about Leveling Up D3, I talked about a different way of building D3.js charts, using the Reusable API, building our components via TDD and improving them with events and refactorings. Following those ideas, and with the help of Eventbrite’s design team, we have been working on our chart library, and now we want to share it with you. It’s called Britecharts.

What is Britecharts?

Britecharts is a client-side reusable Charting Library based on D3.js v4 that allows an easy and intuitive use of charts and components that can be composed, creating beautiful visualizations.

The idea behind Britecharts is twofold: first, we want to allow developers and designers with little experience with D3.js to build great interactive charts with little initial effort. Second, we want to propose a framework for helping D3.js developers to create new D3.js charts by following standards like the Reusable API and Test Driven Development.

What problem does Britecharts solve?

The project is just an implementation of the Reusable Chart API. As such, it solves the problems of regular D3.js charts, namely, lack of modularity, high complexity, low re-usability and poor testability.

We also wanted to accomplish this with an eye for aesthetics so that anybody could have a beautiful chart working out of the box. Our project also offers the set-up necessary to create charts on a TDD basis as well as a playground for polishing and manually testing them.

Rendering your first BriteChart

For installing the library, you can use NPM or Bower to install the individual JavaScript files and CSS stylesheets (we are getting ready a bundled version to be downloaded via CDN). Here we see an example using NPM:

npm install britecharts
npm install d3

Then, you will load the dependencies this way on your ES2015 project:

import * as d3 from 'd3';
import bar from 'britecharts/dist/umd/bar.min.js';

Next up we will create your first chart. We will start with the data definition. Here, we have a piece of data:

const data = [
        {
            "name": "Radiating",
            "value": 0.08167
        },
        {
            "name": "Opalescent",
            "value": 0.0492
        },
        {
            "name": "Shining",
            "value": 0.02782
        },
        {
            "name": "Vibrant",
            "value": 0.04253
        },
        {
            "name": "Vivid",
            "value": 0.02702
        },
        {
            "name": "Brilliant",
            "value": 0.02288
        }
    ];

This data is the result of an imaginary poll we made around our team at Eventbrite. As it is category data, we will use a horizontal bar chart to represent it.

Once we choose the chart type, we want to check out the required data entries for it. We do this by navigating to the global section of the docs and searching for the bar chart. Here, we see that the right data format should be:

[
    {
        value: 1,
        name: 'glittering'
    },
    {
        value: 1,
        name: 'luminous'
    }
]

Our original data format is pretty much the same, so we won’t need to transform the data. To plug our chart inside a container div that we previously created on our HTML, we will need to type:

let barChart = new bar();
let barContainer = d3.select(‘.js-container’);
let containerWidth = barContainer.node() ? barContainer.node().getBoundingClientRect().width : false;

barChart
   .margin({
        left: 120,
        right: 20,
        top: 20,
        bottom: 5
    })
   .horizontal(true)
   .usePercentage(true)
   .percentageAxisToMaxRatio(1.3)
   .width(containerWidth)
   .height(300);

barContainer.datum(data).call(barChart);

And using a template that includes Britecharts styles and the chart container:

<head>
    [...]
    <link rel="stylesheet" href="node_modules/britecharts/dist/css/britecharts.min.css">
</head>
<body>
    <div class="js-container"></div>
</body>

the previous code will render:

Every chart has a series of properties that are public, in this case: horizontal, width, valueLabel and height. You can find them on each chart’s API menu on the docs homepage. Here is the Bar Chart API.

Responsive Charts

Once we have our data visualization rendering, we usually want to make our charts responsive. In order to achieve this, we will first set up a listener to the ‘window.resize’ event and trigger a redraw when that happens.

const redrawCharts = () => {
    let barContainer = d3.select(‘.js-container’);
    let newContainerWidth = barContainer.node() ? barContainer.node().getBoundingClientRect().width : false;
    
    // Setting the new width on the chart
    barChart.width(newContainerWidth);

    // Rendering the chart again
    barContainer.datum(data).call(barChart);
};
const throttledRedraw =  _.throttle(redrawCharts, 200);  

window.addEventListener("resize", throttledRedraw);

It is also useful to throttle that event so that we don’t redraw our chart a considerable number of times, as this event triggers many times with every resize event. For this, we will use a util library like underscore or lodash.

Advanced Settings

Now that we have a responsive chart, we will use other components to add more functionality. In this case, we will add a tooltip to our chart.

The bar chart and other Britecharts have some mouse events attached to their elements and exposed through custom named events. This way, when we hover with our mouse (or tap on mobile devices), a custom event will be triggered. We can easily hook up a handler function, whose code will look like this:

...
import miniTooltip from 'britecharts/dist/umd/mini-tooltip.min.js';

let tooltip = new miniTooltip();
let barChart = new bar();
let barContainer = d3.select('.js-bar-chart-container');
let containerWidth = barContainer.node() ? barContainer.node().getBoundingClientRect().width : false;

barChart
    .margin({
        left: 120,
        right: 20,
        top: 20,
        bottom: 5
    })
    .horizontal(true)
    .usePercentage(true)
    .percentageAxisToMaxRatio(1.3)
    .width(containerWidth)
    .height(300)
    .on('customMouseOver', tooltip.show)
    .on('customMouseMove', tooltip.update)
    .on('customMouseOut', tooltip.hide);

let tooltipContainer = d3.select('.bar-chart .metadata-group');
tooltipContainer.datum([]).call(miniTooltip);

And that’s it! The tooltip is working!

Styling

Depending on the number of charts you will use, you could either load the whole bundle of styles or load the styles of different charts plus the common styles. The bundled configurations and split charts and styles can be found in the dist/ folder.

We can add additional styles to our chart in different ways. Britecharts provides some color palettes that you can use for the bars, and you can also style the SVG elements with CSS, either overriding the original styles or by simply starting again from scratch.

Let’s see an example:

import colors from 'britecharts/dist/umd/colors.min.js';

[...]
barChart.colorSchema(colors.colorSchemas.extendedOrangeColorSchema);
[...]
barContainer.datum(data).call(barChart);

Will render an orange themed bar chart:

Remember that you could also create animations for the SVG paths, using dashed lines or making them move, grow or anything else that you can think of! Read more in this great article by Sara Soueidan

When Britecharts is not for you

We have tried to achieve a healthy balance between ease of use for both nontechnical people and D3.js specialists alike. Still, if you are going to need just one chart to customize deeply and never use again, maybe the example-based approach will work better for you.

Looking ahead

We are super excited about the launch of Britecharts and want to hear your opinions on it!
Any feedback about the documentation, complexity, customization options and ease of use are highly appreciated.

With Britecharts, we hope to help newcomers to the D3 community to structure their charts and test them efficiently. Our goal is for it to become a library of high-quality, tested data visualizations.

Resources

Contributing

If you are excited about Britecharts, want to add more configurable properties or even create your own chart, please check our Contributing Guide. In it, we walk you through the development environment setup, run our docs and demos and create new Pull Requests.

9 Replies to “Introducing Britecharts: Eventbrite’s Reusable Charting Library Based on D3”

  1. How does this differ from, say, Plottable (https://github.com/palantir/plottable) or C3 (https://github.com/c3js/c3) or any of the other charting libraries built on D3 that already exist?

    Not trying to diminish the work or anything but have you considered joining efforts with an existing project? One that fit your needs/requirements the closest? I realize there might not be a perfect match but I think the OSS community/ecosystem would’ve benefited more by you contributing your resources/efforts towards improving an existing project than starting a new one.

    1. Hi Adam, thanks for taking the time to give us feedback!
      What you comment about contributing to other OSS projects it’s a good point, and in theory, makes the most sense. When we get into the context, it gets tricky.

      Britecharts got started circa May 2015 as a way of abstracting away some D3 code, and provide charts with very particular feature and design requirements. Under the influence of two books (Developing a d3.js Edge and Mastering D3), we also wanted something that was tested and running in a CI environment. I did some research and didn’t found anything that covered those requirements, so I we had to roll our own.

      Regarding Plottable, it got a lot nicer, at the time didn’t have that many charts, so I didn’t dive deeper on it. I would reject it though, as it has an API that is really far from D3.

      On C3, they did a great job, it was on my research back then. The interface was again far from D3, being much more declarative, similar to Highcharts.

      Another one would be NVD3, that was on my radar too. Their API is more like D3, and we think a lot less accessible for non-d3 developers or designers. Comparing it with Britecharts, our library is more opinionated on the ‘looks’.

      API-wise, I see them more or less like this:
      D3 —NVD3——Britecharts———Plottable—OOP———C3— Declarative

      This illustrates one of the reasons why I think developers could prefer Britecharts; it could become a stepping stone towards start using D3.

      Using Britecharts, a junior developer could render a chart quickly, just doing d3 selections. Then, she can start tinkering with one of the charts and even create a new one, learning d3.js in the process.

  2. Thanks for your work. What I’m concerning with is, can britecharts easily realize all examples on the D3 website other than the several simple ones you provide?

    1. Hi Scarlett, thanks for your comment!

      Oh, no, Britecharts is not as powerful as D3!
      The point of Britecharts is to help users create Britecharts charts, that internally use D3.js, without having to deal with the powerful but complex D3.js API.
      It is true though that if your D3 level allows it, you could create any D3.js chart following the code structure and tests of Britecharts.

  3. Is there documentation in browser-readable JavaScript? I am trying to use the CDN to link to BriteCharts in my js code but it seems like the documentation is written from the standpoint that I should be developing in a Node environment. Also it assumes that I am using Babel to transpile the code. Is that correct? And is there documentation/demos that tells me how to build a chart from browser-readable JavaScript like HighCharts does? Thanks.

  4. What would you consider best practice to customize the colors by name? While this code `.colorSchema(britecharts.colors.colorSchemas.britecharts)` provides an overall schema, what is the best way to control the colors individually?

Leave a Reply

Your email address will not be published. Required fields are marked *