ChartJS radar-chart hover text - javascript

How do you add custom text over points in radar charts when you hover over them?
I have been following this tutorial but the data in radar chart are in array formats instead of object as specified here so it doesn't apply.
My current radar chart:
JSfiddle
let dataValues = [100, 120, 80, 100, 90, 110, 100, 100, 100]

If you wait until Chart.js version 3.8 is getting released you can use object notation with radar charts:
let dataValues = [{
value: 100,
text: 'f'
},
{
value: 120,
text: 'd'
},
{
value: 80,
text: 'q'
},
{
value: 100,
text: 'b'
},
{
value: 90,
text: 'z'
},
{
value: 110,
text: 'efw'
},
{
value: 100,
text: 'ffew'
},
{
value: 100,
text: 'ffdddew'
},
{
value: 100,
text: 'fffff'
}
]
const sum = dataValues.reduce((a, b) => a.value + b.value, 0);
const avg = sum / dataValues.length;
const sorted = [...dataValues].sort(function(a, b) {
return a.value - b.value;
})
const data = {
labels: [
'Signal 1',
'Signal 2',
'Signal 3',
'Signal 4',
'Signal 5',
'Signal 6',
'Signal 7',
'Signal 8',
'Signal 9'
],
datasets: [{
label: '9 signals',
data: dataValues,
fill: true,
backgroundColor: 'rgba(210, 203, 203, 0.4)',
borderColor: 'rgb(210, 203, 203, 0.6)',
pointBackgroundColor: function(context) {
const index = context.dataIndex;
const value = context.dataset.data[index].value;
return value < sorted[3].value ? 'blue' :
value < sorted[5].value ? 'green' :
value < sorted[7].value ? 'orange' :
'red';
},
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgb(255, 99, 132)'
}]
};
const config = {
type: 'radar',
data: data,
options: {
plugins: {
tooltip: {
callbacks: {
label: (ctx) => (`${ctx.dataset.label}: ${ctx.parsed.r} ${ctx.dataset.data[ctx.dataIndex].text}`)
}
}
},
parsing: {
key: 'value'
},
elements: {
line: {
borderWidth: 3
},
point: {
pointRadius: 5
}
},
scales: {
r: {
angleLines: {
lineWidth: 2
},
grid: {
circular: true,
lineWidth: 2
}
}
}
}
};
let myChart = new Chart(
document.getElementById('myChart'),
config
);
<div class="chartBox">
<canvas id="myChart"></canvas>
<script src="https://www.chartjs.org/dist/master/chart.js"></script>
</div>

Related

ChartJS Annotation line on stacked bar chart

I cannot get the annotation line to work on a stacked Bar Chart.
Example JS Fiddle: https://jsfiddle.net/cledwyn/rd5q6Lsz/10/
I have the standard Annotation per https://www.chartjs.org/chartjs-plugin-annotation/latest/samples/charts/bar.html
const annotation2 = {
type: 'line',
scaleID: 'x',
borderWidth: 3,
borderColor: 'black',
value: 8,
label: {
rotation: 'auto',
position: 'start',
backgroundColor: 'black',
content: 'Line at x=Label 5',
enabled: true
}
};
but when I stack the bar charts
scales: {
xAxes: { stacked: true },
yAxes: { stacked: true }
},
then the annotation line just goes from one corner of the chart to the other.
When running your JSFiddle, you can see the following warning on the console.
"No scale found with id 'x' for annotation 'annotation2'"
Therefore, changing scales.xAxes to scales.x should solve part of your problem.
scales: {
x: { stacked: true },
y: { stacked: true }
}
You'll further have to add missing labels to data.labels and adjust annotation2.value.
Please take a look at your amended code below and see how it works.
const labels = ['Label 1', 'Label 2', 'Label 3', 'Label 4', 'Label 5'];
const data = {
labels: labels,
datasets: [{
label: 'one',
data: [14, 21, 4, 5, 7],
backgroundColor: 'rgb(255, 99, 132)'
}, {
label: 'two',
data: [1, 3, 2, 4, 5],
backgroundColor: 'rgb(255, 199, 132)'
}, {
label: 'three',
data: [7, 1, 9, 6, 7],
backgroundColor: 'rgb(255, 99, 32)'
}]
};
const annotation2 = {
type: 'line',
scaleID: 'x',
borderWidth: 3,
borderColor: 'black',
value: 4,
label: {
rotation: 'auto',
position: 'start',
backgroundColor: 'black',
content: 'Line at x=Label 5',
enabled: true
}
};
const config = {
type: 'bar',
data: data,
options: {
plugins: {
annotation: {
annotations: {
annotation2,
}
}
},
scales: {
x: {
stacked: true
},
y: {
stacked: true
}
},
},
};
const chart = new Chart('chart', config);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/1.4.0/chartjs-plugin-annotation.min.js"></script>
<canvas id="chart" height="110"></canvas>

Is there anyway to overlap one barchart with another in chart js without stacking them?

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.

chart.js remove lower grid from mixed chart

I have a mixed chart (scatter and line), hence I need 2 xAxis.
There's an extra grid that appears on the bottom of the chart, because that's where the other x axis normally has its labels (I removed them because I don't need them)
I'm trying to get rid of that extra grid, but I can't find how to do it. I've tried to specify the ticks color as white but the grid's still there.
Look at the image, it's that solitary extra grid at the bottom (marked with an horizontal bracket):
This is my code:
const ctx = document.getElementById('myChart');
const labels1 = ['A','R','Fyo','A-MAC','HR','Do','Rs','Dpr','GM','GF','EPK','EPS','Is1','Is2','Is3','FP','INVAR','INVER'];
const lasIs = (ctx, value) => ctx.p0DataIndex > 11 ? value: undefined;
const markedIdxs = [0,5,10,15,20,25,30,35,44, //... and many more];
const markedVals = [0,5,10,15,20,25,30,35,10,// ... and many more];
const data1 = {
labels: labels1,
datasets: [
{
type: 'line',
label: 'Line Dataset',
data: [65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65],
pointRadius: 0,
borderWidth: 1,
borderColor: '#0070C5',
xAxisID: 'x2'
},
{
type: 'line',
label: 'Line Dataset',
data: [50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50],
pointRadius: 0,
borderWidth: 1,
borderColor: '#0070C5',
xAxisID: 'x2'
},
{
type: 'line',
label: 'Line Dataset',
data: [102, 38, 54, 56, 102, 38, 54, 56, 102, 38, 54, 56, 102, 38, 54, 87, 62, 91],
pointStyle: 'circle',
pointRadius: 5,
borderWidth: 2,
borderColor: 'rgba(0, 120, 161,0.5)',
backgroundColor: 'rgba(0, 120, 161,0.5)',
fill: true,
segment: {
borderColor: ctx => lasIs (ctx, 'rgba(0, 168, 172, 0.5'),
backgroundColor: ctx => lasIs (ctx, 'rgba(0, 168, 172, 0.5'),
},
xAxisID: 'x2'
},
{
type: 'scatter',
pointStyle: 'dash',
pointRadius: 6,
borderColor: 'rgba(0, 0, 255,0.2)',
xAxisID: 'x',
data: [{x:1, y:36}, {x:1, y:37}, {x:1, y:39}, {x:1, y:40}, {x:1, y:42}... //and many more]
},
],
};
const multiplos5 = {
id: 'multiplos5',
afterDatasetsDraw(chart, args, options) {
const {ctx} = chart;
ctx.save();
ctx.font = "8px Verdana";
ctx.fillStyle = "#0070C5";
yaSeDibujo=84;
paddLeft = 0;
for (i=0; i < markedIdxs.length; i++) {
if (markedVals[i] < 10)
paddLeft=8;
else
paddLeft=12;
ctx.fillText(markedVals[i], chart.getDatasetMeta(3).data[markedIdxs[i]].x - paddLeft, chart.getDatasetMeta(3).data[markedIdxs[i]].y + 3);
}
}
};
Chart.register(multiplos5);
const myChart = new Chart(ctx, {
data: data1,
options: {
scales: {
x2: { // add extra axes
min: 0,
max: 18,
position: 'bottom',
type: 'category',
ticks: {color: '#0070C5'},
offset: true
},
x: {
min: 1,
max: 18,
ticks: {stepSize: 1, display: false},
offset: true
},
y: {
min: 20,
max: 120,
ticks: {stepSize: 10, color: '#555555', crossAlign: 'start'},
grid:{color:'#f1f1f1', display:true},
},
y2: {
position: 'right',
min: 20,
max: 120,
ticks: {stepSize: 10, color: '#555555'},
grid:{display:false}
},
},
plugins: {
multiplos5,
legend: false,
tooltip: {
displayColors: false,
filter: function (tooltipItem) {
return tooltipItem.datasetIndex == 2;
},
callbacks: {
//title: "el título",
label: function(context) {
let label = labels2[context.dataIndex] + ': ' + context.parsed.y;
return label;
}
}
}
},
},
});
Chart.js version is 3.6.2
Any help/workaround will be really appreciated.
Regards!!
Forgot to mention that the axis I'm talking about is 'x' (xAxisID: 'x')
In your config for the X axis where you set the ticks to display false, if you instead do this in the root of the X scale config it will hide that line so you will get:
scales:{
x: {
display: false,
min: 1,
max: 18,
offset: true
}
}

Placing a bubble chart on top of a stacked area chart causing missing tooltip/label and unwanted color inheritance

The intention is to create something called a 'fever chart'.
I have successfully displayed both charts, however, the bubble chart points are inheriting the color of each areaStyle attribute of the line series that it appears in and also preventing the tooltip and label for the bubble chart points from appearing.
To see what I mean please visit https://echarts.apache.org/examples/en/editor.html?c=area-stack and replace the option object with the following:
grid: {
left: '10%'
},
tooltip: {
trigger: 'item',
formatter: function (params) {
if (params.data.length === 4) {
return `Project: ${params.data[3]}<br />
% Chain Completed: ${Math.round(
params.data[0]
)}<br />
% Buffer Consumed: ${Math.round(params.data[1])}`;
} else return;
}
},
xAxis: [
{
type: 'category',
boundaryGap: false,
show: false
},
{
type: 'value',
min: 0,
max: 100,
show: true,
position: 'bottom'
}
],
yAxis: [
{
type: 'value',
min: 0,
max: 120
}
],
series: [
{
name: 'green',
type: 'line',
color: 'green',
stack: 'Total',
areaStyle: { color: 'green', opacity: 0.8 },
emphasis: {
focus: 'none'
},
data: [0, 80]
},
{
name: 'yellow',
type: 'line',
color: 'yellow',
stack: 'Total',
areaStyle: { color: 'yellow', opacity: 0.8 },
emphasis: {
focus: 'none'
},
data: [20, 20]
},
{
type: 'line',
name: 'red',
color: 'red',
stack: 'Total',
areaStyle: { color: 'red', opacity: 0.8 },
emphasis: {
focus: 'none'
},
data: [80, 0]
},
{
type: 'line',
name: 'black',
color: 'black',
stack: 'Total',
areaStyle: { color: 'black', opacity: 0.8 },
emphasis: {
focus: 'none'
},
data: [120, 120]
},
{
name: 'Bubble',
type: 'scatter',
data: [
[
49.82868330885952, //x
27.606461086637275, //y
1000000000, //size
'project 1' //name
],
[
49.82868330885952, //x
64.606461086637275, //y
100000000, //size
'project 2' //name
]
],
symbolSize: function (data) {
return Math.sqrt(data[2]) / 5e2;
},
xAxisIndex: 1,
emphasis: {
focus: 'item',
scale: true,
label: {
show: true,
formatter: function (param) {
return param.data[3];
},
position: 'top'
}
},
itemStyle: {
shadowBlur: 10,
shadowOffsetY: 5,
opacity: 1,
color: '#000000'
}
}
]
};```
I solved this by setting the scatter series' zLevel attribute to 1.
name: 'Bubble',
type: 'scatter',
zLevel: 1,
data: [
[
49.82868330885952, //x
27.606461086637275, //y
1000000000, //size
'project 1' //name
],
[
49.82868330885952, //x
64.606461086637275, //y
100000000, //size
'project 2' //name
]
],
symbolSize: function (data) {
return Math.sqrt(data[2]) / 5e2;
}```

how to highlight stack bar in ChartJS with onclick

Is it possible to select a column in a stack bar chart with a colored border? Like this
I started from here:
https://jsfiddle.net/sdfx/hwx9awgn/
// Return with commas in between
var numberWithCommas = function(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
var dataPack1 = [40, 47, 44, 38, 27, 31, 25];
var dataPack2 = [10, 12, 7, 5, 4, 6, 8];
var dataPack3 = [17, 11, 22, 18, 12, 7, 5];
var dates = ["SN 1.0.1", "SN 1.0.2", "SN 1.0.3", "SN 1.0.4", "SN 1.0.5", "SN 2.0.0", "SN 2.0.1"];
// Chart.defaults.global.elements.rectangle.backgroundColor = '#FF0000';
var bar_ctx = document.getElementById('bar-chart');
var bar_chart = new Chart(bar_ctx, {
type: 'bar',
data: {
labels: dates,
datasets: [{
label: 'Bad Style',
data: dataPack1,
backgroundColor: "#512DA8",
hoverBackgroundColor: "#7E57C2",
hoverBorderWidth: 0
}, {
label: 'Warning',
data: dataPack2,
backgroundColor: "#FFA000",
hoverBackgroundColor: "#FFCA28",
hoverBorderWidth: 0
}, {
label: 'Error',
data: dataPack3,
backgroundColor: "#D32F2F",
hoverBackgroundColor: "#EF5350",
hoverBorderWidth: 0
}, ]
},
options: {
animation: {
duration: 10,
},
tooltips: {
mode: 'label',
callbacks: {
label: function(tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ": " + numberWithCommas(tooltipItem.yLabel);
}
}
},
scales: {
xAxes: [{
stacked: true,
gridLines: {
display: false
},
}],
yAxes: [{
stacked: true,
ticks: {
callback: function(value) {
return numberWithCommas(value);
},
},
}],
}, // scales legend: {display: true} } // options } );
Yes what you can do is in the onClick as second argument you get an array with all the active elements. So what you can do is loop over each dataset in your chart and see if the index matches one of the list with active elements.
If this is the case you give it a borderWidth of 1, else you put it to 0. After you did this you call chart variable.update();
To make this work you need to remove the hoverBorderWidth of all datasets and give all datasets a borderColor of yellow
Use attribute borderColor with an array and borderWith with and object.
datasets: [
{
label: 'Bad Style',
data: dataPack1,
backgroundColor: "#512DA8",
borderColor: [
'rgb(243, 255, 51)',
'rgb(81,45,168)',
'rgb(243, 255, 51)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
],
borderWidth: {
top: 0,
right: 4,
bottom: 0,
left: 4
},
},
rgb(243, 255, 51) is yellow color.
To change the color, try this:
var borderColor = [
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
];
var bar_ctx = document.getElementById('bar-chart');
var bar_chart = new Chart(bar_ctx, {
type: 'bar',
data: {
labels: dates,
datasets: [
{
label: 'Bad Style',
data: dataPack1,
backgroundColor: "#512DA8",
hoverBackgroundColor: "#7E57C2",
hoverBorderWidth: 0,
borderColor: borderColor,
borderWidth: '4',
},
{
label: 'Warning',
data: dataPack2,
backgroundColor: "#FFA000",
hoverBackgroundColor: "#FFCA28",
hoverBorderWidth: 0,
borderColor: borderColor,
borderWidth: '4',
},
{
label: 'Error',
data: dataPack3,
backgroundColor: "#D32F2F",
hoverBackgroundColor: "#EF5350",
hoverBorderWidth: 0,
borderColor: borderColor,
borderWidth: '4',
},
]
},
options: {
onClick: function(e){
var element = this.getElementAtEvent(e);
borderColor[element[0]._index] = 'rgb(244,140,4)';
this.update();
},
animation: {
duration: 10,
},
tooltips: {
mode: 'label',
callbacks: {
label: function(tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ": " + numberWithCommas(tooltipItem.yLabel);
}
}
},
scales: {
xAxes: [{
stacked: true,
gridLines: { display: false },
}],
yAxes: [{
stacked: true,
ticks: {
callback: function(value) { return numberWithCommas(value); },
},
}],
}, // scales
legend: {display: true}
} // options
}
);

Categories