I am trying to create a mixed chart using chart.js. I separated my data into three different array for the plotting purpose. The sample data:
labelData:
Ezion Led Light Bulb - Warm White 10.5w E27
Ezion Induction Cooker Ez822
Ezion Led Light Bulb - Daylight 10.5w E27
Ezion Led Light Bulb - Warm White 5.5w E27
Ezion Led Light Bulb - Warm White 7.5w E27
For the amountData, I wanted it to be in horizontalBar format. As for the quantityData, I wanted it to be in line format.
var opt = {
type: "horizontalBar",
data: {
labels: labelData,
datasets: [{
label: brand,
data: amountData,
}, {
type: 'line',
label: brand,
data: quantityData,
}]
},
options: options
};
The line chart is not plotting at all. Any ideas?
Thanks in advance!
EDIT PART 2
This is the part where I tried to populate my labelData array. I am pulling from firebase but for demonstration purpose, I will just put a few dummy data first:
var topProductList = [{itemName: 'Ezion Led Light Bulb - Warm White 10.5w E27'},
{itemName: 'Ezion Induction Cooker Ez822'},
{itemName: 'Ezion Led Light Bulb - Daylight 10.5w E27'},
{itemName: 'Ezion Led Light Bulb - Warm White 5.5w E27'},
{itemName: 'Ezion Led Light Bulb - Warm White 7.5w E27'}];
for(var i = 0 ; i < topProductList.length; i++){
var itemName = topProductList[i].itemName;
itemName = itemName.replace(/\s/g, '\n');
labelData.push(itemName);
}
As suggested by #GRUNT, I am trying to replace the empty space with '\n' to format the string properly so that the chart could perform callback. However, the code above does not replace the empty space with '\n'. Here is what I obtained:
The easiest workaround would be to use a callback function (to merge the labels back) for tooltips title, as such :
tooltips: {
callbacks: {
title: function(t, d) {
return d.labels[t[0].index].replace(/\n/, ' ');
}
}
}
but first, you should break the x-axis labels using x-axis' ticks callback function, instead of using two-dimensional labels array (as suggested on the thread you mentioned), like so :
xAxes: [{
ticks: {
callback: function(tick) {
return tick.split(/\n/);
}
}
}]
* put a new-line character where you wanna break line in your label, e.g.: Jan\n2017
ᴅᴇᴍᴏ ⧩
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Jan\n2017', 'Feb\n2017', 'Mar\n2017', 'Apr\n2017', 'May\n2017'],
datasets: [{
label: 'LINE',
data: [3, 1, 4, 2, 5],
backgroundColor: 'rgba(0, 119, 290, 0.2)',
borderColor: 'rgba(0, 119, 290, 0.6)',
fill: false
}]
},
options: {
scales: {
xAxes: [{
ticks: {
callback: function(tick) {
return tick.split(/\n/);
}
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
stepSize: 1
}
}]
},
tooltips: {
callbacks: {
title: function(t, d) {
return d.labels[t[0].index].replace(/\n/, ' ');
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
<canvas id="ctx"></canvas>
Related
I am trying to create a bar chart in angular using chart.js and angular.
I want to display the disaters vs area. with the type of disaster ( earthquake, hurricane, storm...etc) on the x-axis and area (as in location) on the y-axis.
However, the area data is string and does not work when trying to plot a bar graph as it requires numbers.
I am reading the data as follows:
ngOnInit(): void {
this.chartService.noOfEqu().subscribe((res) => {
let area = res.map((res) => res.area);
let disaster = res.map((res) => res.disasterNature);
new Chart('disasterCanvas', {
type: 'bar',
data: {
labels: disaster,
datasets: [
{
data: area,
label: 'area',
backgroundColor: '#A121D5',
},
],
},
options: {
plugins: {
legend: {
display: true,
},
},
scales: {
x: {
ticks: {
display: true,
},
},
y: {
ticks: {
display: true,
},
},
},
},
});
});
}
}
Where let area = res.map((res) => res.area); is the area variable.
I want to know what is the best way to structure the data to be entered into the graph.
The disaster data that is logged is:
and the area data :
How can i structure the area such that it counts how much areas that a disaster has occured and plot it on the bar chart?
Thank you in advance...if there is anything i can clarify please let me know in the comments
Also is there another way to display this data besides tallying the string data?
You need to add a labels array to the scale and set the type to category to use string data:
const options = {
type: 'bar',
data: {
labels: ["Earthquake", "Tornade", "Flood"],
datasets: [{
label: '# of Votes',
data: ['Paris', 'Berlin', 'London'],
backgroundColor: 'pink'
}]
},
options: {
scales: {
y: {
type: 'category',
reverse: true,
labels: ['', 'London', 'Paris', 'Berlin']
}
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>
I am trying to achieve the Tooltip shown below in the first image. Inside of the tooltip I need to display the yAxes and xAxes data. The chart.js version I am using is 3.7.0
My tooltip looks like this:
The tooltip that I am trying copy:
The chart.js documentation is quite hard for me to understand. Is there any guru that can explain to me.
Question: Why is my tooltip returning the yAxes data, that I return as a variable(label) as undefined?
Are there any other options I can use to make my chart look like the chart in the second picture?
My Code:
tooltip: {
displayColors: false,
backgroundColor: 'rgba(45,132,180,0.8)',
bodyFontColor: 'rgb(255,255,255)',
callbacks: {
title: function(item, everything){
return;
},
label: function(item, everything){
//console.log(item);
//console.log(everything);
let first = item.yLabel;
let second = item.xLabel;
let label = first + ' ppm';
return label;
}
}
}
Thank you in advance for your time and efforts, please help me figure out what am I doing wrong!
yLabel and xLabel dont exist anymore on the tooltip, they are V2 syntax.
You can just axess the y object in the parsed section to get the y value. Then you can use the afterBody callback to show the x label like so:
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
}]
},
options: {
plugins: {
tooltip: {
displayColors: false,
backgroundColor: 'rgba(45,132,180,0.8)',
bodyFontColor: 'rgb(255,255,255)',
callbacks: {
title: () => {
return
},
label: (ttItem) => (`${ttItem.parsed.y} ppm`),
afterBody: (ttItems) => (ttItems[0].label)
}
}
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.js"></script>
</body>
i have a multilevel donut chart but it is not rendering correctly here is code
the problem is, onmouseover on all green parts it says objects, on all grey parts it says products, solution i would like is, on outer ring it should say products, in middle objects, and inner most should be materials, grey areas should just show number. here is a jsfiddle of the problem
Code:
var op=93;
var ap=99;
var mp=66;
var ctx = new Chart(myChart, {
type: 'doughnut',
data: {
labels: ['Objects', 'Products', 'Materials'],
datasets: [{
label: 'Objects',
data: [op, 100 - op],
backgroundColor: ['#006a4e','#eeeeee'],
hoverOffset: 4
},{
label: 'Products',
data: [ap, 100 - ap],
backgroundColor: ['#2e856e', '#eeeeee'],
hoverOffset: 4
},
{
label: 'Materials',
data: [mp, 100 - mp],
backgroundColor: ['#5ca08e', '#eeeeee'],
hoverOffset: 4
}
]
},
options: {
//cutoutPercentage: 40,
height: 200,
width:200
}
});
You can achieve that fairly simple with Chart.JS 2.7.2. Add labels to each dataset like this:
data: {
labels: ['Existing', 'Non'],
datasets: [
{
labels: ['Objects', 'Non-objects'],
...
}, {
labels: ['Products', 'Non-products'],
...
},
{
labels: ['Materials', 'Non-materials'],
...
}
]
}
And add the following label tooltip callback:
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
var index = tooltipItem.index;
return dataset.labels[index] + ": " + dataset.data[index];
}
}
}
Demo: https://jsfiddle.net/adelriosantiago/fxd6vops/3/
I am sure it is possible with Chart.JS > 3.0 too but I have no idea how since quite a few things changed in the structure.
I had a same problem which took a lot of time but what worked in the end was importing these elements and initialising them ..
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';
ChartJS.register(ArcElement, Tooltip, Legend);
these are the elements that helps make the entire chart. you can't skip them
I am trying to create a visitors bar chart with included values, for example:
I want to show a bar chart of total daily visitors, and that bar should contain info of total visitors and first time visitors.
so data for a bar should look like:
data: {
labels: getDataAttributes(data, 'data-date'),
// an array holding the date of each bar (custom function)
// for example purposes lets say its just 3 bars
datasets: [{
label: ['Number of visitors', 'Number of new visitors'],
data: [[20,15], [25,10], [30, 15]],
// Here if we would use a simple stacked bar chart the height would be the sum of 2 values
// e.g.(20+15=35), but I wish that the bar height would be the number of total visitors 20
// the tooltip should contain values of total visitors and new visitors respectively 20 and 15
}]
}
I looked in the chartjs documentation, but found only examples with stacked values and that solution is not applied in my desired design, can someone please reference documentation/articles/tutorials or personal experience or perhaps I should switch to d3js? Thanks.
You could define two datasets, the first one would contain the values of new visitors, the second one the values of all visitors.
Then you would define the x-axis as being stacked:
options: {
scales: {
xAxes: [{
stacked: true
}],
Please take a look at below runnable code snippet to see how it works:
const baseData = [[20,15], [25,10], [30, 15]];
new Chart('chart', {
type: 'bar',
data: {
labels: ['25.10.2020', '26.10.2020', '27.10.2020'],
datasets: [{
label: 'Number of new visitors',
data: baseData.map(v => v[1]),
backgroundColor: 'green'
},
{
label: 'Number of visitors',
data: baseData.map(v => v[0]),
backgroundColor: 'blue'
}]
},
options: {
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas id="chart" height="100"></canvas>
I already have a graph using chartJS as shown below and the code for that is :
r_chart_data = [[-0.001, 2.052],[-2.385, 2.052]];
dr_chart_data = [[-0.01, 1.83],[1.05, 2.83],[1.05, 2.83]];
myChart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: label,
datasets: [{
label : 'DataSet1',
data: r_chart_data,
backgroundColor: 'rgb(255, 99, 132)'
},
{
label : 'DataSet2',
data: dr_chart_data,
backgroundColor: 'lightblue'
}
]
},
options: {
lineAtIndex : level,
scales: {
xAxes: [{
ticks: {
min: -5,
max: 5,
stepSize: 0.5,
}
}]
}
}
});
But what if my
r_chart_data[0] i.e. [-0.001,2.052]
is not a continuos range and instead its value is something like
[[-0.001,1.023],[1.5,2.052]]
then how should I plot the graph. Modified r_chart_data:
r_chart_data = [[[-0.001,1.023],[1.5,2.052]],[-2.385, 2.052]];
Similarly if I have a range of data sets that I need to plot in the form of a horizontal bar graph using ChartJS. The data set which are in the form of:
dataset1: [[-10,-4],[-2,2],[4,6]] // should be plotted in a single bar graph
dataset2: [[-2,1],[1.5,3.5],[5.2,8.9]] //should be plotted in a second bar
dataset3: [[2,4],[5,7]] //third bar
.. and so on
Moreover, each dataset need not have three range items. It can have one, two or any number of range items.