This question has been asked a few times but I've not been able to use the answers previously provided to finish my first dynamic Charts.js. I'm trying to build a simple example which works and once i've managed to do that I can expand on it. Currently I have the following:
1) A simple dropdown menu which you can pick a year from:
<form>
<div class="row">
<div class="label"><b>Select Year</b></div>
<select id="year" name="year" style = "width:100%">
<option value=2017>2017</option>
<option value=2018>2018</option>
</select>
</div>
</form>
<br>
2) Some javascript which I use to call my MySQL query on.change:
<script type="text/javascript">
jQuery(document).ready( function($) {
var valueCheck;
jQuery('#year').on( 'change', function () {
year = $('#year').val();
jQuery.ajax({
type: "POST",
url: "/wp-admin/admin-ajax.php",
data: {
action: 'call_chart_data',
year: year,
},
success:function(output){
jQuery('#y_data1').html( output );
}
});
}).change();
});
</script>
3) PHP which queries the MySQL database:
function get_chart_data(){
global $wpdb;
$year = $_POST['year'];
$myQuery = $wpdb->get_results('SELECT dreamTeamPoints FROM afl_master WHERE player_id = "CD_I270963" AND year = '.$year);
$data = array();
foreach ($myQuery as $result) {
$data[] = $result->dreamTeamPoints;
}
wp_die();
}
add_action('wp_ajax_nopriv_call_chart_data', 'get_chart_data');
add_action('wp_ajax_call_chart_data', 'get_chart_data');
The code to this point is successful in returning an array of values, as per below (when 2017 is selected):
Array ( [0] => 68 [1] => 152 [2] => 139 [3] => 143 [4] => 132 [5] => 155
[6] => 65 [7] => 59 [8] => 111 [9] => 157 [10] => 92 [11] => 62
[12] => 89 [13] => 83 [14] => 105 [15] => 34 [16] => 134 [17] => 47
[18] => 124 [19] => 97 [20] => 153 [21] => 149 [22] => 76 [23] => 97 )
Now finally, I have a static graph which I want to convert to dynamic by replacing the variable y_data1 (third line in following code) with the MySQL response, however I don't know how to feed this into the javascript.
<script type="text/javascript">
var x_time = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,"QF","SF","PF","GF"];
var y_data1 = [91,115,67,46,,,,,,,,,,,68,111,111,77,95,106,99,93];
var y_data2 = [84,74,64,79,,,,,,,,,,,82,84,80,82,88,87,78,79];
new Chart(document.getElementById("myChart"), {
type: 'bar',
data: {
labels: x_time,
datasets: [{
type:'line',
label: 'Fantasy Points',
fill:false,
backgroundColor: 'orange',
borderColor: 'orange',
data: y_data1,
yAxisID: 'left-axis',
pointRadius: 5,
pointHoverRadius: 7
}, {
label: 'Time On Ground (%)',
fill: true,
backgroundColor: 'black',
borderColor: 'black',
data: y_data2,
yAxisID: 'right-axis'
}]
},
options: {
title: {
display: false},
legend: { display: true },
maintainAspectRatio:true,
responsive: true,
tooltips: {mode: 'index', intersect: false},
hover: {mode: 'nearest', intersect: true},
scales: {
xAxes: [{display: true, stacked:true, scaleLabel: {display: true, labelString: 'Round'}}],
yAxes: [{
type:'linear',
id:'left-axis',
display: true,
position: 'left',
scaleLabel: {display: true, labelString: 'Fantasy Points'},
gridLines: {drawOnChartArea:false},
ticks: {beginAtZero: true}
},{
type:'linear',
id:'right-axis',
display: true,
position: 'right',
stacked:false,
scaleLabel: {display: true, labelString: 'Time On Ground (%)'},
gridLines: {drawOnChartArea:false},
ticks: {beginAtZero: true}
}]
}
}
});
</script>
Appreciate any help people can provide.
I'd be returning the values as a string, rather than an array:
$data = '';
foreach ($myQuery as $result) {
$data .= $result->dreamTeamPoints.',';
}
Then assigning it to a value on the successful ajax post:
success:function(output){
//jQuery('#y_data1').html( output );
var out = output;
}
and lastly putting the 'out' variable inside the assignment:
var y_data1 = [ out ];
You may be able to simplify it more - Go the Eagles.
Related
I am trying to remove the grid lines on the Radar chart on chart.js v2 for react.
Desired Result
but keeping the outermost line while removing the inner lines and numbers
I have attempted to use the following code but it only returns a runtime error saying "category" is not a registered scale.
const options = {
scales: {
x: {
grid: {
display: false
}
},
y: {
grid: {
display: false
}
}
}
}
This can be done through the following options.
scale: {
ticks: {
stepSize: 1,
callback: (v, i, values) => i + 1 < values.length ? '' : v
},
gridLines: {
color: [0, 0, 0, 0, '#ccc']
}
}
For further details, please consult the Styling page from the Chart.js v2.9.4 documentation.
Please take a look at below runnable code and see how it works. Note that it uses a generic approach for defining gridLines.color.
const labels = ['Things 1', 'Things 2', 'Things 3', 'Things 4', 'Things 5'];
const data = [0, 3, 5, 2, 5];
const max = Math.ceil(Math.max(...data));
new Chart('radar-chart', {
type: 'radar',
data: {
labels: labels,
datasets: [{
data: data,
fill: true,
backgroundColor: 'rgba(0, 0, 255,0.2)',
borderColor: 'rgb(0, 0, 255)'
}]
},
options: {
legend: {
display: false
},
scale: {
ticks: {
stepSize: 1,
max: max,
callback: (v, i, values) => i + 1 < values.length ? '' : v
},
gridLines: {
color: Array.from(Array(max).keys()).map((v, i) => i + 1 < max ? 0 : '#ccc')
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
<canvas id="radar-chart" height="80"></canvas>
From the error you are getting it seems like you are using Chart.js V3 and not V2. To get what you want you need to import and register everything if you want to use treeshaking, I suggest you do this at the latest part and for development import everything like so:
import Chart from 'chart.js/auto';
To hide and get the result what you want your config needs to look like this:
const labels = ['Things 1', 'Things 1', 'Things 1', 'Things 1', 'Things 1'];
const data = [0, 3, 5, 2, 3];
new Chart('radar-chart', {
type: 'radar',
data: {
labels: labels,
datasets: [{
data: data,
fill: true,
backgroundColor: 'rgba(0, 0, 255,0.2)',
borderColor: 'rgb(0, 0, 255)'
}]
},
options: {
plugins: {
legend: {
display: false
}
},
scales: {
r: {
ticks: {
stepSize: 1,
callback: (v, i, values) => i + 1 < values.length ? '' : v
},
grid: {
color: data.map((v, i) => i + 1 < data.length ? 0 : '#ccc')
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.js"></script>
<canvas id="radar-chart" height="80"></canvas>
Notice that I specify a r scale instead of x and y
I have an array of data as follows
getDates stores all the dates set by the backend team (01 => 1 April, 02 =>2 April and so on)
getAllApplicantsPerDay stores the number of registrations on each day
Array Name All Data
-------------------------------------------------------------------
getDates '01', '02','03'
getAllApplicantsPerDay 6,4,5,8,7,8
So, basically the data stored are as follows
getDates
Array ( [0] => '01' [1] => '02' [2] => '03')
getAllApplicantsPerDay
Array ( [0] => 6 [1] => 4 [2] => 5 [3] => 8 [4] => 7 [5] => 8 )
Now, as per the requirement of the backend team, they can change the date by adding or removing some dates
So, let's say they add 3 days, the new getDates array would be
getGender
Array ( [0] => '01' [1] => '02' [2] => '03' [3] => '04' [4] => '05' [5] => '06')
In accordance, getAllApplicantsPerDay would also change. I would also want different colours each time (randomly selected color)
However, I cannot show that in a graph. I dont know the syntax to do it.
here is what I tried so far
Script
var config111 = {
type: 'bar',
data: {
labels: [
<?php echo json_encode($getDates); ?>
],
datasets: [{
label: 'DAILY REGISTRATIONS',
backgroundColor:'rgba(178,150,200,0.9)', ------>I want this dynamic too
borderColor: 'rgba(70,158,210,0.9)',
data: [
<?php echo json_encode($getAllApplicantsPerDay ); ?>
],
fill: false,
},
]
},
options: {
responsive: true,
title: {
display: false,
text: 'Daily Registrations'
},
tooltips: {
mode: 'index',
intersect: false,
},
/*hover: {
mode: 'nearest',
intersect: true
},*/
hover: {
mode: 'nearest',
"animationDuration": 0,
intersect: true
},
"animation": {
"duration": 1,
"onComplete": function () {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'left';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function (dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function (bar, index) {
var data = dataset.data[index];
ctx.fillText(data, bar._model.x, bar._model.y - 5);
});
});
}
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: ' Monthly Panchayat Samiti'
}
}],
/*yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Value'
}
}]*/
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
};
$(function () {
var ctx111 = document.getElementById('canvas').getContext('2d');
window.myLine = new Chart(ctx111, config111);
});
Using json_encode would mean that you are encoding the data in JSON format. This format,may not be acceptable by chartjs,as chartjs requires strings for labels, and numbers for data.
Here is what you can do (only the required section of the code)
(Please Note):- Copy and paste this in label tag in chartjs. You can do this exact same thing for data tag as well.
labels: [
<?php
for($i=0;$i<count($getDates);$i++){
echo $getDates[$i];
echo ',';
}
?>
],
Also, make sure to send the data as an array from the backend, if you want to use this method.
As for the random color thing, I suggest you check out this github repository. You can search for other options for random colors as well.
i am using angular and i required to draw a graph/chart i have a data that contains name and time.
in the above situtaion name represents the name of customer and the time represent tha time of call he make(a single customer can make several calls so a customer can have many times). i want to draw a chart in such a way that we can see a customer make a call on this time.
i tried to use chart.js and try line and scatter chart but unable to get desired result.
any suggestion which chart i can use and or how to achieve this
thankyou in advance
Using a scatter chart is a good choice. The solution however depends on the format of your data. Let's presume, it looks like this:
const data = [
{ name: 'Rachel', calls: ['2021-03-01 10:15', '2021-03-01 18:02', '2021-03-02 06:48'] },
{ name: 'William', calls: ['2021-03-01 13:24', '2021-03-02 08:41', '2021-03-02 11:13'] },
{ name: 'Barbara', calls: ['2021-03-01 07:58', '2021-03-01 15:47', '2021-03-02 10:16'] }
];
You need to create a dataset for each user and provide the data in point format where the values of distinct users are different but all values of a same user are identical. This can be done using the Array.map() method as follows:
data.map((user, i) => ({
label: user.name,
data: user.calls.map(call => ({ x: call, y: i + 1 }))
}))
Now you also need to define a ticks.callback function on the y-axis that transforms the numeric tick value back to the user name
yAxes: [{
ticks: {
...
callback: v => v % 1 == 0 ? data[v - 1].name : undefined
}
}],
Please take a look at below runnable code and see how it works.
const data = [
{ name: 'Rachel', calls: ['2021-03-01 10:15', '2021-03-01 18:02', '2021-03-02 06:48'] },
{ name: 'William', calls: ['2021-03-01 13:24', '2021-03-02 08:41', '2021-03-02 11:13'] },
{ name: 'Barbara', calls: ['2021-03-01 07:58', '2021-03-01 15:47', '2021-03-02 10:16'] }
];
const colors = ['red', 'blue', 'green'];
new Chart('myChart', {
type: 'scatter',
data: {
datasets: data.map((user, i) => ({
label: user.name,
data: user.calls.map(call => ({ x: call, y: i + 1 })),
backgroundColor: colors[i],
pointRadius: 4
}))
},
options: {
responsive: true,
tooltips: {
callbacks: {
title: tooltipItem => data[tooltipItem[0].datasetIndex].name,
label: tooltipItem => tooltipItem.xLabel
}
},
scales: {
yAxes: [{
ticks: {
min: 0.5,
max: data.length + 0.5,
stepSize: 0.5,
callback: v => v % 1 == 0 ? data[v - 1].name : undefined
}
}],
xAxes: [{
type: 'time',
time: {
unit: 'hour',
displayFormats: {
hour: 'MMM-DD HH'
},
tooltipFormat: 'MMM-DD HH:mm'
},
gridLines: {
lineWidth: 0
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js"></script>
<canvas id="myChart" height="80"></canvas>
I'm trying to build a chart in chart.js, showing price data of a virtual item, with a line chart showing pricing, and a backlay bar chart, showing sales volume, like this:
My issue is, the y-axis is the same for both, meaning the price data is shown at the bottom with unnoticeable differences, since the volume is in the hundreds.
I want the price data to be on the y-axis, with the bars shown relatively, with the highest volume being shown as 100% height, not the values on the y-axis, something more like this:
Is this possible, and how would it be done? Thanks!
Code:
let marketData = [["Nov 28 2018 20: +0",30.332,"103"],["Nov 28 2018 21: +0",25.801,"188"],["Nov 28 2018 22: +0",25.451,"262"],["Nov 28 2018 23: +0",12.484,"693"]];
let lineData = [];
let barData = [];
let labels = [];
marketData.forEach(function(thing) {
labels.push(thing[0].replace(' +0', '00'));
lineData.push(thing[1]);
barData.push(thing[2]);
});
new Chart(document.getElementById("mixed-chart"), {
type: 'bar',
data: {
labels: labels,
datasets: [
{
label: "Price",
type: "line",
borderColor: "#3e95cd",
data: lineData,
fill: false
},
{
label: "Sold",
type: "bar",
backgroundColor: "rgba(0,0,0,0.2)",
data: barData
}
]
},
options: {
title: {
display: true,
text: 'Sale price vs sale volume'
},
legend: { display: false }
}
});
use a second y-axis to give the bar series a different scale
assign each data set to its own axis by using property --> yAxisID
then set the matching id of the y-axis in the scales.yAxes option
see following working snippet...
$(document).ready(function() {
let marketData = [["Nov 28 2018 20: +0",30.332,"103"],["Nov 28 2018 21: +0",25.801,"188"],["Nov 28 2018 22: +0",25.451,"262"],["Nov 28 2018 23: +0",12.484,"693"]];
let lineData = [];
let barData = [];
let labels = [];
marketData.forEach(function(thing) {
labels.push(thing[0].replace(' +0', '00'));
lineData.push(thing[1]);
barData.push(thing[2]);
});
new Chart(document.getElementById("mixed-chart"), {
type: 'bar',
data: {
labels: labels,
datasets: [
{
label: "Price",
type: "line",
borderColor: "#3e95cd",
data: lineData,
fill: false,
yAxisID: 'A' // <-- set y-axis id
},
{
label: "Sold",
type: "bar",
backgroundColor: "rgba(0,0,0,0.2)",
data: barData,
yAxisID: 'B' // <-- set y-axis id
}
]
},
options: {
title: {
display: true,
text: 'Sale price vs sale volume'
},
legend: {display: false},
scales: {
yAxes: [{
id: 'A', // <-- set y-axis id
position: 'left',
}, {
id: 'B', // <-- set y-axis id
position: 'right',
// hide grid lines and labels
gridLines: {
display: false
},
ticks: {
display: false
}
}]
}
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<canvas id="mixed-chart"></canvas>
I created a bubble chart using ChartJs and populating data dynamically using Json.
See the code below.
for (var i = 0; i < response.data.length; i++) {
var point_data = [];
point_data.push({
x: response.data[i]['return_tickets'].toString(),
y: Math.round(response.data[i]['return_percentage']).toString(),
r: Math.round((response.data[i]['return_percentage'])).toString()
});
data.push({ label: response.data[i]['staff_name'], data: point_data, backgroundColor: getRandomColor(), hoverRadius:4 });
}
new Chart(document.getElementById("bubbleChart"), {
type: 'bubble',
data: {
datasets: data
},
options: {
title: {
display: true,
text: ''
}, scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: "Return Tickets %"
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: "Return Tickets"
}
}]
}
}
});
It generates the desired chart as below
The problem is when I hover over any bubble the size of the bubble increases exponentially.
How to keep the size same ?
I'm setting the hoverRadius property of the dataset but it does nothing for me.
Problem is with your this line of code:
{ label: response.data[i]['staff_name'], data: point_data, backgroundColor: getRandomColor(), hoverRadius:4 }
This is not a valid JSON. Values must be either strings or arrays. Most probably issue is at label: response.data[i]['staff_name'] or in point_data (I can see you are making x, y and r values .toString() that maybe not required). Check it again. Create a valid JSON and then try by setting hoverRadius: 0, it will work.
Setting hoverRadius: 0 working fine for me. Bubble size will not change on mouse over if you set hoverRadius: 0.
Below is working example:
var chart = new Chart(ctx, {
type: 'bubble',
data: {
datasets: [{
label: 'Bubble',
data: [{
x: 5,
y: 55,
r: 27.5
}],
backgroundColor: 'rgba(0, 119, 290, 0.6)',
hoverRadius: 0
}]
},
options: {
tooltips: {
callbacks: {
label: function(t, d) {
return d.datasets[t.datasetIndex].label +
': (Day:' + t.xLabel + ', Total:' + t.yLabel + ')';
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="ctx"></canvas>
Checkout official documentation for more info : https://www.chartjs.org/docs/latest/charts/bubble.html#dataset-properties
I have already faced the same issue also fixed it by typecasting for every x,y & z. I just convert it to float
'x' => (float) $x_axis_value,
'y' => (float) $y_axis_value,
'r' => (float) $radious_value,