Dynamic information in chart.js radar chart - javascript

I created a radar chart in chart.js. How do I update the chart with numbers the user specifies with a drop down menu? I created a variable for each input as follows: "spaceScore", "styleScore", "scheduleScore", "supplementScore".
$(document).ready(function(){
"use strict";
new Chart(document.getElementById("radarChart"), {
type: 'radar',
data: {
labels: ["Space", "Style", "Schedule", "Supplement"],
datasets: [
{
label: "Cognizant Baseline",
fill: false,
backgroundColor: "rgba(179,181,198,0.2)",
borderColor: "rgba(179,181,198,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(179,181,198,1)",
data: [1,3,1,2]
}, {
label: "Assessment",
fill: true,
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(255,99,132,1)",
data: ['spaceScore','styleScore','scheduleScore','supplementScore']
}, {
label: "Learner Centricity",
fill: true,
backgroundColor: "rgba(114, 205, 244,0.2)",
borderColor: "rgba(114, 205, 244,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(114, 205, 244,1)",
data: [2,2,2,1]
}
]
},
options: {
title: {
display: false,
},
legend: {
display: false
},
tooltips: {
enabled: false
}
}
});
function getData(){
var radarChart = document.getElementById("radarChart");
var spaceScore = document.getElementById('spaceScore').value();
var styleScore = document.getElementById('styleScore').value;
var scheduleScore = document.getElementById('scheduleScore').value;
var supplementScore = document.getElementById('supplementScore').value;
radarChart.update;
}
});

I added 4 number inputs as an interface to update values. I gave them values ranging from 0 to 3, adapt to your needs. I also added an update button, so that the update happens only when you click it.
If you want specifically drop-down inputs, just replace the number inputs with traditional <select> tags, with <options> matching possible values.
To perform the actual update on the chart you need to first overwrite the old data from the dataset, then call a rerendering of the char-canvas with radarChart.update(). Follow the inline code comments to get an idea of whats happening in code.
$(document).ready(function() {
"use strict";
// hold a radarChart reference for future updates
var radarChart = new Chart(document.getElementById("radarChart"), {
type: 'radar',
data: {
labels: ["Space", "Style", "Schedule", "Supplement"],
datasets: [{
label: "Cognizant Baseline",
fill: false,
backgroundColor: "rgba(179,181,198,0.2)",
borderColor: "rgba(179,181,198,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(179,181,198,1)",
data: [1, 3, 1, 2]
}, {
label: "Assessment",
fill: true,
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(255,99,132,1)",
data: ['spaceScore', 'styleScore', 'scheduleScore', 'supplementScore']
}, {
label: "Learner Centricity",
fill: true,
backgroundColor: "rgba(114, 205, 244,0.2)",
borderColor: "rgba(114, 205, 244,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(114, 205, 244,1)",
data: [2, 2, 2, 1]
}]
},
options: {
title: {
display: false,
},
legend: {
display: false
},
tooltips: {
enabled: false
}
}
});
// click handler of the update button
$('#update').on('click', function() {
getData();
});
function getData() {
// get new user-selected values
var spaceScore = document.getElementById('spaceScore').value;
var styleScore = document.getElementById('styleScore').value;
var scheduleScore = document.getElementById('scheduleScore').value;
var supplementScore = document.getElementById('supplementScore').value;
// update chart dataset with new values
radarChart.data.datasets[0].data[0] = spaceScore;
radarChart.data.datasets[0].data[1] = styleScore;
radarChart.data.datasets[0].data[2] = scheduleScore;
radarChart.data.datasets[0].data[3] = supplementScore;
// redraw chart
radarChart.update();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="inputs">
<input id="spaceScore" type="number" min="0" max="3" value="1" />
<input id="styleScore" type="number" min="0" max="3" value="3" />
<input id="scheduleScore" type="number" min="0" max="3" value="1" />
<input id="supplementScore" type="number" min="0" max="3" value="2" />
<button id="update" type="button">Update</button>
</div>
<canvas id="radarChart" />

Related

Conflict lifecycle Graph.js and firebase data

I'm stuck to display a list of graph from data of a realtime database firebase.
At the moment I can display a list of graph, however I can't get the data of the list : "listData" .
When I change the lifecycle "ngAfterViewInit" by "ngAfterViewChecked", it works for displaying the Graph and the data of listData, however I want to do this cycle once.
If the lifecycle is ngAfterViewInit I can't display the graph
my script
#ViewChildren('pr_chart') chartElementRefs: QueryList<ElementRef>;
constructor(
public afDB: AngularFireDatabase,
public afSG: AngularFireStorage,
public afAuth: AngularFireAuth,
){ }
listData = []
chartData1 = [];
charts= [];
colorCurve = null;
colorCurveFull = null;
ngAfterViewInit() {
this.chartData1 = [1,2,3,4,5,6];
this.afDB.list('db').snapshotChanges(['child_added']).subscribe(async mybets => {
mybets.forEach(mybet => {
this.listData.push({
data : mybet.payload.exportVal().bankroll)
});
var data = Object.values(mybet.payload.exportVal().bankroll);
({result: this.colorCurve, result_full: this.colorCurveFull} = this.giveColor(Object.values(data)));
});
this.charts = this.chartElementRefs.map((chartElementRef, index) => {
return new Chart(chartElementRef.nativeElement, {
type: 'line',
data: {
labels: Object.keys(this.listData[index]["data"]),
datasets: [
{
label: "Test",
fill: true,
borderCapStyle: 'butt',
borderDash: [],
backgroundColor: this.colorCurve,
borderColor: this.colorCurveFull,
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'rgba(75,192,192,1)',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: Object.values(this.listData[index]["data"]),
spanGaps: false,
}
]
},
options: {
scales: {
yAxes: {
title: {
display: true,
text: "Bankroll (100€/match)",
font: {
size: 10
}
},
ticks: {
precision: 0
}
},
xAxes: {
title: {
display: true,
text: "Number value bets",
font: {
size: 10
}
}
}
},
plugins: {
legend: {
display: false,
}
}
}
});
});
// this.chartData1 = Array.from(Array(this.listData.length).keys())
// console.log("test ", this.chartData1 )
});
}
}
my html script :
<ion-card *ngFor="let data of listData" >
<ion-card-content>
<canvas #pr_chart></canvas> <!--I can't display the graph-->
</ion-card-content>
</ion-card>
<ion-card *ngFor="let data of chartData1" >
<ion-card-content>
{{listData[0].country}} <!--I can't display list data-->
<canvas #pr_chart></canvas> <!--I can display the graph-->
</ion-card-content>
</ion-card>
I've tried to changed by other lifecycle and nothing works correctly... If someone can help me !

Creating charts

I need to make a chart at the level with a row in the table, are there any tips on how to implement this enter image description here
I need the chart lines to match the row level in the table
and this code draws a separate chart
const diag = () => {
document.getElementById("canvasic").innerHTML = ' ';
document.getElementById("canvasic").innerHTML = '<canvas id="densityChart" className="canav"></canvas>';
densityCanvas = document.getElementById("densityChart");
//remove canvas from container
Chart.defaults.global.defaultFontFamily = "Arial";
Chart.defaults.global.defaultFontSize = 16;
var densityData = {
label: 'CallVol',
data:calloiList1,
backgroundColor: 'rgba(0,128,0, 0.6)',
borderColor: 'rgba(0,128,0, 1)',
borderWidth: 2,
hoverBorderWidth: 0
};
var densityData1 = {
label: 'PutVol',
data:calloiList3 ,
backgroundColor: 'rgba(255,0,0, 0.6)',
borderColor: 'rgba(255,0,0, 1)',
borderWidth: 2,
hoverBorderWidth: 0
};
var chartOptions = {
scales: {
yAxes: [{
barPercentage: 0.5
}]
},
elements: {
rectangle: {
borderSkipped: 'left',
}
}
};
var barChart = new Chart(densityCanvas, {
type: 'horizontalBar',
data: {
labels: calloiList4,
datasets: [densityData,densityData1],
},
options: chartOptions
}
);
}
enter image description here

How to maintain chartjs / ng2-charts gradient on window resize?

I had applied some gradient rule to my chartjs chart. And it looks great as you can see on the below
However, when the browser window is resized (i.e. width of window is smaller), the gradient is ruined (bottom blue colors disappeared). Screenshot:
I want to maintain the graph's gradient with all values and fit the different widths (responsive). Is there any way to do that? Here is what I had tried but didn't work:
.TS File
ngAfterViewInit() {
const ctx = (<HTMLCanvasElement>this.myChart.nativeElement).getContext('2d');
const purple_orange_gradient = ctx.createLinearGradient(0, 200, 0, 20);
purple_orange_gradient.addColorStop(0.1, "#000279");
purple_orange_gradient.addColorStop(0.2, "#0000F2");
purple_orange_gradient.addColorStop(0.3, "#0362FD");
purple_orange_gradient.addColorStop(0.4, "#04D3FD");
purple_orange_gradient.addColorStop(0.5, "#45FFB7");
purple_orange_gradient.addColorStop(0.6, "#B7FF46");
purple_orange_gradient.addColorStop(0.7, "#FFD401");
purple_orange_gradient.addColorStop(0.8, "#FE6500");
purple_orange_gradient.addColorStop(0.9, "#F30004");
purple_orange_gradient.addColorStop(1, "#7E0100");
const bar_chart = new Chart(ctx, {
type: "horizontalBar",
data: {
labels: []=this.histogramLabels.reverse(),
datasets: [{
borderColor: purple_orange_gradient,
pointBorderColor: purple_orange_gradient,
pointBackgroundColor: purple_orange_gradient,
pointHoverBackgroundColor: purple_orange_gradient,
pointHoverBorderColor: purple_orange_gradient,
pointBorderWidth: 10,
pointHoverRadius: 10,
pointHoverBorderWidth: 1,
pointRadius: 3,
fill: true,
backgroundColor: purple_orange_gradient,
borderWidth: 4,
data: []=this.histogramGraphData
}]
},
options: {
legend: {
display:false,
position: "bottom"
},
scales: {
yAxes: [{
ticks: {
display: false,
fontColor: "rgba(0,0,0,0.5)",
fontStyle: "bold",
beginAtZero: true,
maxTicksLimit: 1,
padding: 20,
},
gridLines: {
drawTicks: false,
display: false
}
}],
xAxes: [{
gridLines: {
zeroLineColor: "transparent",
},
ticks: {
padding: 20,
beginAtZero: true,
fontColor: "rgba(0,0,0,0.5)",
fontStyle: "bold"
}
}]
}
}
}
)
}
.HTML
<div class="row my-2">
<div class="col-md-6">
<canvas id=”myChart” #myChart height="130"></canvas>
</div>
</div>
HTML Canvas' createLinearGradient() depends on the y axis coordinates that you pass in as argument. You had passed in a static 200 every time (i.e. ctx.createLinearGradient(0, 200, 0, 20);).
That's why the gradient's steps remains the same everytime. For the gradient to update, you have to recalculate the height of the <canvas> element on window resize and pass it in to createLinearGradient() again.
You can accomplish this by:
Separating the block where you create the gradient into a separate function. eleHeight retrieves the height of the canvas element.
generateGradient(){
let eleHeight = this.myChart.nativeElement.offsetHeight;
// console.log(eleHeight)
let purple_orange_gradient: CanvasGradient = this.myChart.nativeElement.getContext('2d').createLinearGradient(0, eleHeight, 0, 20);
purple_orange_gradient.addColorStop(0.1, "#000279");
purple_orange_gradient.addColorStop(0.2, "#0000F2");
purple_orange_gradient.addColorStop(0.3, "#0362FD");
purple_orange_gradient.addColorStop(0.4, "#04D3FD");
purple_orange_gradient.addColorStop(0.5, "#45FFB7");
purple_orange_gradient.addColorStop(0.6, "#B7FF46");
purple_orange_gradient.addColorStop(0.7, "#FFD401");
purple_orange_gradient.addColorStop(0.8, "#FE6500");
purple_orange_gradient.addColorStop(0.9, "#F30004");
purple_orange_gradient.addColorStop(1, "#7E0100");
return purple_orange_gradient;
}
Add a onresize event handler to your containing <div> and generate the gradient again. You also need to programatically update the chart every time you make a change to re-render it.
<div style="display: block; max-height: 100%" (window:resize)="onResize($event)" >
...
</div>
onResize(event?){
// console.log("onResize");
this.barChartData.forEach((d, i) => {
d.backgroundColor = this.generateGradient();
})
this.chart.chart.update(); //update the chart to re-render it
}
Update the barchartData's properties (that uses gradient) in ngAfterViewInit. We need to do this here because we only want the height of the <canvas> element with data populated. Without data populated, the element is much smaller.
ngAfterViewInit(){
this.barChartData.forEach((d, i) => {
d.backgroundColor = this.generateGradient();
});
this.chart.chart.update(); //update the chart to re-render it
}
Have a look at this Stackblitz example⚡⚡ I have created.
You have to change the gradient whenever your canvas is resizing. Took me a while to figure out a good structure to minimize lines of code and optimize performance. This is the best I could achieve.
There are exeptions when the chart.js onResize() fires though but I couldn't solve this issue completly bulletproof. But for simple resizes it should work.
Complete code (same code in JSBin with live preview):
let sData = {}
sData.labels = []
sData.data = []
const count = 50
for (let x = 0; x < count; x++) {
sData.data.push(Math.floor(Math.random()*100))
sData.labels.push(x)
}
const canvas = document.getElementById('chart')
const ctx = canvas.getContext("2d")
let purple_orange_gradient
function updateGradient() {
let bottom = bar_chart.chartArea.bottom
let top = bar_chart.chartArea.top
purple_orange_gradient = ctx.createLinearGradient(0, bottom+top, 0, top)
purple_orange_gradient.addColorStop(0.1, "#000279")
purple_orange_gradient.addColorStop(0.2, "#0000F2")
purple_orange_gradient.addColorStop(0.3, "#0362FD")
purple_orange_gradient.addColorStop(0.4, "#04D3FD")
purple_orange_gradient.addColorStop(0.5, "#45FFB7")
purple_orange_gradient.addColorStop(0.6, "#B7FF46")
purple_orange_gradient.addColorStop(0.7, "#FFD401")
purple_orange_gradient.addColorStop(0.8, "#FE6500")
purple_orange_gradient.addColorStop(0.9, "#F30004")
purple_orange_gradient.addColorStop(1.0, "#7E0100")
return purple_orange_gradient
}
const bar_chart = new Chart(ctx, {
type: "horizontalBar",
data: {
labels: sData.labels,
datasets: [{
borderColor: purple_orange_gradient,
pointBorderColor: purple_orange_gradient,
pointBackgroundColor: purple_orange_gradient,
pointHoverBackgroundColor: purple_orange_gradient,
pointHoverBorderColor: purple_orange_gradient,
pointBorderWidth: 10,
pointHoverRadius: 10,
pointHoverBorderWidth: 1,
pointRadius: 3,
fill: true,
backgroundColor: purple_orange_gradient,
borderWidth: 4,
data: sData.data
}]
},
options: {
legend: {
display: false,
position: "bottom"
},
scales: {
yAxes: [{
ticks: {
display: false,
fontColor: "rgba(0,0,0,0.5)",
fontStyle: "bold",
beginAtZero: true,
maxTicksLimit: 1,
padding: 20,
},
gridLines: {
drawTicks: false,
display: false
}
}],
xAxes: [{
gridLines: {
zeroLineColor: "transparent",
},
ticks: {
padding: 20,
beginAtZero: true,
fontColor: "rgba(0,0,0,0.5)",
fontStyle: "bold"
}
}]
},
onResize: function(chart, size) {
// onResize gradient change
changeGradient()
}
}
});
// Initial gradient change
changeGradient()
function changeGradient() {
let newGradient = updateGradient()
bar_chart.data.datasets[0].borderColor = newGradient
bar_chart.data.datasets[0].pointBorderColor = newGradient
bar_chart.data.datasets[0].pointBackgroundColor = newGradient
bar_chart.data.datasets[0].pointHoverBackgroundColor = newGradient
bar_chart.data.datasets[0].pointHoverBorderColor = newGradient
bar_chart.data.datasets[0].backgroundColor = newGradient
bar_chart.update()
}

Live streaming data using chart.js, javascript, html

I wanted to stream live data in the form of a chart. I'm new to Javascript, so I wanted to first experiment with the sample on this page.
https://web.archive.org/web/20211113012042/https://nagix.github.io/chartjs-plugin-streaming/latest/samples/charts/line-horizontal.html
The code is given as:
var chartColors = {
red: 'rgb(255, 99, 132)',
orange: 'rgb(255, 159, 64)',
yellow: 'rgb(255, 205, 86)',
green: 'rgb(75, 192, 192)',
blue: 'rgb(54, 162, 235)',
purple: 'rgb(153, 102, 255)',
grey: 'rgb(201, 203, 207)'
};
function randomScalingFactor() {
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
}
function onRefresh(chart) {
chart.config.data.datasets.forEach(function(dataset) {
dataset.data.push({
x: Date.now(),
y: randomScalingFactor()
});
});
}
var color = Chart.helpers.color;
var config = {
type: 'line',
data: {
datasets: [{
label: 'Dataset 1 (linear interpolation)',
backgroundColor: color(chartColors.red).alpha(0.5).rgbString(),
borderColor: chartColors.red,
fill: false,
lineTension: 0,
borderDash: [8, 4],
data: []
}, {
label: 'Dataset 2 (cubic interpolation)',
backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
borderColor: chartColors.blue,
fill: false,
cubicInterpolationMode: 'monotone',
data: []
}]
},
options: {
title: {
display: true,
text: 'Line chart (hotizontal scroll) sample'
},
scales: {
xAxes: [{
type: 'realtime'
}],
yAxes: [{
scaleLabel: {
display: true,
labelString: 'value'
}
}]
},
tooltips: {
mode: 'nearest',
intersect: false
},
hover: {
mode: 'nearest',
intersect: false
},
plugins: {
streaming: {
duration: 20000,
refresh: 1000,
delay: 2000,
onRefresh: onRefresh
}
}
}
};
window.onload = function() {
var ctx = document.getElementById('myChart').getContext('2d');
window.myChart = new Chart(ctx, config);
};
document.getElementById('randomizeData').addEventListener('click', function() {
config.data.datasets.forEach(function(dataset) {
dataset.data.forEach(function(dataObj) {
dataObj.y = randomScalingFactor();
});
});
window.myChart.update();
});
var colorNames = Object.keys(chartColors);
document.getElementById('addDataset').addEventListener('click', function() {
var colorName = colorNames[config.data.datasets.length % colorNames.length];
var newColor = chartColors[colorName];
var newDataset = {
label: 'Dataset ' + (config.data.datasets.length + 1),
backgroundColor: color(newColor).alpha(0.5).rgbString(),
borderColor: newColor,
fill: false,
lineTension: 0,
data: []
};
config.data.datasets.push(newDataset);
window.myChart.update();
});
document.getElementById('removeDataset').addEventListener('click', function() {
config.data.datasets.pop();
window.myChart.update();
});
document.getElementById('addData').addEventListener('click', function() {
onRefresh(window.myChart);
window.myChart.update();
});
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://github.com/nagix/chartjs-plugin-streaming/releases/download/v1.5.0/chartjs-plugin-streaming.min.js"></script>
</head>
<body>
<div>
<canvas id="myChart"></canvas>
</div>
<p>
<button id="randomizeData">Randomize Data</button>
<button id="addDataset">Add Dataset</button>
<button id="removeDataset">Remove Dataset</button>
<button id="addData">Add Data</button>
</p>
</body>
When I copy and paste it into jsfiddle, the first code snippet going into the Javascript section and the second going into the HTML section. However, nothing happens? Could someone explain why/help me edit it so that it works?
Note: the code above is not my own, it belongs to this guy
In JSFiddle, the load type is set to 'On Load' by default, so you cannot handle the load event. Setting the load type to 'No wrap - bottom of ' works (in the pop-up menu in the Javascript section).

Chart js. How to change font styles for "labels" array?

I got a chart from Chart JS library.
Screenshot
var ctx = document.getElementById("myChart");
var data = {
labels: ["HTML", "CSS", "JavaScript", "jQuery", "Bootstrap", "Gulp", "PHP", 'SQL', 'Git'],
datasets: [
{
defaultFontColor: 'red',
backgroundColor: "rgba(0,255,255,.4)",
borderColor: "rgba(0,255,255,.4)",
pointBackgroundColor: "red",
pointBorderColor: "#fff",
lineTension: 0,
pointHoverBackgroundColor: "#fff",
pointHoverBorderColor: "rgba(179,181,198,1)",
data: [95, 99, 60, 91, 36, 95, 40, 95, 95]
}
]
};
var myRadarChart = new Chart(ctx, {
type: 'radar',
data: data,
options: {
responsive: true,
scale: {
reverse: false,
ticks: {
// defaultFontSize: true
}
}
}
});
I need to change font styles for underlined labels. I've dug over documentation and i tried all what i could. Even global font settings didn't change label styles, though it worked for the rest of other text. Have you met such a problem? Thanks.
It's well hidden, but you can find this under "Point Label Options"
http://www.chartjs.org/docs/#scales-radial-linear-scale
here is a example:
https://jsfiddle.net/qvrt01jp/1/
options: {
scale: {
pointLabels :{
fontStyle: "bold",
}
}
}
global should also work if set it like this:
Chart.defaults.global.defaultFontStyle = 'italic'
To give an update for v3.5.1:
Like this for font weights:
Chart.defaults.font.weight = '600';
Or if you want to do it inside the options object:
options: {
plugins: {
legend: {
labels: {
font: {
style: 'italic',
weight: '600',
}
}
}
}
}
Documentation with more info: https://www.chartjs.org/docs/latest/general/fonts.html

Categories