billboard.js 3.9 release: arc.needle, dark theme 🌘 & more!

Jae Sung Park
6 min readJul 3, 2023


New 3.9 release 🥳 out today! This release comes with 7 new features and 3 bug fixes.

For the detailed release info, please checkout the release note:

What’s New?


Needle can be used to point certain point of data value, within arc shape.


The needle shape can be fully customized by your own(in this case it needs specify path value), or just simply update the length or top/bottom radii.

Checkout full option interface and its comments to understand each options.

[donut | gauge]: {
// when '' is set, will able to use template to reflect needle value
title: "{=NEEDLE_VALUE}"
arc: {
needle: {
show: true,
color: "red", // any valid CSS color

// for customized needle
path: function(length) {
const len = length - 20;

// will return upper arrow shape path
// Note: The path should begun from '0,0' coordinate to top center.
const path = `M 0 -${len + 20}
L -12 -${len}
L -5 -${len}
L -5 0
A 1 1 0 0 0 5 0
L 5 -${len}
L 12 -${len} Z`;

return path;

value: 40, // will make needle to point value 40.
length: 80, // needle length in percentages relative to radius.

top: {
// rx and ry are the two radii of the ellipse;
rx: 1,
ry: 1,
width: 5

bottom: {
// rx and ry are the two radii of the ellipse;
rx: 1,
ry: 1,
width: 10
len: 10

The first donut chart uses customized needle and initial value specified. In this case, when some dataseries is hidden, the needle will updating to point given value.

And the second chart, initialized with 0 value, and the needle value is updated dynamically.

To update needle value dynamically, it provides simple API method to update current needle value by chart.$.needle.updateHelper().

// Update arc needle position
const chart = bb.generate({
data: {
type: "donut"
arc: {
needle: {
show: true,

chart.$.needle.updateHelper(70); // update needle position to point value 70.

// update needle position to point value 70 and the config value.
// NOTE: updating config value, will update needle pointer initial value too.
chart.$.needle.updateHelper(70, true);

// update needle point position every 1 second
let i = 0;
setInterval(() => {
chart.$.needle.updateHelper(i += 10);
}, 1000)

Dark theme

Dark mode are quite common these days, and to facilitate will provide dark theme from this release.

Of course as other themes, it can be used as a starter to apply your own styles based on dark theme.

dark theme will be distributed as single css file and see in action from the example page by selecting it from the left side navigation “Theme” section.


point.sensitivity option will let customize the distance(from data point’s x/y coordinate)to be interacted.


When sensitivity value is 3, it means the interaction will happen when mouse pointer enters 3px boundaries starting from exact x/y coordinate.

But for bubble type, specifying absolute value can’t make to interact smoothly, because each bubble radius will vary on its value.

To improve this, will provide radius option, to reflect the sensitivity depend on each bubble radius. And also, provides callback option which can add some conditional to control it in more detail way.

point: {
// having lower value, means how closer to be for interaction
sensitivity: 3,

// sensitivity based on point's radius
sensitivity: "radius",

// callback for each point to determine the sensitivity
sensitivity: function(d) {
// ex. of argument d:
// ==> {x: 2, value: 55, id: 'data3', index: 2, r: 19.820624179302296}

// returning d.r, will make sensitivity same as point's radius value.
return d.r;

The below example, illustrate when sensitivity value is specified as absolute value and when is specified radius value.


Another enhancement option to control the position of data label text.


Just simply return corresponding x/y coordinate value for each data text element as you want.

data: {
labels: {
show: true,
* The arguments are:
* - `type` coordinate type string, which will be 'x' or 'y'.
* - `v` is the value of the data point where the label is shown.
* - `id` is the id of the data where the label is shown.
* - `i` is the index of the data series point where the label is shown.
* - `texts` is the array of whole corresponding data series' text labels.
position: function(type, v, id, i, texts) {
let pos = 0;
const len = texts.size() / 2 - 1;

if (type === "x" && (i === 0 || i === len)) {
pos = i === 0 ? 20 : -20;

return pos;


When various shape types with bar type are used in single chart, usually bar shapes are positioned in behind of other shapes elements to not make overlap and interrupt the visibility.

Controlling z-order is not easy in “svg world”, because the z-order will be following relative of DOM tree structure.

The only way to control this, it needs control DOM tree structure which is not an easy task.


Enabling this option, will simply make bar shapes to appear at the front of other shapes elements.

bar: {
front: true

Easily can notice the differences from below example.


By default, legend items will have toggle and over/out interaction. But sometimes there’re needs to disable it.

From this release, will provide new options to control it.


Will provide 2 way to control:

  • Enable or disable the default legend interaction
  • Provide a “double click” interaction, which in this case, double clicking will make focusing clicked dataseries and hiding others.
legend: {
item: {
// will disable default interaction (mouse hover effect and click to hide clicked dataseries)
interaction: false | {
* Set legend item to interact on double click.
* - **NOTE:**
* - Double clicking will make focused clicked dataseries only, hiding all others.
* - for single click case, `click + altKey(Win)/optionKey(Mac OS)` to have same effect.
* - To return initial state(which all dataseries are showing), double click current focused legend item again.
* - for single click case, `click + altKey(Win)/optionKey(Mac OS)` to have same effect.
* - In this case, default `click` interaction will be disabled.
dblclick: true

// when set below callback option value, will work regardless of 'interaction=false' is set
onclick: function(id) { ... },
onover: function(id) { ... },
onout: function(id) { ... }

See in action when dblclick option is enabled. “Double clicking” legend item, will make appearing clicked dataseries only and hiding the others.

To return initial states, double click focused legend item again.


The number of downloads are continuously growing, and it reached 100k downloads per month!

This proves competitiveness among other options, and this is somehow delightful 😆 to see more more developers around the worlds are choosing billboard.js for the data visualization.

We’ll continuously making improvements from your supports!