Custom Axis labels for Grouped Bar chart - javascript

Needed output:
I need to configure a grouped bar chart in which the type of each bar is shown in the axis itself.
I am using chartjs 2.9. How can I add the text "Availability","Co-funded","CPC" in the axis itself. I can't find any configuration which support this implementation in Chart js . Is there any other JS library where this is possible
this.barChart = new .Chart(ctx, {
type: "bar",
data: {
labels: this.barChartData["chart-data"].map((obj) => obj.y),
datasets:
this.barChartData["chart-mapping"].map((obj) => {
return {
label: obj.label,
data: this.barChartData["chart-data"],
backgroundColor: obj.color,
parsing: {
xAxisKey: obj.key,
},
};
}),
},
options: {
datasets: {
barThickness: 20,
},
indexAxis: "y",
plugins: {
legend: { position: "right", align: "start", title: "Type" },
},
},
});
barChartData = {
"chart-mapping": [
{
key: "avi",
label: "Availability..",
color: "rgba(50, 144, 237, 1)",
},
{
key: "cfd",
label: "Co-funded..",
color: "rgba(119, 181, 242, 1)",
},
{
key: "CPC",
label: "CPC",
color: "rgba(157, 83, 242, 1)",
},
{
key: "od",
label: "Order Drop..",
color: "rgba(195, 152, 245, 1)",
},
],
"chart-data": [
{
y: "Name1",
avi: 32,
cfd: 32,
CPC: 57,
od: 12,
},
{
y: "AK",
avi: 15,
cfd: 23,
CPC: 42,
od: 45,
},
{
y: "Name3",
avi: 67,
cfd: 34,
CPC: 21,
od: 43,
},
],
};
Current implementation:

Related

How To Change Layout to Horizontal in Chart Js

I've chart and it's currently a vertical bar chart but I wanted to make it completely horizontal so how can I do it?
import React, { Component } from "react";
import { render } from "react-dom";
import Hello from "./Hello";
import "./style.css";
import { Bar } from "react-chartjs-2";
require("./RoundedBars.js");
class App extends Component {
constructor() {
super();
this.state = {
data: {
labels: ["Week I", "Week II", "Week III", "Week IV"],
datasets: [
{
label: "Pending Approval",
backgroundColor: "rgb(51, 153, 255)",
data: [20, 10, 30, 15],
stack: 1,
name: "AMR"
},
{
label: "Invoice Created",
backgroundColor: "rgb(51, 204, 51)",
data: [60, 20, 20, 30],
stack: 1
},
{
label: "Approved!",
backgroundColor: "green",
data: [40, 50, 20, 45],
stack: 1
},
{
label: "Pending Approval",
backgroundColor: "rgb(51, 153, 255)",
data: [25, 5, 20, 10],
stack: 2
},
{
label: "Invoice Created!",
backgroundColor: "rgb(51, 204, 51)",
data: [51, 25, 10, 30],
stack: 2
},
{
label: "Approved!",
backgroundColor: "green",
data: [45, 40, 22, 55],
stack: 2
},
{
label: "Pending Approval",
backgroundColor: "rgb(51, 153, 255)",
data: [35, 5, 25, 10],
stack: 3
},
{
label: "Invoice Created!",
backgroundColor: "rgb(51, 204, 51)",
data: [51, 25, 10, 30],
stack: 3
},
{
label: "Approved!",
backgroundColor: "green",
data: [45, 40, 22, 55],
stack: 3
},
{
label: "Pending Approval",
backgroundColor: "rgb(51, 153, 255)",
data: [15, 5, 21, 17],
stack: 4
},
{
label: "Invoice Created!",
backgroundColor: "rgb(51, 204, 51)",
data: [51, 25, 10, 30],
stack: 4
},
{
label: "Approved!",
backgroundColor: "green",
data: [45, 40, 22, 55],
stack: 4
}
]
},
options: {
cornerRadius: 10,
legend: {
labels: {
generateLabels: function(chart) {
return Chart.defaults.global.legend.labels.generateLabels
.apply(this, [chart])
.filter(function(item, i) {
return i <= 2;
});
}
}
},
scales: {
xAxes: [
{
id: "xAxis1",
type: "category",
ticks: {
display: false
}
},
{
id: "xAxis2",
type: "linear",
ticks: {
beginAtZero: true,
max: 4,
min: 0,
stepSize: 0.25,
labelOffset: 15,
callback: function(value, index, values) {
var array = ["W1", "W2", "W3", "W4"];
// console.log("values: ", index % array.length) ;
if (index == values.length - 1) return "";
return array[index % array.length];
}
}
},
{
id: "xAxis3",
type: "linear",
ticks: {
beginAtZero: true,
max: 4,
min: 0,
stepSize: 1,
labelOffset: 55,
callback: function(value, index, values) {
var weeks = ["Week I", "Week II", "Week III", "Week IV"];
return weeks[index];
}
}
}
],
yAxes: [
{
stacked: true
}
]
},
tooltips: {
mode: "nearest",
callbacks: {
title: function(tooltipItem, data) {
const arr = [
"W1",
"W1",
"W1",
"W2",
"W2",
"W2",
"W3",
"W3",
"W3",
"W4",
"W4",
"W4"
];
// console.log(tooltipItem);
return arr[tooltipItem[0].datasetIndex];
}
}
}
}
};
}
render() {
return (
<div>
<Bar data={this.state.data} options={this.state.options} />
</div>
);
}
}
render(<App />, document.getElementById("root"));
StackBlitz Demo
To make it horizontal, you should use HorizontalBar component instead of Bar component. Obviously, you will need to update your data a little bit, to make sure it can be displayed in HorizontalBar - but that's the way to have horizontal bar.
Here is a quick example on how to use HorizontalBar:
Using react-chartjs-2
https://codesandbox.io/s/jjpk3o5l3?file=/src/Hello.js
Using original library:
https://www.chartjs.org/docs/latest/charts/bar.html#horizontal-bar-chart

How to create a stacked line chart using Apache ECharts using encode

I see this example in Apache ECharts
https://echarts.apache.org/examples/en/editor.html?c=line-stack
import * as echarts from 'echarts';
var chartDom = document.getElementById('main');
var myChart = echarts.init(chartDom);
var option;
option = {
title: {
text: '折线图堆叠'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
},
yAxis: {
type: 'value'
},
series: [
{
name: '邮件营销',
type: 'line',
stack: '总量',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '联盟广告',
type: 'line',
stack: '总量',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '视频广告',
type: 'line',
stack: '总量',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: '直接访问',
type: 'line',
stack: '总量',
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: '搜索引擎',
type: 'line',
stack: '总量',
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
option && myChart.setOption(option);
Now that ECharts v5.x has support to specify encode , is it possible to create the above chart using encode instead of specifying data array for each series?
What i am looking for is something on these lines
option = {
title: {
text: 'Some Title'
},
tooltip: {
trigger: 'axis'
},
dataset:{
source:[
['XAxis_Column_Name','Series_Column_Name','YAxis_Column_Name'],
['x1','s1',10],
['x2','s2',20],
['x3','s1',40],
['x4','s1',70],
['x5','s2',90],
['x5','s1',100],
['x6','s3',120],
]
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
encode:{
x: "XAxis_Column_Name"
}
},
yAxis: {
type: 'value',
encode:{
y: "YAxis_Column_Name"
}
},
series: [
{type: 'line'},
{type: 'line'},
{type: 'line'}
]
};
The end result should be a line chart with 3 lines (one each for s1, s2 and s3). Any help here is much appreciated. I don't want to deal with data extraction and segregating them into arrays for each series

ChartJS multiple annotations (vertical lines)

i am trying to put 2 vertical lines on a chart.JS chart using the annotations plugin. i am using the following versions:
chart.js = 2.8.0
annotations plugin = 0.5.7
here's the JSFiddle
please see my code below:
var ann = ["4.35"];
var ann_labels = ["start"];
var annotations_array = ann.map(function(value, index) {
return {
type: 'line',
id: 'vline' + index,
mode: 'vertical',
scaleID: 'x-axis-0',
value: value,
borderColor: 'green',
borderWidth: 1,
label: {
enabled: true,
position: "bottom",
content: ann_labels
}
}
});
var ann2 = ["4.29"];
var ann_labels2 = ["stop"];
var annotations_array2 = ann2.map(function(value, index) {
return {
type: 'line',
id: 'vline2' + index,
mode: 'vertical',
scaleID: 'x-axis-0',
value: value,
borderColor: 'green',
borderWidth: 1,
label: {
enabled: true,
position: "top",
content: ann_labels2
}
}
});
var ctx = document.getElementById('test').getContext('2d');
var test = new Chart(ctx, {
type: 'line',
data: {
labels: ["1.44","4.03","4.35","3.99","3.58","3.75","4.29","5.02","5.95","6.65"],
datasets: [{
data: ["1", "2", "1", "2", "1", "2", "1", "2", "1", "2"],
yAxisID: 'A',
backgroundColor: [
'rgba(91, 192, 222, 0.1)',
],
borderColor: [
'rgba(0, 123, 255, 0.8)',
],
borderWidth: 1.3,
},
{
data: ["10", "11", "12","13","14","15","16","17",],
yAxisID: 'B',
backgroundColor: [
'rgba(255, 206, 86, 0.0)',
],
borderColor: [
'rgba(217, 83, 79, 0.6)',
],
borderWidth: 1.3,
}]
},
options: {
annotation: {
drawTime: 'afterDatasetsDraw',
annotations: annotations_array
},
maintainAspectRatio: true,
scales: {
yAxes: [{
id: 'A',
ticks: {
callback: function(value, index, values) {
return value + ' m';
},
reverse: true,
}
},
{
id: 'B',
position: 'right',
ticks: {
callback: function(value, index, values) {
return value + ' °C';
},
reverse: true,
}
}]
},
elements: {
point:{
radius: 0,
}
},
legend: {
position: 'bottom',
display: false,
},
}
});
however, i am unable to display both vertical lines (annotations_array and annotations_array2) at the same time.
everything works fine when i do this:
annotations: annotations_array
or this:
annotations: annotations_array2
but when i try to print both arrays, it doesnt work:
annotations: annotations_array, annotations_array2
I have also tried this without any luck:
annotations: [{annotations_array},{annotations_array2}]
does anyone know what am i doing wrong?
Thanks in advance!
You have to provide both annotations as object in 1 array, not an array containing objects containing arrays, see example:
var ann = ["4.35", "4.29"];
var ann_labels = ["start", "stop"];
var annotations_array = ann.map(function(value, index) {
return {
type: 'line',
id: 'vline' + index,
mode: 'vertical',
scaleID: 'x-axis-0',
value: value,
borderColor: 'green',
borderWidth: 1,
label: {
enabled: true,
position: "bottom",
content: ann_labels[index]
}
}
});
var ctx = document.getElementById('test').getContext('2d');
var test = new Chart(ctx, {
type: 'line',
data: {
labels: ["1.44", "4.03", "4.35", "3.99", "3.58", "3.75", "4.29", "5.02", "5.95", "6.65"],
datasets: [{
data: ["1", "2", "1", "2", "1", "2", "1", "2", "1", "2"],
yAxisID: 'A',
backgroundColor: [
'rgba(91, 192, 222, 0.1)',
],
borderColor: [
'rgba(0, 123, 255, 0.8)',
],
borderWidth: 1.3,
},
{
data: ["10", "11", "12", "13", "14", "15", "16", "17", ],
yAxisID: 'B',
backgroundColor: [
'rgba(255, 206, 86, 0.0)',
],
borderColor: [
'rgba(217, 83, 79, 0.6)',
],
borderWidth: 1.3,
}
]
},
options: {
annotation: {
drawTime: 'afterDatasetsDraw',
annotations: annotations_array
},
maintainAspectRatio: true,
scales: {
yAxes: [{
id: 'A',
ticks: {
callback: function(value, index, values) {
return value + ' m';
},
reverse: true,
}
},
{
id: 'B',
position: 'right',
ticks: {
callback: function(value, index, values) {
return value + ' °C';
},
reverse: true,
}
}
]
},
elements: {
point: {
radius: 0,
}
},
legend: {
position: 'bottom',
display: false,
},
}
});
<h3 class="card-text"><canvas id="test"></canvas></h3>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/0.5.7/chartjs-plugin-annotation.min.js"></script>
Fiddle: https://jsfiddle.net/Leelenaleee/6Ltycqfh/7/

ReactJS ApexCharts not displaying tooltip

I take one of the examples posted and slightly modify it by removing some data. When the sets don't have the same number of data points, the tooltips stop displaying.
Please see the following two examples. The first one being the one posted in the docs. The second, the modified version. When hovering starting from the end data points, the tooltip doesn't display anything for the last columns.
Example from docs: https://codepen.io/junedchhipa/pen/YJQKOy
var options = {
chart: {
height: 310,
type: 'line',
stacked: false,
},
stroke: {
width: [0, 2, 5],
curve: 'smooth'
},
plotOptions: {
bar: {
columnWidth: '50%'
}
},
series: [{
name: 'Series Column',
type: 'column',
data: [23, 11, 22, 27, 13, 22, 37, 21, 44, 22, 30]
}, {
name: 'Series Area',
type: 'area',
data: [44, 55, 41, 67, 22, 43, 21, 41, 56, 27, 43]
}, {
name: 'Series Line',
type: 'line',
data: [30, 25, 36, 30, 45, 35, 64, 52, 59, 36, 39]
}],
fill: {
opacity: [0.85,0.25,1],
gradient: {
inverseColors: false,
shade: 'light',
type: "vertical",
opacityFrom: 0.85,
opacityTo: 0.55,
stops: [0, 100, 100, 100]
}
},
labels: ['01/01/2003', '02/01/2003','03/01/2003','04/01/2003','05/01/2003','06/01/2003','07/01/2003','08/01/2003','09/01/2003','10/01/2003','11/01/2003'],
markers: {
size: 0
},
xaxis: {
type:'datetime'
},
yaxis: {
title: {
text: 'Points',
},
min: 0
},
legend: {
show: false
},
tooltip: {
shared: true,
intersect: false,
y: {
formatter: function (y) {
if(typeof y !== "undefined") {
return y.toFixed(0) + " points";
}
return y;
}
}
}
}
var chart = new ApexCharts(
document.querySelector("#chart"),
options
);
chart.render();
// check if the checkbox has any unchecked item
checkLegends()
function checkLegends() {
var allLegends = document.querySelectorAll(".legend input[type='checkbox']")
for(var i = 0; i < allLegends.length; i++) {
if(!allLegends[i].checked) {
chart.toggleSeries(allLegends[i].value)
}
}
}
// toggleSeries accepts a single argument which should match the series name you're trying to toggle
function toggleSeries(checkbox) {
chart.toggleSeries(checkbox.value)
}
Modified example:
https://codepen.io/mmk2118/pen/mdbpOWN
var options = {
chart: {
height: 310,
type: 'line',
stacked: false,
},
stroke: {
width: [0, 2, 5],
curve: 'smooth'
},
plotOptions: {
bar: {
columnWidth: '50%'
}
},
series: [{
name: 'Series Column',
type: 'column',
data: [23, 11, 22, 27, 13, 22, 37, 21, 44, 22, 30]
}, {
name: 'Series Area',
type: 'area',
data: [44, 55, 41, 67, 22, 43, 21, 41]
}, {
name: 'Series Line',
type: 'line',
data: [30, 25, 36, 30, 45, 35, 64, 52, 59, 36, 39]
}],
fill: {
opacity: [0.85,0.25,1],
gradient: {
inverseColors: false,
shade: 'light',
type: "vertical",
opacityFrom: 0.85,
opacityTo: 0.55,
stops: [0, 100, 100, 100]
}
},
labels: ['01/01/2003', '02/01/2003','03/01/2003','04/01/2003','05/01/2003','06/01/2003','07/01/2003','08/01/2003','09/01/2003','10/01/2003','11/01/2003'],
markers: {
size: 0
},
xaxis: {
type:'datetime'
},
yaxis: {
title: {
text: 'Points',
},
min: 0
},
legend: {
show: false
},
tooltip: {
shared: true,
intersect: false,
y: {
formatter: function (y) {
if(typeof y !== "undefined") {
return y.toFixed(0) + " points";
}
return y;
}
}
}
}
var chart = new ApexCharts(
document.querySelector("#chart"),
options
);
chart.render();
// check if the checkbox has any unchecked item
checkLegends()
function checkLegends() {
var allLegends = document.querySelectorAll(".legend input[type='checkbox']")
for(var i = 0; i < allLegends.length; i++) {
if(!allLegends[i].checked) {
chart.toggleSeries(allLegends[i].value)
}
}
}
// toggleSeries accepts a single argument which should match the series name you're trying to toggle
function toggleSeries(checkbox) {
chart.toggleSeries(checkbox.value)
}
Your codepen example uses an older version of ApexCharts.
Please update by pulling the latest version here
https://cdn.jsdelivr.net/npm/apexcharts#latest
Also, if you have a different number of data-points in each series, you can turn off shared tooltip and only show the tooltip when the user hovers over bars/markers directly.
tooltip: {
shared: false,
intersect: true
}

How to move the x-axis values and line points to the middle of two x-axis lines using chartjs?

Using chartjs, I setup the following chart:
function myFunction(){
var options = {
type: 'line',
data: {
labels: ["1", "2", "3", "4", "5"],
datasets: [
{
data: [26, 26, 29, 28, 29],
borderWidth: 2,
fill: false,
lineTension: 0
},
{
data: [26, 26, 33, 28, 30],
borderWidth: 2,
fill: false,
lineTension: 0,
}
]
},
options: {
scales: {
yAxes: [{
display: false,
ticks: {
suggestedMin: 0,
beginAtZero: true
}
}]
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
}
I want to move the points and the x-axis numbers to the right, sothat they are positioned between the axis lines. (like: 1 between 1 and 2; 2 between 2 and 3; etc.) See below:
How can I do this?
Here is how you can do this :
ꜰɪʀꜱᴛ
Set default chart type to bar , like so :
var options = {
type: 'bar',
data: {
...
ꜱᴇᴄᴏɴᴅ
Set first dataset­'s type to line , as such :
...
datasets: [{
type: 'line',
data: [26, 26, 29, 28, 29],
...
ᴡᴏʀᴋɪɴɢ ᴇxᴀᴍᴘʟᴇ ⧩
function myFunction() {
var options = {
type: 'bar',
data: {
labels: ["1", "2", "3", "4", "5"],
datasets: [{
type: 'line',
data: [26, 26, 29, 28, 29],
borderColor: 'rgba(0, 119, 220, 1)',
borderWidth: 2,
fill: false,
lineTension: 0
}, {
data: [26, 26, 33, 28, 30],
borderWidth: 2
}]
},
options: {
scales: {
yAxes: [{
display: false,
ticks: {
suggestedMin: 0,
beginAtZero: true
}
}]
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
}
myFunction();
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="chartJSContainer"></canvas>

Categories