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
Related
I need the graph to display the values without rounding, the same as shown in the tooltip
In your chart options dataLabels use the formatter to define the display value, e.g.
dataLabels: {
formatter: function(val) {
return val.toFixed(2);
}
}
Full example with demo chart taken from official docs and added custom label:
var options = {
series: [{
name: 'Marine Sprite',
data: [44, 55, 41, 37, 22, 43, 21]
}, {
name: 'Striking Calf',
data: [53, 32, 33, 52, 13, 43, 32]
}, {
name: 'Tank Picture',
data: [12, 17, 11, 9, 15, 11, 20]
}, {
name: 'Bucket Slope',
data: [9, 7, 5, 8, 6, 9, 4]
}, {
name: 'Reborn Kid',
data: [25, 12, 19, 32, 25, 24, 10]
}],
chart: {
type: 'bar',
height: 350,
stacked: true,
stackType: '100%'
},
plotOptions: {
bar: {
horizontal: true,
},
},
stroke: {
width: 1,
colors: ['#fff']
},
title: {
text: '100% Stacked Bar'
},
xaxis: {
categories: [2008, 2009, 2010, 2011, 2012, 2013, 2014],
},
dataLabels: {
formatter: function(val) {
return val.toFixed(2);
}
},
tooltip: {
y: {
formatter: function(val) {
return val + "K"
}
}
},
fill: {
opacity: 1
},
legend: {
position: 'top',
horizontalAlign: 'left',
offsetX: 40
}
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<div id="chart"></div>
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:
I tried using the stack and offset but it does not seem to work
This is my code:
import React, {
useEffect
} from 'react';
import {
Bar
} from 'react-chartjs-2';
import useWindowWidth from 'wa-shared/src/hooks/useWindowWidth';
const state = {
count: 0,
data: {
labels: [
['Total Users'],
['Users with', 'Active', 'Session'],
['Created 1', 'or More', 'Videos'],
['Shared 1', 'or More', 'Videos']
],
datasets: [{
backgroundColor: '#26863D',
data: [70, 66, 57, 1],
barThickness: '35',
},
{
backgroundColor: '#F2F2F2',
data: [70, 70, 70, 70],
borderRadius: '5',
barThickness: '35',
}
]
}
}
const App = ({}) => {
const width = useWindowWidth();
useEffect(() => {});
return ( <
div className = 'singlebar-chart'
id = "barchart" >
<Bar> data = {
state.data
}
options = {
{
scales: {
x: {
grid: {
display: false,
},
offset: true,
ticks: {
maxRotation: 0,
minRotation: 0,
font: {
size: 8,
}
},
},
y: {
min: 0,
max: 100,
ticks: {
fontColor: '#8A8A8A',
font: {
size: 8,
},
stepSize: 25,
callback: function(value) {
return value + "%"
},
},
scaleLabel: {
display: true,
labelString: "Percentage",
},
grid: {
display: false,
}
}
},
plugins: {
legend: {
display: false,
},
}
}
</Bar>
</div>
)
}
export default App;
.singlebar-chart{
width: 95%;
}
You can use a second x axis and map the other dataset to that axes:
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'pink'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
backgroundColor: 'orange',
xAxisID: 'x2'
}
]
},
options: {
scales: {
x: {},
x2: {
display: false // Dont show the axes since it is just a duplicate
}
}
}
}
var 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.8.0/chart.js"></script>
</body>
Although this gives the exect same result as setting stacked true on the x axis.
So I'm using the datalabels plugin for Chartjs on a bar chart. Each label has data for monthly and 7 days prior. I want the datalabels to be colored red for monthly black for 7 days prior. the color feature in options groups 2 bars together and displays 2 red 2 black 2 red 2 black in chunks as appose to individually.
Heres a link to the outputted chart. https://imgur.com/fqPesYz
import Chart from "chart.js";
import ChartDataLabels from "chartjs-plugin-datalabels";
require("../../Row4/Row4Charts/RoundedBars.js");
export default class Cancellations7daysChart extends Component {
Cancellations7daysChart = React.createRef();
componentDidMount() {
const Cancellations7daysChart = this.Cancellations7daysChart.current.getContext(
"2d"
);
new Chart(Cancellations7daysChart, {
type: "bar",
data: {
labels: ["DSL", "FTTC", "FTTP", "GFast"],
datasets: [
{
label: "Monthly",
data: [7, 19, 2, 0],
backgroundColor: [
"rgba(255, 9, 49)",
"rgba(255, 9, 49)",
"rgba(255, 9, 49)",
"rgba(255, 9, 49)"
],
borderColor: [
"rgba(0, 193, 189)",
"rgba(255, 9, 49)",
"rgba(0, 193, 189)",
"rgba(0, 193, 189)"
],
borderWidth: 1,
pointRadius: 4,
},
{
label: "7 days prior",
data: [2, 11, 5, 3],
backgroundColor: [
"rgba(208, 210, 211)",
"rgba(208, 210, 211)",
"rgba(208, 210, 211)",
"rgba(208, 210, 211)"
],
borderColor: [
"rgba(208, 210, 211)",
"rgba(208, 210, 211)",
"rgba(208, 210, 211)",
"rgba(208, 210, 211)"
],
borderWidth: 1,
pointRadius: 6,
}
]
},
options: {
maintainAspectRatio: true,
cornerRadius: 6,
cutoutPercentage: 65,
angleLines: {
display: true
},
tooltips: {
enabled: true
},
label: {
usePointStyle: true
},
legend: {
position: "bottom",
labels: {
filter: function (legendItem, Cancellations7daysChart) {
return !legendItem.text.includes("Monthly");
}
}
},
scales: {
ticks: {
maxTickLimit: 1,
max: 15,
display: false
},
//yaxes change
yAxes: [
{
gridLines: {
drawBorder: false,
display: false
},
ticks: {
beginAtZero: true,
display: false
}
}
],
//xaxes change
xAxes: [
{
ticks: {
//Change font here
},
gridLines: {
drawBorder: false,
display: false,
scaleShowLabels: false
}
}
]
},
plugins: {
datalabels: {
color: ["red", "black", "red", "black", "red", "black", "red", "black"],
align: "end",
anchor: "end"
}
}
}
});
}
render() {
return (
<div>
<canvas
id="Cancellations7daysChart"
ref={this.Cancellations7daysChart}
width={360}
height={360}
/>
</div>
);
}
}
You need to make a function to change the colors depending their label:
plugins: {
datalabels: {
anchor: 'end',
align: 'end',
color: function(context) {
var index = context.dataIndex;
var value = context.dataset.data[index];
var valueRed = context.dataset.label;
if(valueRed === 'Monthly') {
return value = 'red';
} else {
return value = '#000';
}
}
}
}
Here is a working example: Plunker example
More info about formatting in the plugin's page: Scriptable Options
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
}