Chart.js Treemap Custom text - javascript

In my code below, I am able to draw a Treemap and also display the tag in each tree cell. But I want to add some custom text next to my tag,
Like say I want the word 'Language' to appear in each tree map cell. I tried the formatter options, But its not working for the version of chart.js I am using. Kindly provide me a solution for the specific version I am using. Since I have multiple other charts defined and changing the version would cause issues.
var topTags = [
{tag:'android',num:42657},{tag:'reactjs',num:38844},{tag:'php',num:34381},{tag:'sql',num:29996},
];
var canvas = document.getElementById("treemap");
var ctx = canvas.getContext("2d");
var chart = window.chart = new Chart(ctx, {
type: "treemap",
data: {
datasets: [{
tree: topTags,
key: "num",
groups: ['tag'],
spacing: 0.5,
borderWidth: 1.5,
fontColor: "black",
borderColor: "grey"
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
tooltips: { enabled: false }
}
});
CHART.JS AND TREEMAP VERSION :
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-chart-treemap#0.2.3"></script>

The formatter option only got added in version 2 of the treemap chart type, the scriptable option is only available in version 1 so the best way for you to get the extra text is by editing your original data array first and adding the text to it that way like so:
let topTags = [{
tag: 'android',
num: 42657
}, {
tag: 'reactjs',
num: 38844
}, {
tag: 'php',
num: 34381
}, {
tag: 'sql',
num: 29996
}, ];
topTags = topTags.map(e => ({
num: e.num,
tag: `Lang: ${e.tag}`
}))
const canvas = document.getElementById("chart");
const ctx = canvas.getContext("2d");
const chart = window.chart = new Chart(ctx, {
type: "treemap",
data: {
datasets: [{
tree: topTags,
key: "num",
groups: ['tag'],
spacing: 0.5,
borderWidth: 1.5,
fontColor: "black",
borderColor: "grey",
}]
},
options: {
maintainAspectRatio: false,
legend: {
display: false
},
tooltips: {
enabled: false
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-chart-treemap#0.2.3"></script>
<canvas id="chart"></canvas>

Related

Styling problems with Chart.Js

How can I add these styles to my graph? I'm having trouble finding it in the documentation for it, and the other forums aren't very helpful. I am using Flask for the backend, so that's why the data values look like that.
Labels on top of bars
Change font size on both axis
Set y scale as a fixed value (0,8)
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var options = {
scales: {
yAxes: [{
ticks: {
fontSize: 40
}
}]
}
}
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Lithium Battery', 'Other Mfg', 'Delivery', 'Tailpipe', 'Fuel Cycle', 'Disposal', 'Total'],
datasets: [{
label: 'ICEV CAR (MTCO2e/Year)',
labels: [
"{{data['battery_icev_car']}}",
"{{data['other_mfg_icev_car']}}",
"{{data['delivery_icev_car']}}",
"{{data['tailpipe_icev_car']}}",
"{{data['fuel_cycle_icev_car']}}",
"{{data['disposal_icev_car']}}",
"{{data['total_icev_car']}}"
],
data: [ /* errors are normal, fixes when server ru
[0, {{data['y1_icev']}}],
[{{data['y1_icev']}}, {{data['y2_icev']}}],
[{{data['y2_icev']}}, {{data['y3_icev']}}],
[{{data['y3_icev']}}, {{data['y4_icev']}}],
[{{data['y4_icev']}}, {{data['y5_icev']}}],
[{{data['y5_icev']}}, {{data['y6_icev']}}],
[0, {{data['y6_icev']}}]
],
backgroundColor: [
'rgba(0,0,0,0.9)'
],
borderColor: [
'rgba(0,0,0,1)'
],
borderWidth: 1,
borderSkipped: false
}]
},
options: {
responsive: true,
plugins: {
legend: {
labels: {
// This doesn't work on axis
font: {
size: 20
}
}
}
},
y: {
beginAtZero: true
}
}
});
</script> </script>
Since your config is not working I assume you are using V3, in which case the solution is as followed:
For point one you need to use an external plugin, you can write your own or use the datalabels plugin
For your second problem you need to style it as a font object as told in the documentation like so:
options: {
scales: {
y:{
ticks:{
font:{
size: 50
}
}
}
}
}
For your last part you can set the stepSize to 0.8

Chart.js - change which data the legend uses for the coloured box

I have a bar chart that always shows 4 bars. The bars are coloured dynamically. It looks like the coloured box takes its colour from the first data. I would like to use the colour from the 4th (last) data value. Maybe the options:plugins:legend:label:sort function helps but I don't understand what it does.
options
const options = {
scales: {
x: {
grid: {
display: false,
color: 'rgba(0,0,0)'
}
},
y: {
display: false,
min: 0,
max: 4
},
},
plugins: {
legend: {
position: 'bottom'
}
}
}
So I don't know if I can change the data that the box color comes from, or if there is a config option somewhere where I can change it manually.
You can use the generateLabels function as described here.
Please take a look at below runnable sample code and see how it works.
new Chart('myChart', {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow'],
datasets: [{
label: 'My Dataset',
data: [300, 50, 100],
backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56']
}]
},
options: {
responsive: false,
plugins: {
legend: {
labels: {
generateLabels: chart => {
let ds = chart.data.datasets[0];
let color = ds.backgroundColor[ds.backgroundColor.length - 1];
return [{
datasetIndex: 0,
text: ds.label,
fillStyle: color,
strokeStyle: color
}];
}
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<canvas id="myChart" height="180"></canvas>
Following up with #uminder's answer, if you want to keep the hide/show chart and the line-through style after clicking on the legend, you can add the following line:
options: {
responsive: false,
plugins: {
legend: {
labels: {
generateLabels: chart => {
let ds = chart.data.datasets[0];
let color = ds.backgroundColor[ds.backgroundColor.length - 1];
return [{
datasetIndex: 0,
text: ds.label,
fillStyle: color,
strokeStyle: color,
+ hidden: !chart.isDatasetVisible(0)
}];
}
}
}
}
}

How to change font weight of footer in tooltips in Chart JS

I am trying to change the font weight of footer in tooltips in Chart JS. According to this link (https://www.chartjs.org/docs/latest/configuration/tooltip.html#tooltip-configuration), footerFont seems to be the one to control this but I could not quite get it to work
My code:
options: {
tooltips:{
footerFont: {weight: 'normal'},
callbacks: {
footer: function(tooltipItem, data) {
return 'some text'
}
}
},
}
Fiddle: https://jsfiddle.net/dqdqdq/yp47oL9t/10/ . The footer is still bold when we hover any bubbles.
You are looking at the documentation of chart.js version 3 which has some major changes from version 2, if you take the version 2 docs: https://www.chartjs.org/docs/2.7.1/configuration/tooltip.html you can see that the property is called a bit different and also just accepts a string
Working sample:
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bubble',
data: {
datasets: [{
label: 'Top',
data: [{
x: 110,
y: 0,
r: 10,
name: "Performance"
}],
backgroundColor: "rgba(153,255,51,0.6)"
},
{
label: 'Average',
data: [{
x: 75,
y: 0,
r: 10,
name: "Performance"
}],
backgroundColor: "rgba(153,155,51,0.6)"
},
]
},
pointDot: true,
options: {
tooltips: {
footerFontStyle: 'normal',
callbacks: {
footer: function(tooltipItem, data) {
return 'some text'
}
}
},
}
});
<canvas id="myChart"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#0.2.0/dist/chartjs-plugin-datalabels.min.js"></script>

Add HTML to label of bar chart - chart js

I am using the chart js to display a bar graph. It's working correctly on normal instances, but I am willing to change the color or a small portion of the label i.e, I want to include some HTML on the label of the bar chart. But, it isn't rendering the HTML instead it is showing plain HTML text.
If it is not possible, it's okay for me if there is another way to achieve this like, change the color of the price and keep the name as it is.
let $js_dom_array = ["43.28", "93.13"];
let $js_am_label_arr = ["<span>$0</span> None", "<span class='text-danger'>$23.63</span> Handicap Accessible"];
let ctx2 = document.getElementById("barChart").getContext("2d");
let chart = new Chart(ctx2, {
type: 'bar',
data: {
labels: $js_am_label_arr,
datasets: [{
label: 'Amenity Name',
data: $js_dom_array,
backgroundColor: 'rgba(26,179,148,0.5)',
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
legendCallback: function(chart) {
var text = [];
for (var i=0; i<chart.data.datasets.length; i++) {
console.log(chart.data.datasets[i]); // see what's inside the obj.
text.push(chart.data.datasets[i].label);
}
return text.join("");
},
tooltips: {
"enabled": false
},
scales: {
xAxes: [{
stacked: false,
beginAtZero: true,
ticks: {
stepSize: 1,
min: 0,
autoSkip: false,
callback: function(label, index, labels) {
if (/\s/.test(label)) {
return label.split(" ");
}else{
return label;
}
}
}
}]
},
animation: {
duration: 0,
onProgress: function() {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = Chart.helpers.fontString(16, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function(dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function(bar, index) {
if (dataset.data[index] > 0) {
let data = dataset.data[index];
ctx.fillText('$'+Math.round(data), bar._model.x, bar._model.y - 5);
}
});
});
}
},
}
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<canvas id="barChart" height="140"></canvas>
</div>
#Note: Here, you might see that the data in $js_am_label_arr is already an HTML element, but if there is something from where I could pass the array of the raw values and the convert in HTML than I could pass the raw value (without) as well.
Currently $js_am_label_arr is created as:
if($avg_amount < 0){
$text_color = 'text-danger';
$avg_amount_text = "<span class='text-danger'>$".abs($avg_amount)."</span>";
}else{
$text_color = '';
$avg_amount_text = "<span>$".abs($avg_amount)."</span>";
}
$am_label_arr[] = $avg_amount_text.' '.$fv['amenity_name'];
Update:
Expected Output
So if the value is negative for example in the above case, its -$23.63. In this case, I want the label to be ($23.63)[in color red] followed by the name Handicap Accessible. This can be seen at the result as well, text-danger classes is added to show that part in red color.
As you are open to any plugin so i suggest you to use HighCharts to achieve above case . In below demo code i have just passed the label value to categories in xAxis and done a little change to span tag . i.e : i have added inline css to span where you need to display color red .
Here is demo code :
var chart;
let $js_dom_array = [43.28, 93.13];
let $js_am_label_arr = ["<span>$0</span> None", "<span style='color:red'>$23.63</span> Handicap Accessible"];
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'chart_container', //under chart_container chart will display
defaultSeriesType: 'bar', //bar grapgh
backgroundColor: '#CCCCCC',
type: 'column' //to display in columns wise
},
plotOptions: {
bar: {
colorByPoint: true,
dataLabels: {
enabled: false
}
}
},
title: {
text: 'Something.... '
},
xAxis: {
categories: $js_am_label_arr, //for value in labels
},
series: [{
name: 'Amenity Name',
data: $js_dom_array //array value to plot data
}]
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/gantt/highcharts-gantt.js"></script>
<div id="chart_container"></div>
You can change the color when you hover the label, with the tooltips callback
Move your mouse over the bar
let $js_dom_array = [43.28, 93.13];
let $js_am_label_arr = ["$0", "$23.63"];
let ctx2 = document.getElementById("barChart").getContext("2d");
let chart = new Chart(ctx2, {
type: 'bar',
data: {
labels: $js_am_label_arr,
datasets: [{
backgroundColor: 'rgba(26,179,148,0.5)',
label: 'Amenity Name',
data: $js_dom_array,
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
tooltips: {
enable: true,
callbacks: {
labelTextColor: function(tooltipItem, chart) {
if(tooltipItem.index === 1)
return 'red';
}
}
},
scales: {
xAxes: [{
stacked: false,
beginAtZero: true,
ticks: {
stepSize: 1,
min: 0,
autoSkip: false,
fontColor: "red",
callback: function(label, index, labels) {
if (/\s/.test(label)) {
return label.split(" ");
}else{
return label;
}
}
}
}]
}
}
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<canvas id="barChart" height="140"></canvas>
</div>
As far as i know, its not possible to do what you want.
With the current version (v2.9.3) its not even possible to change the color for specifics X ticks labels, you can only change the color for every label with:
options: {
scales: {
yAxes: [{
ticks: {
fontColor: "red",
}
}],
xAxes: [{
ticks: {
fontColor: "red",
}
}]
}
}
There is a workaround with version v2.6.0 (as you tagged this version, i imagine you are using it) wich you can pass an array of colors to fontColor, like: fontColor: ["red","green"], but you need to change some code lines of chartjs and yet you cannot change just a specific part of the text of axis tick label as you want.
If you have interested in this solution, you can check it here Add possibility to change style for each of the ticks
But again, this solution is related to an older version of chartjs and i dont know what features you lose here.
Looks like it will be able to change the color for each ticks in version 3.0, but this version isnt released yet.
UPDATED
I done a simple example here with c3/d3 js. but it has some points:
It take a little time to show Labels updated when chart is rendered.
On changeTickLabel i did a harded code to check value and then append the text (like 'Handicap Accessible'). So here you will need to find logic that is better to you.
var chart = c3.generate({
onrendered: function () { changeTickLabel() },
data: {
columns: [
['data1', 43.28, 93.13]
],
type: 'bar',
},
axis: {
x : {
type: 'category',
categories: ["$0", "$23.63"],
tick: {
multiline:false,
culling: {
max: 1
},
},
},
}
});
function changeTickLabel(){
d3.selectAll('.c3-axis-x .tick tspan')
.each(function(d,i){
var self = d3.select(this);
var textValue = self.text();
if(textValue !== '$0'){
self.style("fill", "red");
self.append('tspan').style("fill", "black").text(' Handicap Accessible');
}
else {
self.append('tspan').text(' None');
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.20/c3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="chart"></div>

How to show bar labels in legend in Chart.js 2.1.6?

I'm creating charts using Chart.js and I want to show the labels for the bars in the legend, not the title of the dataset (there is only one), please see the below image as an example:
My current legend just looks like this:
I have looked through the docs but to no avail, I found them very confusing actually.
Here is my current code:
var chart_0 = new Chart($('#cp_chart_0'), {
type: 'bar'
, data: {
labels: ['Blue','Green','Yellow','Red','Purple','Orange']
, datasets: [{
label: 'Dataset 1'
, borderWidth: 0
, backgroundColor: ['#2C79C5','#7FA830','#7B57C3','#ED4D40','#EC802F','#1DC6D3']
, data: ['12','2','5','0','9','1']
}]
}
});
Thanks!
In one of the most recent releases of Chart.js 2.1.x, they added back this functionality. So go get the latest release first. Then insert the code below.
It is located under the options and legend. Here is how you use it:
options: {
legend: {
position: 'right'
}
}
Easiest way is to provide your data with multiple sets :
data: {
labels: ['total votes']
, datasets: [{
label: 'Blue'
, backgroundColor: ['#2C79C5']
, data: ['12']
},{
label: 'Green'
, backgroundColor: ['#7FA830']
, data: ['2']
},
...
]
}
But you can generate a custom labels using generateLabels - http://www.chartjs.org/docs/#chart-configuration-legend-configuration
Or even customise the whole legend, including formatting, with legendCallback - http://www.chartjs.org/docs/#chart-configuration-common-chart-configuration
This solution uses Chart.js version 3. You can pre-process your data using the Plugin Core API. The API offers different hooks that may be used for executing custom code.
I use the beforeInit hook to create individual datasets for each defined label/value pair. Note that the data of these new datasets are defined in point format (for instance [{ x: 1, y: 12 }]):
beforeInit: chart => {
let dataset = chart.config.data.datasets[0];
chart.config.data.datasets = chart.config.data.labels.map((l, i) => ({
label: l,
data: [{ x: i + 1, y: dataset.data[i] }],
backgroundColor: dataset.backgroundColor[i],
categoryPercentage: 1
}));
chart.config.data.labels = undefined;
}
Further you need to define a second x-axis that will contain the labels.
x1: {
offset: true,
gridLines: {
display: false
}
}
The labels on x1 need to be collected and defined programmatically each time the hidden state of a dataset changes. This can be done in the beforeLayout hook.
beforeLayout: chart => chart.options.scales.x1.labels = chart.config.data.datasets.filter((ds, i) => !chart.getDatasetMeta(i).hidden).map(ds => ds.label)
Please take a look at below runnable code and see how it works.
new Chart('chart', {
type: 'bar',
plugins: [{
beforeInit: chart => {
let dataset = chart.config.data.datasets[0];
chart.config.data.datasets = chart.config.data.labels.map((l, i) => ({
label: l,
data: [{ x: i + 1, y: dataset.data[i] }],
backgroundColor: dataset.backgroundColor[i],
categoryPercentage: 1
}));
chart.config.data.labels = undefined;
},
beforeLayout: chart => chart.options.scales.x1.labels = chart.config.data.datasets.filter((ds, i) => !chart.getDatasetMeta(i).hidden).map(ds => ds.label)
}],
data: {
labels: ['Blue', 'Green', 'Yellow', 'Red', 'Purple', 'Orange'],
datasets: [{
data: ['12', '2', '5', '0', '9', '1'],
backgroundColor: ['#2C79C5', '#7FA830', '#FFF200', '#ED4D40', '#800080', '#EC802F']
}]
},
options: {
interaction: {
intersect: true,
mode: 'nearest'
},
plugins: {
legend: {
position: 'right'
},
tooltip: {
callbacks: {
title: () => undefined
}
}
},
scales: {
y: {
beginAtZero: true
},
x: {
display: false
},
x1: {
offset: true,
gridLines: {
display: false
}
}
}
}
});
canvas {
max-width: 400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.2.0/chart.min.js"></script>
<canvas id="chart" height="120"></canvas>

Categories

Resources