I'm using chartjs 3.9 to build a bar chart. I'm trying to get a shadow effect on the bars like this:
I couldn't find how to do this on the documentation. Can someone help me, please?
This are my datasets:
datasets: [
{
label: 'SLP',
data: [23000, 46000, 40000, 41000, 39000, 25000, 45000, 40500, 41000],
backgroundColor: gradientBg21,
borderRadius: 9,
categoryPercentage: 0.8,
barPercentage: 0.8
},
{
label: 'AXS',
data: [19000, 22000, 19000, 42000, 39500, 18000, 22000, 18000, 42000],
backgroundColor: gradientBg31,
borderRadius: 9,
categoryPercentage: 0.8,
barPercentage: 0.8
}
]
Here's my chart: JsFiddle
import { Bar } from 'react-chartjs-2';
import {
BarElement,
CategoryScale,
Chart as ChartJS,
Legend,
LinearScale,
Title,
Tooltip,
TooltipItem,
} from 'chart.js';
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);
const shadowPlugin = [{
id: 'shadow',
beforeDraw: (chart: ChartJS<'bar', number[], unknown>) => {
const { ctx } = chart;
const _fill = ctx.fill;
ctx.fill = function () {
ctx.save();
ctx.shadowColor = 'red';
//ctx.shadowColor = 'rgba(12,77, 229, 0.2)';
ctx.shadowBlur = 8;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 2;
_fill.apply(this, arguments as any);
ctx.restore();
};
},
}];
<Bar
height={(BAR_THICKNESS + 28) * data.length + TICKS_PADDING}
width={chartRefContainer?.current?.offsetWidth || undefined}
ref={chartRef}
options={options}
data={dataWithGradient}
plugins={shadowPlugin}
/>
result
Related
I'm making a line chart in sveltekit, using the svelte-chartjs package. The data for this chart is a set of timestamps, so I have to use a date adapter for chart.js.
The adapter I'm using is chartjs-adapter-luxon, and it seems to work, it spaces everything out correctly, except it has the wrong labels.
The labels are all showing one specific day: Jan 20, 1970, but my data has timestamps from several weeks in it, and none of them are from 1970. It's also suspicious that they're so close to the Unix epoch.
I can't figure it out, please help
My relevant code:
<script>
export let data
import { Line } from 'svelte-chartjs';
import 'luxon'
import 'chartjs-adapter-luxon'
import {
Chart,
Tooltip,
Legend,
BarElement,
CategoryScale,
LinearScale,
LineElement,
PointElement,
TimeScale,
} from 'chart.js';
Chart.register(
Tooltip,
Legend,
BarElement,
CategoryScale,
LineElement,
PointElement,
LinearScale,
TimeScale,
);
let graphdata = graph()
let graphoptions = {
scales: {
x: {
type: 'time',
time: {
unit: 'day',
displayFormats: {
second: 'MMM d, yyyy'
}
},
adapters: {
date: {
zone: 'UTC+6'
}
},
}
},
responsive: true,
maintainAspectRatio: false,
}
function graph() {
if (data.graph) {
let labels = []
for (let i = 0; i < data.graph.timestamp.length; i++) {
let timestamp = data.graph.timestamp[i]
const myDateTime = new Date(timestamp * 1000)
const myDateTimeISO = myDateTime.toISOString()
labels.push(new Date(myDateTimeISO))
}
let graphdata = {
labels: data.graph.timestamp,
datasets: [
{
label: 'Followers',
data: data.graph.followers,
backgroundColor: ["rgb(30 58 138 / 1)"],
borderWidth: 2,
borderColor: "#e5e7eb",
hoverBackgroundColor: ["rgb(30 58 138 / 1)"],
hoverBorderColor: "#e5e7eb",
},
{
label: 'Following',
data: data.graph.following,
backgroundColor: ["#818cf8"],
borderWidth: 2,
borderColor: "#e5e7eb",
hoverBackgroundColor: ["#818cf8"],
hoverBorderColor: "#e5e7eb",
},
{
label: 'Posts',
data: data.graph.posts,
backgroundColor: ["rgb(253 224 71 / 1)"],
borderWidth: 2,
borderColor: "#e5e7eb",
hoverBackgroundColor: ["rgb(253 224 71 / 1)"],
hoverBorderColor: "#e5e7eb",
},
],
};
return graphdata
} else {
return null
}
}
</script>
<Line data={graphdata} options={graphoptions} />
I want to implement a simple Gantt Chart using 'react-chartjs-2'.
I want Courses on Y axis, and Time-slots(HH:mm) in X axis. I also want to set Duration of each entry. I did This -
import React from 'react'
import UniNavbar from './UniNavbar';
import {UserData} from '../components/Chart/Data';
import { Bar } from 'react-chartjs-2';
import 'chartjs-adapter-date-fns';
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
TimeScale,
BarElement,
Title,
Tooltip,
Legend,
} from 'chart.js';
ChartJS.register(
TimeScale,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend
);
export const options = {
indexAxis: 'y',
elements: {
bar: {
},
},
scales: {
x:{
min: '00:00',
type: 'time',
time:{
unit:'hour',
displayFormats: {
hour: 'HH:mm'
},
},
},
},
responsive: true,
plugins: {
legend: {
position: 'right',
},
title: {
display: true,
text: 'Chart.js Horizontal Bar Chart',
},
},
};
const labels = ['CSE150', 'CSE331', 'IPE120D', 'CSE333', 'PHY203D', 'BUS201D', 'EEE303D'];
export const data = {
labels,
datasets: [
{
label: 'Dataset 1',
data: [
['02:00','00:40'],
['02:00','00:40'],
['02:00','00:40'],
['02:00','00:40'],
['02:00','00:40'],
['02:00','00:40'],
],
backgroundColor: [
'rgba(255, 26, 104, 0.2)',
],
borderColor: [
'rgba(255, 26, 104, 1)',
],
barPercentage: 0.2,
},
],
};
const Schedules = () => {
return (
<div>
<UniNavbar/>
Schedules
<Bar options={options} data={data} />
</div>
)
}
In each data, I want to enter starttime and endtime, according to that, I want entries on the chart.
Is my data definition wrong here?
There was no output in the chart of each data entry(HH: mm). What am I doing wrong here?
I'm currently building a realtime chart to test it out. I wrote something to receive data as an example, but it doesn't work. Below is my code.
import { StreamingPlugin, ChartStreaming } from 'chartjs-plugin-streaming'
import {
Chart as ChartJS,
LinearScale,
CategoryScale,
RadialLinearScale,
BarElement,
PointElement,
LineElement,
ArcElement,
Legend,
Tooltip
} from 'chart.js'
import {
Chart,
Line,
Pie,
Doughnut,
Radar,
getDatasetAtEvent,
getElementAtEvent,
getElementsAtEvent,
} from 'react-chartjs-2'
ChartJS.register(
LinearScale,
RadialLinearScale,
CategoryScale,
BarElement,
PointElement,
LineElement,
ArcElement,
StreamingPlugin,
Legend,
Tooltip
)
const data =
{
datasets :
[
{
label : "real",
backgroundColor : "rgb(255, 99, 132)",
borderColor: "rgb(255, 99, 132)",
fill : false,
lineTension : 0,
borderDash: [8,4],
data : [],
showLine: true,
}
]
}
console.log(data.datasets[0].data)
const RealTime_ChartTest_options =
{
elements :
{
line :
{
tesion: 0.5
}
},
scales :
{
xAxes: [
{
type: "realtime",
realtime: {
onRefresh: function () {
data.datasets[0].data.push({
x: Date.now(),
y: Math.random() * 100
}
);
},
delay: 300,
refresh: 300
}
}
],
yAxes: [
{
scaleLabel: {
display: true,
fontFamily: "Arial",
labelString: "Moment",
fontSize: 20,
fontColor: "#6c757d"
},
ticks: {
max: 100,
min: 0
}
}
]
}
}
const App = ()=>
{
retrun(
<Line data={data} options={RealTime_ChartTest_options} />
)
}
As a result, the Y-axis and labels are displayed correctly, but the values are not stored in the data in real time and the graph is not drawn.
What am I doing wrong in the code?
This is because your scale config is wrong, you are using V2 syntax while using V3, changing it to this should resolve the issue:
scales: {
x: {
type: "realtime",
realtime: {
onRefresh: function() {
data.datasets[0].data.push({
x: Date.now(),
y: Math.random() * 100
});
},
delay: 300,
refresh: 300
}
},
y: {
max: 100,
min: 0
}
}
For all changes please read the migration guide
In react-chartjs-2
In Line chart every grid should have different background colors.
Is this achievable with this library?
This is how LineChart should looks:
This is my Code/configuration:
const options = {
responsive: true,
scales: {
y: {
grid: {
backgroundColor: [
'rgba(36, 206, 0, 0.8)',
'rgba(255, 255, 0, .8)',
'rgba(255, 162, 0, 0.8)',
'rgba(36, 206, 0, 0.8)',
],
},
};
Thanks for reading.
You can use an inline plugin to achieve it:
var GradientBgPlugin = {
beforeDraw: function(chart, args, options) {
const ctx = chart.ctx;
const canvas = chart.canvas;
const chartArea = chart.chartArea;
// Chart background
var gradientBack = canvas.getContext("2d").createLinearGradient(0, 250, 0, 0);
gradientBack.addColorStop(0, "rgba(213,235,248,1)");
gradientBack.addColorStop(0.16, "rgba(213,235,248,1)");
gradientBack.addColorStop(0.17, "rgba(226,245,234,1)");
gradientBack.addColorStop(0.25, "rgba(226,245,234,1)");
gradientBack.addColorStop(0.26, "rgba(252,244,219,1)");
gradientBack.addColorStop(0.5, "rgba(252,244,219,1)");
gradientBack.addColorStop(0.51, "rgba(251,221,221,1)");
gradientBack.addColorStop(1, "rgba(251,221,221,1)");
ctx.fillStyle = gradientBack;
ctx.fillRect(chartArea.left, chartArea.bottom,
chartArea.right - chartArea.left, chartArea.top - chartArea.bottom);
}
};
Than just include it in your Chart options:
plugins: [GradientBgPlugin]
The result should be similar to this JSFiddle.
EDIT
For Reach Charts JS 2, you need small changes in setup. You define plugin this way:
const plugins = [{
beforeDraw: function(chart) {
const ctx = chart.ctx;
const canvas = chart.canvas;
const chartArea = chart.chartArea;
// Chart background
var gradientBack = canvas.getContext("2d").createLinearGradient(0, 250, 0, 0);
gradientBack.addColorStop(0, "rgba(213,235,248,1)");
gradientBack.addColorStop(0.16, "rgba(213,235,248,1)");
gradientBack.addColorStop(0.17, "rgba(226,245,234,1)");
gradientBack.addColorStop(0.25, "rgba(226,245,234,1)");
gradientBack.addColorStop(0.26, "rgba(252,244,219,1)");
gradientBack.addColorStop(0.5, "rgba(252,244,219,1)");
gradientBack.addColorStop(0.51, "rgba(251,221,221,1)");
gradientBack.addColorStop(1, "rgba(251,221,221,1)");
ctx.fillStyle = gradientBack;
ctx.fillRect(chartArea.left, chartArea.bottom,
chartArea.right - chartArea.left, chartArea.top - chartArea.bottom);
}
}];
Than you plug it this way:
<Line data={data} plugins={plugins} />
You can see it working fine on CodeSandbox here.
You can write a custom inline plugin, that draws the colors on the chart Area. In the options section you can put an object with all the sections you want, from where to where and which color they need to be
Example:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [100, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
plugins: {
backgrounds: {
hbars: [{
from: 28,
to: 100,
color: "rgb(195, 230, 195)"
},
{
from: 20,
to: 28,
color: "rgb(230, 220, 195)"
},
{
from: 0,
to: 20,
color: "rgb(230, 195, 195)"
}
]
}
}
},
plugins: [{
id: 'backgrounds',
beforeDraw: (chart, args, options) => {
const {
ctx,
chartArea,
scales: {
y
}
} = chart;
options.hbars.forEach((hBar) => {
ctx.save();
ctx.fillStyle = hBar.color;
ctx.fillRect(chartArea.left, y.getPixelForValue(hBar.from), chartArea.right - chartArea.left, y.getPixelForValue(hBar.to) - y.getPixelForValue(hBar.from));
ctx.restore();
})
}
}]
}
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.2.0/chart.js"></script>
</body>
Detailed explanation can be found here: https://medium.com/#omi10859/alternative-background-lines-in-chartjs-a626ce4d3bcb
We can use annotaion plugin with chartjs to create custom elements.
we can use annotation plugin to do this
import annotationPlugin from "chartjs-plugin-annotation";
import {Chart} from 'chart.js';
Chart.register(annotationPlugin);
this code will add a box to our chart
{
type: 'box', #type of draw
drawTime: 'beforeDraw', #this will decide background or foreground
yMin: 5, #value min on y axis
yMax: 10, #value max on y axis
borderColor: 'rgb(242, 244, 248, 0.9)', #border color of the box
borderWidth: 1, #boarder width for box
backgroundColor: '#F2F4F8', #colour of the box
}
# add option while rendering
const options = {
plugins: {annotation: {annotations: background_annotation}
}
this code render this
I am trying to make a line chart using Chart.js in React.
I did not use DOM to create and reach canvas.
I can arrange the background color but I just want to make it as gradient. How can I do that?
My codes below:
import React from "react";
import { Line } from "#reactchartjs/react-chart.js";
const data = {
labels: ["day1", "day2", "day3", "day4", "day5", "day6"],
datasets: [
{
label: "Your BMI",
data: [28.3, 28, 27, 27.6, 25, 25.6],
fill: true,
backgroundColor: "rgba(10,10,10,.2)",
borderColor: "rgba(152,222,217,0.2)"
}
]
};
const options = {
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
}
};
const LineChart = () => (
<>
<Line data={data} options={options} />
</>
);
export default LineChart;
output
You can use the canvas "createLinearGradient" method.
Docs:
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createLinearGradient,
https://developer.mozilla.org/en-US/docs/Web/API/CanvasGradient/addColorStop
Example: https://codepen.io/alexgill/pen/MWbjXOP
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var gradient = ctx.createLinearGradient(0, 0, 0, 400);
gradient.addColorStop(0, 'rgba(10,10,10,.2)');
gradient.addColorStop(1, 'rgba(255,255,255,1)');
const data = {
labels: ["day1", "day2", "day3", "day4", "day5", "day6"],
datasets: [
{
label: "Your BMI",
data: [28.3, 28, 27, 27.6, 25, 25.6],
backgroundColor : gradient,
borderColor: "rgba(152,222,217,0.2)"
}
]
};