ChartJS widget
The ChartJS widget renders a chart by leveraging the open-source library chartjs.org (opens in a new tab).
Test in Kitchen Sink (opens in a new tab)
To modify an existing chart's data points, whether appending or replacing data, you need to use the chart methods. Binding the chart to storage or an API response only renders the chart once. Subsequent rendering of chart data happens through update method. See below for examples.
Basic example
The primary property required for ChartJs widget requires is config
.
View:
body:
Column:
children:
- ChartJs:
onTap:
eexecuteCode:
body: |
console.log(event.data);
config: |
{
"type": "pie",
"data": {
"labels": ["Red", "Blue", "Yellow"],
"datasets": [{
"data": [300, 50, 100],
"backgroundColor": [
"rgb(255, 99, 132)",
"rgb(54, 162, 235)",
"rgb(255, 205, 86)"
]
}]
}
}
Prompt ChatGPT to generate this configuration. E.g. What is the json configuration for pie chart using chartjs?
Replace chart's data with new data
You can change the entire data of a chart using setData
method:
- Add an id to your chart widget.
- Use
setData
replace data. - Use
update
to redraw the chart.
View:
body:
Column:
styles:
padding: 100 0
gap: 16
crossAxis: center
children:
- Text:
text: Energy Sources
styles:
textStyle:
fontSize: 20
- ToggleButton:
styles:
spacing: 10
runSpacing: 10
color: black
selectedColor: white
backgroundColor: white
selectedBackgroundColor: green
selectedBorderColor: blue
borderColor: green
items:
- Your home
- Others
value: "Your home"
onChange: |
if (this.value == "Your home") {
energySourceChart.setData(0, [60,10,20,10]);
energySourceChart.update();
centerText.text = "60%";
} else {
energySourceChart.setData(0, [20,40,50,20]);
energySourceChart.update();
centerText.text = "10%";
}
- Stack:
styles:
alignChildren: center
children:
- ChartJs:
styles:
width: ${ device.width }
height: ${ device.width }
id: energySourceChart
config: ${ setEnergyChartConfig([60,10,20,10])}
- Column:
styles: { crossAxis: center, mainAxis: center }
children:
- Text:
text: Green energy
styles:
textStyle:
color: 0xff969BA1
fontSize: 12
- Text:
id: centerText
text: 60%
styles:
textStyle:
fontSize: 32
textAlign: end
Global: |-
function setEnergyChartConfig (data) {
return ({
"type": 'doughnut',
"data": {
"labels": ["Green", "Coal", "Gas", "Oil"],
"datasets": [{
"data": data,
"backgroundColor": ['#4BC22F','#474747','#FFBE0A', '#6933FF'],
"hoverOffset": 30,
"borderWidth": 0
}]
},
"options": {
"responsive" : true,
"aspectRatio": 1,
"cutout": 80 ,
"plugins": {
"legend": {
"display": false
},
"tooltip": {
"enabled": true,
"position": "nearest"
},
"labelInsideCircumference": {
"font": {
"size": '11',
"weight": 'normal'
},
"color": '#000',
"space": 40, // Space between label and circumference
"labelPadding": 10, // Padding on the left and right of the label inside the box
"boxHeight": 30, // Height of the label box
"borderRadius": 4, // Border radius for the label box
"iconOffset": 15 // Horizontal offset for the icon inside the box,
}
},
"layout": {
"padding": 80
}
},
"plugins": [{
"id": 'labelInsideCircumference',
"beforeDraw": function (chart) {
var labels = chart.data.datasets[0].data;
var colors = chart.data.datasets[0].backgroundColor;
var ctx = chart.ctx;
var width = chart.width;
var height = chart.height;
var labelConfig = chart.options.plugins.labelInsideCircumference;
ctx.restore();
ctx.font = labelConfig.font.size + 'px ' + labelConfig.font.weight;
ctx.fillStyle = labelConfig.color;
ctx.textBaseline = 'middle';
var total = chart.config.data.datasets[0].data.reduce(function (acc, val) {
return acc + val;
}, 0);
var startAngle = -0.54 * Math.PI;
var endAngle = startAngle;
// unicodes for the icons
var iconUnicodes = ['🍃', '🪨', '🔥', '🛢️'];
var text = ["Green", "Coal", "Gas", "Oil"];
for (var i = 0; i < labels.length; i++) {
var angle = (chart.data.datasets[0].data[i] / total) * (2 * Math.PI);
endAngle += angle;
var x = width / 2 + Math.cos((startAngle + endAngle) / 2) * (width / 2 - labelConfig.space);
var y = height / 2 + Math.sin((startAngle + endAngle) / 2) * (height / 2 - labelConfig.space);
var label = text[i] + " " + labels[i].toString() +"%";
var labelWidth = ctx.measureText(label).width;
var icon = iconUnicodes[i];
var iconWidth = ctx.measureText(icon).width;
var contentWidth = labelWidth + iconWidth + labelConfig.labelPadding * 2; // Icon width + label width + padding
var boxWidth = Math.max(contentWidth, 70); // Ensure a minimum box width
var boxHeight = labelConfig.boxHeight;
var borderRadius = labelConfig.borderRadius;
// Set label color to match area color
ctx.fillStyle = colors[i];
// Calculate box position
var boxX = x - boxWidth / 2;
var boxY = y - boxHeight / 2;
// Draw label box
ctx.beginPath();
ctx.moveTo(boxX + borderRadius, boxY);
ctx.lineTo(boxX + boxWidth - borderRadius, boxY);
ctx.quadraticCurveTo(boxX + boxWidth, boxY, boxX + boxWidth, boxY + borderRadius);
ctx.lineTo(boxX + boxWidth, boxY + boxHeight - borderRadius);
ctx.quadraticCurveTo(boxX + boxWidth, boxY + boxHeight, boxX + boxWidth - borderRadius, boxY + boxHeight);
ctx.lineTo(boxX + borderRadius, boxY + boxHeight);
ctx.quadraticCurveTo(boxX, boxY + boxHeight, boxX, boxY + boxHeight - borderRadius);
ctx.lineTo(boxX, boxY + borderRadius);
ctx.quadraticCurveTo(boxX, boxY, boxX + borderRadius, boxY);
ctx.closePath();
ctx.fillStyle = '#fff';
ctx.strokeStyle = "#fff";
ctx.lineWidth = 1;
ctx.fill();
ctx.stroke();
// Draw icon
ctx.font = '13px';
ctx.fillStyle = '#9DAEC1';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(icon, x - (labelWidth + labelConfig.labelPadding) / 3, y);
// Draw label text
ctx.font = '15px';
ctx.fillStyle = "black";
ctx.fillText(label, x + (iconWidth + labelConfig.labelPadding) / 2, y);
ctx.canvas.style.zIndex = 100;
startAngle = endAngle;
}
ctx.save();
}
}]
});
}
Update chart with new data points
You can append new data points to an existing chart:
- Add an id to your chart widget.
- Use
addLabels
andaddData
to add new data points. - Use
update
to redraw the chart.
View:
body:
Column:
styles:
gap: 16
padding: 24
children:
- Button:
label: Add Data
onTap:
executeCode:
body: |
testLineChart.addLabels(['July','August','September']);
testLineChart.addData(0,[20,30,40]);
testLineChart.addData(1,[5,45,25]);
testLineChart.update();
- ChartJs:
id: testLineChart
styles:
width: ${device.width}
config: |
{
type: 'line',
data: {
labels: [
'January',
'February',
'March',
'April',
'May',
'June'
],
datasets: [
{
label: 'My First dataset',
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1,
data: [0, 10, 5, 2, 20, 45],
fill: 'start'
},{
label: 'My Second dataset',
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1,
data: [5, 12, 7, 0, 18, 25],
fill: 'start'
}
]
},
options: {
scales: {
x: {
ticks: {
maxRotation: 0,
minRotation: 0
}
}
},
plugins: {
filler: {
propagate: false,
}
},
interaction: {
intersect: false,
},
tension: 0.4
}
}
Properties
Property | Type | Description |
---|---|---|
id | string | Assign an id to the chart so that you can run its methods |
config | object | Chart's configuration that conforms to chartjs.org (opens in a new tab) specification |
onTap | action | Triggers Ensemble's built-in functions or custom code execution on chart interaction, with access to data at the tap point via event.data based on chart type. |
Styles
Property | Type | Description |
---|---|---|
width | integer | The width property determines the horizontal size of an element, allowing control over its width dimension within the layout. |
height | integer | The height property determines the vertical size of an element, allowing control over its height dimension within the layout. |
Methods
setData
This method replaces the data of the chart. Existing data are removed. You must call the update
method after using setData
to re-render the chart.
If you intend to append data, use addData
and addLabels
method.
Parameters:
- datasetIndex (integer): The index of the dataset to which the data should be added.
- data (array): An array of data points to add to the chart.
Example:
myChart.setData(0, [60, 10, 20, 10]);
addLabels
This method appends labels to the x-axis of the chart.
Parameters:
- labels (array): An array of strings representing the labels for the chart.
Example:
myChart.addLabels(["January", "February", "March"]);
addData
This method appends data to an existing dataset.
Parameters:
- datasetIndex (integer): The index of the dataset to which the data should be added.
- data (array): An array of data points to add to the chart.
Example:
myChart.addData(0, [10, 20, 30]);
update
This method updates the chart to reflect any changes in data, labels, or configurations.
Example:
myChart.update();