Double labels on x axis in chart.js - javascript

I am using chart.js with react-chart-2 in react , but i got double labels below x axis how can i prevent it .
import 'chartjs-adapter-moment';
import moment from 'moment';
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,enter image description here
LineElement,
Title,
Tooltip,
Legend,
TimeScale,
} from 'chart.js';
import type { ChartData, ChartOptions } from 'chart.js';
import { Line } from 'react-chartjs-2';
import zoomPlugin from 'chartjs-plugin-zoom';
import { useRef } from 'react';
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
TimeScale,
LineElement,
Title,
Tooltip,
Legend,
zoomPlugin
);
const dump = [
{
time: 1675056240000,
soc: 62,
},
{
time: 1675056270000,
soc: 62,
},
{
time: 1675056300000,
soc: 62,
},
{
time: 1675056330000,
soc: 62,
},
{
time: 1675056360000,
soc: 62,
},
];
let lables: number[] = [];
let values: number[] = [];
dump.map((x, i) => {
lables.push(x.time);
values.push(x.soc);
});
const data: ChartData<'line'> = {
labels: lables,
datasets: [
{
label: 'Soc',
data: values,
backgroundColor: '#03c782',
borderColor: '#03c782',
borderWidth: 1,
},
],
};
export default function Main() {
const lineGraphRef = useRef<ChartJS<'line', number[], string>>(null);
const options: ChartOptions<'line'> = {
responsive: true,
animation: false,
scales: {
y: {
ticks: {
color: 'white',
},
type: 'linear',
display: true,
position: 'left',
},
xAxis: {
type: 'time',
ticks: {
major: {
enabled: true, // <-- This is the key line
},
maxRotation: 45,
minRotation: 45,
maxTicksLimit: 12,
color: 'white',
},
display: true,
},
},
datasets: {
line: {
pointRadius: 0, // disable for all `'line'` datasets,
showLine: true,
},
},
hover: {
mode: 'x',
// intersect:false,
},
onHover: (e: any) => {
if (lineGraphRef !== null && lineGraphRef.current !== null) {
lineGraphRef.current.clear();
lineGraphRef.current.draw();
const y = e.y;
const topY = lineGraphRef.current.scales.y.top;
const bottomY = lineGraphRef.current.scales.y.bottom;
// console.log(
// moment(
// lineGraphRef.current.scales.xAxis.getValueForPixel(e.x)
// ).format('MMM Do YYYY, h:mm:ss a')
// );
let ctx = e.chart.ctx;
ctx.save();
ctx.beginPath();
ctx.moveTo(e.x, 0);
ctx.lineTo(e.x, bottomY);
ctx.lineWidth = 1;
ctx.strokeStyle = '#FFAB50';
ctx.stroke();
ctx.restore();
}
},
plugins: {
legend: {
labels: {
color: 'white',
boxWidth: 13,
},
},
tooltip: {
enabled: false,
//intersect: false,
external: (context) => {
// console.log("context", context);
},
},
zoom: {
zoom: {
// wheel: {
// enabled: true
// },
drag: {
enabled: true,
threshold: 10,
},
mode: 'x',
},
},
},
};
return (
<Line
options={options}
data={data}
ref={lineGraphRef}
/>
);
}
I have tried the display false in the xAxis but it hide upper labels that i need . I want to remove lower labels . I have tries many things but not able to remove them. Can anyone explain why there are two rows for labels.
Here I am providing code sandbox link for the same
https://codesandbox.io/s/gifted-cache-6i3lqv?file=/src/styles.css

I got the answer , in documentation it says we can use any variable for axis but it start from x for X-axis and from y for Y-axis. But it gives unexpected results when only one parameter chart. If there is single axis chart than we have to use x and only.
scales: {
y: {
ticks: {
color: 'white',
},
type: 'linear',
display: true,
position: 'left',
},
x: { /// change xAxix to only x
type: 'time',
ticks: {
major: {
enabled: true, // <-- This is the key line
},
maxRotation: 45,
minRotation: 45,
maxTicksLimit: 12,
color: 'white',
},
display: true,
},
},

Related

How to use Real time chart in react?

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

Show x axis label on top of stacked bar and custom tooltip on chart js

I want to show the total value and x axis label on top of my stacked bar chart so it look like this
but right now, i'm only can show the total value, i don't know how to add the x axis label, so far mine look like this
i'm also want to custom my tooltip to look like this
Here's my code:
export default {
name: 'BarAllYear',
data() {
return {
BarAllYearData,
};
},
mounted() {
const ctx = document.getElementById('bar-all-year').getContext('2d');
const BarChart = {
type: 'bar',
data: this.BarAllYearData,
plugins: [ChartDataLabels],
options: {
borderWidth: 1,
responsive: true,
plugins: {
legend: {
display: false,
},
tooltip: {
xAlign: 'center',
yAlign: 'bottom',
backgroundColor: '#FFF',
displayColors: false,
titleFont: {
size: 20,
},
bodyFont: {
size: 18,
},
titleColor(tooltipItem) {
const titleLabelColor = tooltipItem.tooltip.labelColors[0].backgroundColor;
return titleLabelColor;
},
bodyColor() {},
},
datalabels: {
color: '#666666',
align: 'top',
anchor: 'end',
offset: 1,
formatter(value, context) {
const sumValue = context.chart.config.data.datasets.map((datapoint) => datapoint.data[context.dataIndex]);
function totalSum(total, datapoint) {
return total + datapoint;
}
const sum = sumValue.reduce(totalSum, 0);
return `${sum}`;
},
font: {
weight: 'bold',
size: 16,
},
},
},
scales: {
x: {
ticks: {
color: 'black',
font: {
weight: 'bold',
size: 16,
},
},
stacked: true,
},
y: {
ticks: {
stepSize: 1,
font: {
size: 18,
},
},
stacked: true,
},
},
layout: {
padding: 20,
},
},
};
/* eslint-disable no-new */
new Chart(ctx, BarChart);
},
};
and this is the BarAllYearData:
const DonutAllYearData = {
labels: [
'Butuh Perhatian Khusus',
'Dalam Proses',
'Selesai',
],
datasets: [{
label: 'My First Dataset',
data: [16, 3, 5],
backgroundColor: [
'#FF7A00',
'#23C4DB',
'#666666',
],
hoverOffset: 4,
}],
};
export default DonutAllYearData;
I'm using vue 3 by the way.
Anyway, thanks for the help

how to only show zero grid axes at center and hide all other gridlines in chart js

I am trying to hide all the grid lines on y axis except the middle line which shows the positive values above x axis and negative below y axis.
I found out that zeroWidthLine option isnt avaiable in version 3 anymore.I am attching the js fiddle link in comment.
You can use scriptable options for the grid color to achieve this:
Chart.register(ChartDataLabels);
chartLabels = ['2018', '2019', '2020', 'TTM']
equityToAssetData = [4.32, -5.37, 4.73, 4.89, 3.6, ];
var equityToAssetDatasets = {
labels: chartLabels,
datasets: [{
type: 'line',
label: 'Equity to Asset ',
data: equityToAssetData,
backgroundColor: 'rgb(97,207,5)',
borderColor: 'rgb(97,207,5)',
borderWidth: 1.8,
lineTension: 0.4,
pointStyle: 'rectRot'
}]
}
var chartStylingSingle = {
animation: {
duration: 500,
},
responsive: true,
layout: {
padding: 20
},
interaction: {
mode: 'index',
intersect: false
},
elements: {
point: {
hoverRadius: 5
}
},
plugins: {
legend: {
display: false,
},
datalabels: {
borderWidth: 0.5,
color: 'green',
anchor: 'start',
align: 'end',
offset: 6,
formatter: (v, ctx) => {
let label = ctx.chart.data.labels[ctx.dataIndex];
if (label != 'TTM') {
label = ' ' + label;
}
return label + '\n ' + v;
},
font: {
size: 11,
weight: 'bold',
}
}
},
scales: {
y: {
display: true,
grid: {
color: (ctx) => (ctx.tick.value === 0 ? 'rgba(0, 0, 0, 0.1)' : 'transparent')
}
},
x: {
display: true,
grid: {
display: false,
}
}
}
}
var ctx = document.getElementById('equityToAsset').getContext('2d');
var myChart = new Chart(ctx, {
data: equityToAssetDatasets,
options: chartStylingSingle
})
<canvas id="equityToAsset"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.min.js"></script>

Two different x-axes using charts.js and react

I'm trying to create a chart component for weather in React using chart.js. I want two different x-axes with the temp above the chart, and the times below the chart. The data is correct in how I want it, I just want to use two different labels along the top and the bottom of the x-axes. How would I do this?
import React from "react";
import { Line } from "react-chartjs-2";
class WeatherOverview extends React.Component {
constructor(props) {
super(props);
this.state = {
chartData: {
labels: [
"15:00",
"18:00",
"21:00",
"00:00",
"03:00",
"06:00",
"09:00",
"12:00",
], //time
datasets: [
{
data: [18, 19, 18, 16, 15, 15, 16, 17, 18], //temp
},
],
},
};
}
render() {
return (
<div className="chart">
<Line
data={this.state.chartData}
options={{
scales: {
yAxes: [
{
gridLines: {
drawOnChartArea: false,
},
ticks: {
suggestedMin: 13, // lowest from data minus 2/3
display: false,
},
},
],
xAxes: [
{
gridLines: {
drawOnChartArea: false,
},
},
{ position: "top" },
],
},
}}
/>
</div>
);
}
}
export default WeatherOverview;
I want something like the google weather widget -
To match the Google Weather example with values floating over data points, what you really need is a plugin like chartjs-plugin-datalabels.
Install it via npm:
npm install chartjs-plugin-datalabels --save
Import:
import 'chartjs-plugin-datalabels';
And include it in your options object:
plugins: {
datalabels: {
display: true
}
}
This will add data labels on top of your data points. See the documentation for further information on how to customize the data labels.
I've made your chart look like the Google Weather chart with a couple other changes. Here's a full example using your data:
Some of the changes I made include:
Added datalabels plugin
Set colors accordingly
Set pointRadius to 0 on your dataset
Removed your extra X axis
On each axis, set drawBorder: false and tickMarkLength: 0
{
type: 'line',
data: {
labels: ['15:00', '18:00', '21:00', '00:00', '03:00', '06:00', '09:00', '12:00'], //time
datasets: [{
data: [18, 19, 18, 16, 15, 15, 16, 17, 18], //temp
backgroundColor: '#fff5cc',
borderColor: '#fc0',
pointRadius: 0,
}],
},
options: {
scales: {
yAxes: [{
gridLines: {
drawOnChartArea: false,
drawBorder: false,
tickMarkLength: 0,
},
ticks: {
suggestedMin: 13, // lowest from data minus 2/3
display: false
}
}],
xAxes: [{
gridLines: {
drawOnChartArea: false,
drawBorder: false,
tickMarkLength: 0,
},
ticks: {
fontColor: '#bababa',
}
}]
},
legend: {
display: false
},
layout: {
padding: {
top: 20
}
},
plugins: {
datalabels: {
align: 'top',
color: '#bababa',
font: {
weight: 'bold'
},
display: true,
},
},
}
}
This is my approach:
var chartData = {
labels: ['15:00', '18:00', '21:00', '00:00', '03:00', '06:00', '09:00', '12:00'],
datasets: [
{
fillColor: "#FFF5D7",
strokeColor: "#FFCC01",
data: [18, 19, 18, 16, 15, 15, 16, 17, 18]
}
]
};
var ctx = document.getElementById("myChart1").getContext("2d");
var myLine = new Chart(ctx).Line(chartData, {
scaleOverride : true,
scaleSteps : 10,
scaleStepWidth : 3,
scaleStartValue : 0,
showTooltips: false,
onAnimationComplete: function () {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
ctx.fillStyle = this.scale.textColor
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
this.datasets.forEach(function (dataset) {
dataset.points.forEach(function (points) {
ctx.fillText(points.value, points.x, 20);
});
})
}
});
https://jsfiddle.net/MartinGK/u4Lr8gzw/31/
Maybe it will help you get started.
I recommend to continue reading the documentation.

How to display final point value in charts.js

I'm using Charts.js library to display a line graph from data which is constantly updated. Is there a way to display only the final point value at all times? I want it to do this to monitor the added values at all times.
javascript code:
var config2 = {
type: 'line',
data: {
labels: 0,
datasets: [{
label: "No selection",
lineTension: 0,
borderColor: "rgba(222, 44, 31)",
pointBackgroundColor: "#fff675",
fill: false,
data: 0,
}
]
},
options: {
responsive: true,
title: {
display: false,
text: 'Chart.js Time Point Data'
},
scales: {
x: {
type: 'time',
display: true,
scaleLabel: {
display: true,
labelString: 'Date'
},
ticks: {
major: {
enabled: true
},
fontStyle: function(context) {
return context.tick && context.tick.major ? 'bold' : undefined;
},
fontColor: function(context) {
return context.tick && context.tick.major ? '#FF0000' : undefined;
}
}
},
y: {
display: true,
scaleLabel: {
display: true,
labelString: 'value'
}
}
}
}
};
Each time, a new value is available, you can simply remove outdated labels and dataset.data values once a certain limit is reached. This can be done using Array.shift(), which removes the first element from an array. Once these array are updated, you need to invoke chart.update().
var maxValues = 4;
setInterval(() => {
chart.data.labels.push(new Date());
chart.data.datasets[0].data.push(Math.floor((Math.random() * 20) + 1));
if (chart.data.labels.length > maxValues) {
chart.data.labels.shift();
chart.data.datasets[0].data.shift();
}
chart.update();
}, 1000);
For displaying the value on the last added data point, you can use the Plugin Core API. It offers different hooks that may be used for executing custom code. In below runnable code snippet, I use the afterDraw hook to draw text directly on the canvas.
var chart = new Chart('chart', {
type: "line",
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
var iLastValue = chart.data.labels.length - 1;
var lastValue = chart.data.datasets[0].data[iLastValue];
var x = xAxis.getPixelForValue(chart.data.labels[iLastValue]);
var y = yAxis.getPixelForValue(lastValue);
ctx.save();
ctx.textAlign = 'center';
ctx.font = '14px Arial';
ctx.fillStyle = "red";
ctx.fillText('Value: ' + lastValue, x, y - 15);
ctx.restore();
}
}],
responsive: true,
maintainAspectRatio: false,
data: {
labels: [],
datasets: [{
label: "Data",
data: [],
fill: false,
lineTension: 0,
backgroundColor: "white",
borderColor: "red",
}]
},
options: {
layout: {
padding: {
right: 50
}
},
scales: {
xAxes: [{
type: 'time',
ticks: {
source: 'auto'
},
time: {
unit: 'second',
displayFormats: {
second: 'mm:ss'
},
tooltipFormat: 'mm:ss'
},
}],
yAxes: [{
ticks: {
min: 0,
max: 20,
stepSize: 5
}
}]
}
}
});
var maxValues = 4;
setInterval(() => {
chart.data.labels.push(new Date());
chart.data.datasets[0].data.push(Math.floor((Math.random() * 20) + 1));
if (chart.data.labels.length > maxValues) {
chart.data.labels.shift();
chart.data.datasets[0].data.shift();
}
chart.update();
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="chart" height="90"></canvas>

Categories

Resources