Stacked Bars with different colors - javascript

I was looking at the stacked bars for chart js (https://www.chartjs.org/docs/latest/samples/bar/stacked.html)
They seem to be pretty much automatically stack bars together, which is not exactly what i want. In my case, let's just say i want to draw 5 vertical bars, and each of these bars have 2 values. The before value and the after value.
For example, let's say that the before value s $10,000 and the after values is $8,000. I want to draw a stacked bar where the $10,000 bar is blue in color and the 8,000 is yellow in color, while their difference, the $2,000 is red, indicating a visual $2,000 loss of that initial amount of $10,000.
Likewise, if the before value is $10,000 and the after value is $12,000, the bar color from $10,000 to $12,000 would be green, to indicate a gain.
Is there an example of a chart of that sort somewhere ? I have been struggling to make this work :/

Not exactly sure what your ultimate goal is for an output, but I think this is the basic idea of what you are after.
const stats = {
base: [800, 600],
gain: [0, 0],
loss: [0, 200],
}
const labels = ["Total", "breakdown"];
const data = {
labels: labels,
datasets: [
{
label: 'Base Money',
data: stats.base,
backgroundColor: "green",
},
{
label: 'Gains',
data: stats.gain,
backgroundColor: "lime",
},
{
label: 'Losses',
data: stats.loss,
backgroundColor: "red",
},
]
};
const config = {
type: 'bar',
data: data,
options: {
responsive: true,
scales: {
x: {
stacked: true,
},
y: {
stacked: true
}
}
}
};
var ctx = $('#myChart');
var myChart = new Chart(ctx, config);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.2/chart.min.js"></script>
<div class="graph">
<div class="chart-legend">
</div>
<div class="chart">
<canvas id="myChart"></canvas>
</div>
</div>

Related

How to order bubbles according their size and not by the order of their datasets?

I have a bubble chart with multiple datasets. Two points of two different datasets may have the same coordinates (x and y-value) and lay on the same place in the chart. Because the display order of the points is determined according the order of the datasets, the smaller point could be completely covered by the bigger point in front of it.
Is there a option or a way, to display the points in order of their bubble size?
Simplified example of four points. The solution must also work for multiple datasets with each 30+ points.
I am searching a solution to draw the blue point in front of the red point, for the left pair and let the right pair as it is. This order must be independent of the order of the datasets, as it is per point and not per dataset.
Sorting the datasets seems to be no option for me, as the order cannot be determined per dataset, but instead must be determined for every coordinate/point. When drawing a point, it must be checked for this particular coordinate, if any other point with the same coordinates exists and if this point is greater than the current point (if true, the greater point must be drawn before, to not cover up the current point).
const config = {
type: 'bubble',
data: {
datasets: [{
label: 'Dataset 1',
data: [{
x: 1,
y: 1,
r: 20
},
{
x: 2,
y: 1,
r: 15
}
],
borderColor: 'red',
backgroundColor: 'red'
},
{
label: 'Dataset 2',
data: [{
x: 1,
y: 1,
r: 15
},
{
x: 2,
y: 1,
r: 20
}
],
borderColor: 'blue',
backgroundColor: 'blue'
}
]
},
options: {
responsive: true,
scales: {
x: {
suggestedMin: 0,
suggestedMax: 3
}
},
plugins: {
legend: {
position: 'top',
}
}
}
};
var ctx = document.getElementById('chartJSCanvas').getContext('2d');
const chart = new Chart(ctx, config);
<body>
<canvas id="chartJSCanvas" width="300" height="100"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.1.0/chart.js" integrity="sha512-LlFvdZpYhQdASf4aZfSpmyHD6+waYVfJRwfJrBgki7/Uh+TXMLFYcKMRim65+o3lFsfk20vrK9sJDute7BUAUw==" crossorigin="anonymous"></script>
</body>
The easiest way would be to just sort the data in the datasets and then the datasets themselves before drawing them.
An easy way to do this is provided by Array.prototype.forEach and Array.prototype.sort
First sort the data within each dataset like this:
config.data.datasets.forEach(function(element){
element.data.sort(function (a, b) {
return a.r - b.r;
});
});
Then you can sort the data sets by their smallest element like this:
config.data.datasets.sort(function (a, b) {
return a.data[0].r - b.data[0].r;
});
After that, you can regularly pass your config object with ordered datasets to your library call just the way you do it above:
const chart = new Chart(ctx, config);

chart.js - how to draw and manage line when only one label present in chart js Linechart

I'm using Chart.JS v 2.9.3 to create a line chart
line-chart diagram to show the month-wise total of expenses of selected product
For example, if the user select XYZ product then this charts would show the monthly expenses [Jan-2021-Dec-2021]
and if that respective product expense only present Jan-2021 then it displays month on y-Axes at staring
here is jsfiddle example
Adding offset trick I had already tried xAxes : [{ offset:true }],
var config = {
type: 'line',
data: {
labels: ["jan-2021"],
datasets: [{
label: "month-year",
data: [65],
backgroundColor: "rgb(118, 101, 228)",
}],
},
scales : {
xAxes : [{
offset:true
}],
},
};
var ctx = document.getElementById("myChart").getContext("2d");
new Chart(ctx, config);
<div class="myChart">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
<canvas id="myChart"></canvas>
</div>
please refer to the above image for getting an idea of what I'm trying to archive, I'm not concern about dot that on the chart
As you can see, the points are stick to the y-axis. Is there a possibility to center the line chart when only one data is present in the diagram?
Chart.js does not support this kind of use case since it gives a distorted image of your chart since point and label don't align anymore. If you really want this you can check beforehand in your code if there is only 1 data point there. If this is the case add an empty string in your labels array in the front and back and add zero at the front of back of your data array (or a slightly lower value as your single datapoint so that the scales don't get big steps) like so:
var config = {
type: 'line',
data: {
labels: ["", "January-2021", ""],
datasets: [{
label: "month-year",
data: [0, 134335066, 0],
backgroundColor: "rgb(118, 101, 228)",
}],
},
scales: {},
};
var ctx = document.getElementById("myChart").getContext("2d");
new Chart(ctx, config);
<div class="myChart">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.js"></script>
<canvas id="myChart"></canvas>
</div>
You can use align option:
var mybarChart = new Chart(ctx, {
type: 'bar',
responsive: true,
data: data,
options: {
legend: {
display: false,
position: 'bottom',
align: 'center'
},
var config = {
type: 'line',
data: {
labels: ["", "January-2021", ""],
datasets: [{
label: "month-year",
data: [0, 134335066, 0],
backgroundColor: "rgb(118, 101, 228)",
}],
options: {
legend: {
display: false,
position: 'bottom',
align: 'center'
},
},
scales: {},
};
refer to this

ChartJS: Highlight dataset in a stacked bar chart when hovering over the legend?

I've got a horizontal stacked bar chart rendered in Chart.js, and the legend corresponds to the different classes. Here's a bit of it (working on a dummy dataset, disregard the nonsense names):
The labels on the left are users, the labels in the legend (which correspond to the classes in the bar chart, i.e. the different datasets) are mailing lists. The chart, basically, shows how many users are members of specific mailing lists; the length of the bar is how many mailing lists a given user is a member of.
What I'd like to do is set it up so hovering over an entry in the legend will highlight (ideally with a border or something) the portions of the bar chart corresponding to that dataset. So if I hovered over the first dataset entry, the blue block at the left end of all those bars (except "anionic") would get a highlight.
Using the onHover and onLeave events for the legend, I'm successfully console.log'ing the currently-hovered dataset index. But I can't figure out how to make the bar elements belonging to that dataset highlight.
With the new upcomming release of version 3 you can do this with the setActive elements.
Documentation: https://www.chartjs.org/docs/master/developers/api/#setactiveelementsactiveelements
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1,
hoverBackgroundColor: 'green',
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1,
hoverBackgroundColor: 'red',
}
]
},
options: {
scales: {}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
const chart = new Chart(ctx, options);
chart.setActiveElements([{
datasetIndex: 0,
index: 1,
}, {
datasetIndex: 1,
index: 1,
}]);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.0.0-beta.10/chart.js" integrity="sha512-7igYTuENB1pHNsZ/SyzMYrcJAmRCk084yVOsxNNCQAdX1wSYvCeBOgSOMC6wUdKMO76kCJNOpW4jY3UW5CoBnA==" crossorigin="anonymous"></script>
</body>
Using ChartJS 3 setActiveElements API, you can highlight an entire dataset on legend hover using the following code in options.plugins.legend
onHover: function (event, legendItem) {
const datasetIndex = legendItem.datasetIndex;
let elementList = [];
for (let i = 0; i < this.chart.getDatasetMeta(datasetIndex).data.length; i++) {
elementList.push({
'datasetIndex': datasetIndex,
'index': i,
});
}
this.chart.setActiveElements(elementList);
this.chart.update();
}

Stacked bar chart with chartjs with included values

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>

Plot Ranged horizontal bar graph with holes using ChartJS

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.

Categories

Resources