Récemment, pour un développement de dashboards, j’ai cherché une librairie pour générer des graphiques de façon simple et sexy. Après quelques recherches, mon choix s’est porté sur C3js.
Comme le stipule le titre, C3js est une librairie de graphiques pré-construits basée sur D3js. Nous avons donc les types de graphiques les plus courants, avec les possibiltés de D3js, mais ce n’est pas tout, C3js nous offre aussi la possibilité de mettre à jour les données en live avec de beaux effets. Si vous allez sur la page d’accueil, essayez d’utiliser le bouton “Start Demo” tout en haut de la page, il donne tout de suite un bon aperçu des possibilités.
Utilisant AngularJS, il me fallait des directives pour générer et manipuler les graphiques. Après quelques recherches sur le net, et ne trouvant pas exactement toutes les fonctionnalités que je recherchais avec cette configuration, il ne restait plus qu’à en élaborer des nouvelles.
Aujourd’hui je vous propose donc d’explorer un peu les possibilités que nous offre C3js, ainsi que quelques exemples utilisant les directives résultantes de ce développement.
Alors, nous avons des graphiques D3js de type “line”, “spline”, “step”, “area”, “bar”, “scatter plot”, “pie”, “donut” et “gauge” directement disponibles grâce à C3js.
Nous avons aussi des exemples de graphiques sur cette page, qui est assez fournie. Le code de chaque exemple est éditable en live, ce qui est très pratique pour faire des essais.
L’API se décompose en plusieurs sections:
Je trouve cette documentation bien détaillée, et les multiples exemples aident beaucoup à la compréhension.
Pour suivre au maximum l’API proposée par C3js, j’ai fait le choix de créer une directive par section de l’API. La directive de base se nomme szC3Chart
et comprend les parties “Chart” et “Data”.
Pour définir un graphique, il faut au minimum le déclarer comme suit:
<sz-c3-chart bindto="mon-graphique"></sz-c3-chart>
Pour lui passer des données, j’ai défini les types columns
, rows
ou json
. Il faut donc formater les données correctement et les passer par le bon attribut à la directive. Disons que nous avons une variable columns
dans le scope
, avec le format columns
attendu par C3js:
$scope.columns: [
['data1', 30, 20, 50, 40, 60, 50],
['data2', 200, 130, 90, 240, 130, 220],
['data3', 300, 200, 160, 400, 250, 250]
];
il est alors possible de la passer à la directive par l’attribut columns
:
<sz-c3-chart bindto="chart-id"
columns="columns">
</sz-c3-chart>
L’attribut type
permet de définir le type global du graphique (on peut aussi définir un type par courbe, c’est un peu plus loin):
<sz-c3-chart bindto="chart-id"
type="pie"
columns="columns">
</sz-c3-chart>
Pour ajuster les dimensions du graphique, les attributs size
et padding
donnent accès aux options C3js du même nom:
<sz-c3-chart bindto="chart-id"
size="{ width: 600 }"
padding="{ bottom: 12 }"
type="pie"
columns="columns">
</sz-c3-chart>
Pour chacune des autres sections de l’API de C3js, une directive correspondante est disponible. Par exemple pour changer la position de la légende:
<sz-c3-chart bindto="chart-id"
size="{ width: 600 }"
padding="{ bottom: 12 }"
type="pie"
columns="columns">
<legend position="right"></legend>
</sz-c3-chart>
Et ainsi de suite.
J’ai par contre redéfini au niveau de la directive szC3Chart
, une partie de l’API proposée par C3js qui permet de donner les options de chaque courbe. Au lieu de passer les attributs names
, types
et colors
séparément, vous pouvez définir un tableau contenant ces options:
$scope.curvesOptions = [
{ id: 'data1', type: 'bar', name: "Données numéro 1", color: '#D62728' },
{ id: 'data2', type: 'bar', name: "Données numéro 2", color: '#FF7F0E' },
{ id: 'data3', type: 'line', name: "Données numéro 3", color: '#1F77B4' }
];
et le passer à la directive par l’attribut curvesOptions
:
<sz-c3-chart bindto="chart-id"
size="{ width: 600 }"
padding="{ bottom: 12 }"
columns="columns"
curves-options="curvesOptions">
<legend position="right"></legend>
</sz-c3-chart>
Notez que dans le cas de données de type JSON, il faudra au minimum passer les id
des courbes devant être tracées à curvesOptions
.
Pour mettre à jour les données du graphique avec un bel effet de transition, il faut envoyer un évènement ReloadData
avec les nouvelles données en paramètre, à partir d’un contrôleur englobant la directive:
$scope.$broadcast('ReloadData', {
columns: [
['data1', 22, 23, 36, 33, 42, 55],
['data2', 133, 140, 122, 210, 60, 327],
['data3', 355, 210, 188, 304, 281, 213]
]
});
Il est aussi possible de mettre à jour dynamiquement l’axe des abscisses, en envoyant un évènement ChangeRange
avec les nouvelles valeurs minimum et maximum que le graphique doit afficher.
Je n’ai pas implémenté toute l’API proposée par C3js, mais en consultant les parties relatives aux scopes de chaque directive, vous aurez leur API actuelle. Par exemple pour la directive de base:
scope: {
// chart
bindto: '@',
size: '=',
padding: '=',
colorPattern: '=',
// data
x: '@',
order: '@',
labels: '@',
type: '@',
axes: '=',
colors: '=',
groups: '=',
json: '=',
rows: '=',
columns: '=',
curvesOptions: '=',
color: '&'
}
Voyons ce que donne le premier graphique de type “pie”, juste avant l’exemple avec les options:
.controller('PieController', ['$scope', function($scope) {
$scope.columns: [
['data1', 30, 20, 50, 40, 60, 50],
['data2', 200, 130, 90, 240, 130, 220],
['data3', 300, 200, 160, 400, 250, 250]
];
}]);
<div ng-controller="PieController">
<sz-c3-chart bindto="chart-id"
type="pie"
size="{ width: 600 }"
padding="{ bottom: 12 }"
columns="columns">
<legend position="right"></legend>
</sz-c3-chart>
</div>
Voyons maintenant celui avec les 2 courbes de type “bar” et une de type “line”, ainsi que la mise à jour des données:
See the Pen C3js bar and line chart with live update by Numa Claudel (@Claun) on CodePen.
Un troisième avec cette fois-ci une plage de temps sur l’axe des abscisses, avec mise à jour de la plage affichée:
See the Pen C3js line timeseries chart with axis move by Numa Claudel (@Claun) on CodePen.
L’attribut x
sert à définir quelles données sont représentées par l’axe des abscisses, ici les dates. Dans le cas de données de type JSON, il faut passer à l’attribut curvesOptions
une entrée de plus, contenant l’id
de l’axe, comme si c’était une courbe, et la value
(les données qu’il représente):
$scope.curvesOptions = [
{ id: 'x', value: 'x' }
];
Pour ma part je trouve que les graphiques proposés par C3js sont assez plaisants, qu’en pensez-vous ?
Pour ce qui est des directives que je vous propose, mon objectif était d’utiliser C3js au travers d’AngularJS, en conservant son API et en essayant d’avoir les meilleures performances possibles.
angular-c3js est disponible sur notre Github. N’ayant pas couvert toute l’API de C3js, sentez vous donc libre de forker le dépot pour adapter les directives à vos besoins.
L’équipe Synbioz.
Libres d’être ensemble.