I'm trying to implement a line graph through chart js on react, however, whenever my function sets the x and y axis data, it keeps returning a line chart that is vertical with x-axis values at 0.
Here is my code below:
import React, { useEffect, useState } from 'react'
import './LineGraph.css'
import {Line} from "react-chartjs-2"
function LineGraph() {
const [ graphData, setGraphData ] = useState([])
const data = [{x:10, y:20}, {x:15, y:10}, {x:12, y:4}]
const createMockData = () => {
let data = [];
let value = 50;
for(var i = 1; i < 366; i++) {
let date = new Date()
date.setHours(0,0,0,0)
date.setDate(i)
value += Math.round((Math.random() < 0.5 ? 1 : 0) * Math.random() * 10)
data.push({x: value, y:value})
console.log(data)
}
setGraphData(data)
}
useEffect(()=> {
createMockData()
}, [])
return (
<div className="linegraph">
<Line
data={{
datasets: [
{
type: "line",
data: graphData,
backgroundColor: "black",
borderColor: "#5AC53B",
borderWidth: 2,
pointBorderColor: 'rgba(22, 22, 22, 0)',
pointBackgroundColor: 'rgba(0,0,0,0)',
pointHoverBackgroundColor: '#5AC53B',
pointHoverBorderColor: '#000000',
pointHoverBorderWidth: 4,
pointHoverRadius: 6,
}
]
}}
options={{
plugins:{
legend: {
display: false
},
tooltips: {
interaction: {
mode: "index",
intersect: false
}
}
},
scales: {
x: [
{
type: "time",
time: {
format: "MM/DD/YY",
tooltipFormat: "ll",
},
ticks: {
display: false,
}
},
],
y: {
ticks: {
display: false
}
}
}
}}
/>
</div>
)
}
export default LineGraph
I'm using react-charts-2, latest version 3.5.1. I think the main problem is with my x-axis because my y-coordinates all show up, which is why the line is vertical, however, all the x values are 0, so their is not diagonal or correlated uphill/downhill line. Please help me resolve this
You are defining the x axis scale as an array , this is v2 syntax. All scales have to be defined as an object. So at the moment chart.js sees your scale as a category scale instead of a time scale and it cant handle number inputs as labels.
To fix this you will need to change your scale like so:
scales: {
x: {
type: "time",
time: {
format: "MM/DD/YY",
tooltipFormat: "ll",
},
ticks: {
display: false,
}
},
,
}
For using the timescale you will also need a date adapter, since you are using js dates you can just use the normal datefns adapter like so:
npm install date-fns chartjs-adapter-date-fns --save
import {Line} from "react-chartjs-2"
import 'chartjs-adapter-date-fns';
Related
I'm trying to make the below graph using chart js in React 18:
So far I've written the below code and tried to limit the x and y axes through maxTicksLimit, but I suppose I'm missing something here:
import "./styles.css";
import { data } from "./data";
import { Line } from "react-chartjs-2";
import moment from "moment";
export default function App() {
const series = data.cpu.values.map((item) => item[1]);
const labels = data.cpu.values.map((item) =>
moment(item[0] * 1000).format("hh:mm:ss")
);
const options = {
responsive: true
};
const datax = {
labels,
datasets: [
{
label: "CPU USAGE",
data: series,
borderColor: "rgb(255, 99, 132)",
backgroundColor: "rgba(255, 99, 132, 0.5)",
pointRadius: 0,
fill: true
}
],
scales: {
xAxes: [
{
ticks: {
maxTicksLimit: 9
}
}
],
yAxes: [
{
ticks: {
maxTicksLimit: 4
}
}
]
}
};
return (
<div className="App">
<Line options={options} data={datax} />
</div>
);
}
I get the below output:
I would appreciate any help CodeSandBox
To solve your problem, define options as follows.
const options = {
responsive: true,
scales: {
x: {
ticks: {
maxTicksLimit: 9
}
},
y: {
ticks: {
maxTicksLimit: 4
}
}
}
};
For further information, consult Tick Configuration Options from the Chart.js documentation.
Please take a look at your amended CodeSandbox and see how it works.
I am trying to plot stock data, but there are gaps in the graph where data for these time periods don't exist. How do I remove these gaps? I found that there is an update_xaxes function but I'm not sure how to apply it to my case.
My code:
import React, { useState, Component, useEffect } from "react";
import Plot from 'react-plotly.js';
export const Chart = () => {
return (
<div>
<Plot
data={[
{
x: data['dates'],
y: data['open_price'],
type: 'scatter'
}
]}
layout={{
autosize: false,
width: 1500,
height: 800,
xaxis: {
color: 'red',
rangebreaks: {
bounds: ["sat", "mon"],
values: ["2015-12-25", "2016-01-01"],
bounds: [17, 9], pattern: "hour"
}
}
}}
/>
</div>
)
}
react-ploty allows configuring the underlying ploty configuration through props. The data props you're already using accepts the same Traces Object than regular ploty. Therefore you can use rangebreaks as suggested by #r-beginners to achieve the desired effect.
xaxis: {
color: 'red',
rangebreaks: [
{ bounds: ["sat", "mon"] },
{
values: ["2019-12-25"]
},
{ bounds: [17, 9], pattern: "hour" }
]
}
I fixed it by making rangebreaks an array.
I am working on the latest version of Chart.js, i.e., v3.7.1. However, I notice that most of the configurations have been changed from those of version 2.x. My problem is that I would like to draw a vertical line everytime there is a mouseover the chart, but not necessary having the mouse on the data points, but can be above or below, as long as the mouse point is in line with a data point, a verical line is drawn. This is clearly illustrated by this code on JSFiddle. I tried this Solution on this platform but it fails to work since it is based on ChartJS v2.6.0. Anyone with an idea of doing this? Here are my codes:
LineChart.js
import React from "react";
import Chart from 'chart.js/auto';
import { Line } from "react-chartjs-2";
import 'chartjs-adapter-moment';
const newOptions = {
responsive: true,
plugins: {
responsive: true,
title: {
display: true,
text: 'Weekly Logs'
},
},
scales: {
x: {
type: "time",
time: {
displayFormats: {
'day': 'dddd'
}
}
}
},
interaction: {
mode: "index",
axis: 'y'
}
};
const LineChart = ({ dataChart }) => {
return <Line
data={dataChart} options={newOptions}
/>;
};
export default LineChart;
You can use a custom plugin for this:
const plugin = {
id: 'corsair',
afterInit: (chart) => {
chart.corsair = {
x: 0,
y: 0
}
},
afterEvent: (chart, evt) => {
const {
chartArea: {
top,
bottom,
left,
right
}
} = chart;
const {
x,
y
} = evt.event;
if (x < left || x > right || y < top || y > bottom) {
chart.corsair = {
x,
y,
draw: false
}
chart.draw();
return;
}
chart.corsair = {
x,
y,
draw: true
}
chart.draw();
},
afterDatasetsDraw: (chart, _, opts) => {
const {
ctx,
chartArea: {
top,
bottom,
left,
right
}
} = chart;
const {
x,
y,
draw
} = chart.corsair;
if (!draw) {
return;
}
ctx.lineWidth = opts.width || 0;
ctx.setLineDash(opts.dash || []);
ctx.strokeStyle = opts.color || 'black'
ctx.save();
ctx.beginPath();
if (opts.vertical) {
ctx.moveTo(x, bottom);
ctx.lineTo(x, top);
}
if (opts.horizontal) {
ctx.moveTo(left, y);
ctx.lineTo(right, y);
}
ctx.stroke();
ctx.restore();
}
}
Chart.register(plugin)
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'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'orange'
}
]
},
options: {
plugins: {
corsair: {
horizontal: false,
vertical: true,
color: 'red',
dash: [],
width: 2
}
}
},
}
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>
For you to use this in react, you only need the Chart.register line like so:
import React from "react";
import Chart from 'chart.js/auto';
import { Line } from "react-chartjs-2";
import 'chartjs-adapter-moment';
const plugin = {
// Plugin code, see stack snipet above
}
Chart.register(plugin)
I am trying to add a drop shadow for one specific line in the chart.
This helped somehow but was not enough:
https://stackoverflow.com/a/33124653/4500286
I am using the package of "react-chartjs-2": "2.7.6" in a react project.
What I came up with, adds a drop shadow for all the lines .. I can't seem to find a way to add it per dataset.
I have prepended this code to the componentWillMount that adds a drop shadow to all the lines (which isn't what I want)
Chart.pluginService.register({
id: 'dropShadow',
afterDraw: function (chart, easing) {
console.log(chart);
let originial = this;
const { ctx } = chart;
let originalStroke = ctx.stroke;
ctx.stroke = function () {
ctx.save();
ctx.shadowColor = '#C4A4BF';
ctx.shadowBlur = 7;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
originalStroke.apply(this, arguments)
ctx.restore();
}
}
});
This is a mini sample of the code I'm tried to build
import React from 'react';
import mediaPlanner from '../api/mediaPlanner';
import {Line,Chart} from "react-chartjs-2";
class Revenue extends React.Component{
constructor(props){
super(props);
this.state = {
data: {}
}
this.graphDataSample = {
forecastRevenue: ["3000", "3500", "3500"]
revenue: ["1000", "3000", "5000"]
timestamp: ["2019-02-01", "2019-02-02", "2019-02-03"]
}
// get up the options of the graph
this.options = {
maintainAspectRatio: false,
legend: {
display: true,
position: 'bottom',
labels: {
fontColor: 'rgb(255,255,255)',
}
},
tooltips: {
backgroundColor: "#f5f5f5",
titleFontColor: "#333",
bodyFontColor: "#666",
bodySpacing: 4,
xPadding: 12,
mode: "nearest",
intersect: 0,
position: "nearest"
},
responsive: true,
scales: {
yAxes: [
{
barPercentage: 1.6,
gridLines: {
drawBorder: false,
color: "rgba(29,140,248,0.0)",
zeroLineColor: "transparent"
},
ticks: {
suggestedMin: 60,
suggestedMax: 125,
padding: 20,
fontColor: "#9a9a9a"
}
}
],
xAxes: [
{
barPercentage: 1.6,
gridLines: {
drawBorder: false,
color: "rgba(29,140,248,0.1)",
zeroLineColor: "transparent"
},
ticks: {
padding: 20,
fontColor: "#9a9a9a"
}
}
]
}
};
}
componentWillMount = () => {
// supposed to make an api call to get the data returned
// by graphDataSample
// adds the drop shadow to both revenue and forecast revenue
// I only want to add it to the forecast revenue
Chart.pluginService.register({
id: 'dropShadow',
afterDraw: function (chart, easing) {
console.log(chart);
let originial = this;
const { ctx } = chart;
let originalStroke = ctx.stroke;
ctx.stroke = function () {
ctx.save();
ctx.shadowColor = '#C4A4BF';
ctx.shadowBlur = 7;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
originalStroke.apply(this, arguments)
ctx.restore();
}
}
});
this.setState({data: function(canvas){
return {
labels: this.graphDataSample.timestamp, // X-axis
datasets: [
{
fill: false,
borderColor: "#6C6C74",
borderWidth: 3,
borderDash: [],
borderDashOffset: 0.0,
pointBackgroundColor: "#6C6C74",
pointHoverRadius: 0,
pointHoverBorderWidth: 10,
pointBorderWidth: 0,
steppedLine: false,
pointRadius: 0,
label: "Revenue ($)",
data: this.graphDataSample.revenue, // Y-axis
},
{
fill: false,
borderColor: "red",
borderWidth: 3,
borderDash: [],
borderDashOffset: 0.0,
pointBackgroundColor: "red",
pointHoverRadius: 0,
pointHoverBorderWidth: 10,
pointBorderWidth: 0,
steppedLine: false,
pointRadius: 0,
label: "Forecast Revenue ($)",
data: this.graphDataSample.forecastRevenue, // Y-axis
}
]
};
}});
}
render() {
return (
<Line
data={this.state.data}
options={this.options}
/>
);
}
}
export default Revenue;
As said the expected is to add a drop shadow to one line in my case is for the forecast revenue and not the revenue
That's a screenshot https://drive.google.com/file/d/1LjLyXEPGlgqlE1AziUQdf0GZJptwVEyf/view?usp=sharing
I'm trying to create a linechart, using react-chartjs-2, that has a vertical line when hovering over the datapoints in the chart. Like in this picture below:
Chart requirements
I tried using the chartjs-plugin-annotation plugin, but with mixed results. I managed to create a static line, not understanding how or why it works. How should I achieve this? Am I onto something?
const data = {
labels: [...week(d)],
datasets: [
{
...
data: [10000, 9500, 7000, 4500, 2500, 1500, 500, 0],
}
]
};
var line = [{
type: "line",
mode: "vertical",
// ???
scaleID: "y-axis-0",
value: -20000,
borderColor: "#2984c5",
borderWidth: 1,
}];
const options = {
tooltips: {
xPadding: 20,
yPadding: 10,
displayColors: false,
bodyFontSize: 16,
bodyFontStyle: 'bold',
},
annotation: {
annotations: line,
},
scales: {
yAxes: [{
gridLines: {
drawBorder: false,
tickMarkLength: 0,
},
ticks: {
fontSize: 14,
padding: 15,
max: data.maxY,
min: 0,
maxTicksLimit: 6,
fontColor: "#485465"
}
}],
xAxes: [{
ticks: {
padding: 5,
fontSize: 14,
fontColor: "#485465",
},
gridLines: {
display: false,
},
},
],
},
responsive: false,
}
I have my full code available here: https://codesandbox.io/s/y28mk3rn4z
In case someone needs it for "react-chartjs-2": "^4.0.1". This one worked for me based on previous answers:
import { Chart } from 'chart.js';
import { Line } from 'react-chartjs-2';
Chart.register(
{
id: 'uniqueid5', //typescript crashes without id
afterDraw: function (chart: any, easing: any) {
if (chart.tooltip._active && chart.tooltip._active.length) {
const activePoint = chart.tooltip._active[0];
const ctx = chart.ctx;
const x = activePoint.element.x;
const topY = chart.scales.y.top;
const bottomY = chart.scales.y.bottom;
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 2;
ctx.strokeStyle = '#e23fa9';
ctx.stroke();
ctx.restore();
}
}
}
);
.
.
.
<Line
options={{
...options,
interaction: {
mode: 'index',
intersect: false,
}}}
data={data}
/>
The below answer is correct it only needs some tweaks, Thanks Jordan.
Chart.pluginService.register({
afterDraw: function(chart, easing) {
if (chart.tooltip._active && chart.tooltip._active.length) {
const activePoint = chart.controller.tooltip._active[0];
const ctx = chart.ctx;
const x = activePoint.tooltipPosition().x;
const topY = chart.scales['y-axis-0'].top;
const bottomY = chart.scales['y-axis-0'].bottom;
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 2;
ctx.strokeStyle = '#e23fa9';
ctx.stroke();
ctx.restore();
}
}
});
In the chart options we need to add the below config to display the line on near by hover.
tooltips: {
mode: 'index',
intersect: false
},
hover: {
mode: 'index',
intersect: false
}
PS: if there are multiple chart plotted together then above piece of code might cause problems. if we want to have this effect on a specific chart(e.g line) then we can add the below condition.
if (
chart.tooltip._active &&
chart.tooltip._active.length &&
chart.config.type === 'line'
)
This worked for me, hope this help.
Just looked into this exact thing and this will get you there! It won't do the fills on either side of the line, but it creates the vertical line!
componentWillMount() {
Chart.pluginService.register({
afterDraw: function (chart, easing) {
if (chart.tooltip._active && chart.tooltip._active.length) {
const activePoint = chart.controller.tooltip._active[0];
const ctx = chart.ctx;
const x = activePoint.tooltipPosition().x;
const topY = chart.scales['y-axis-1'].top;
const bottomY = chart.scales['y-axis-1'].bottom;
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 2;
ctx.strokeStyle = '#e23fa9';
ctx.stroke();
ctx.restore();
}
}
});
}
Also for anyone with multiple datasets you can add this into your options for tooltips on all lines at once.
tooltips: {
mode: 'x'
},