I want to plot an area fill line chart with multiple series, using javascript & RGraph, for a period between two dates, but I do not have data points for every date; how do I do this with RGraph?
I cannot miss out dates in the data I pass to RGraph because although some of the series do not have that data, it might be that other series do (e.g. ABC has data for January and March, and XYZ has data for January and April).
I must have all dates for the year, which is represented with a horizontal axis showing just the month/period labels.
I have boiled this down to a simplified example below, and with a jsFiddle example on https://jsfiddle.net/Abeeee/25m1sc7d/1/
Both the code below and the JSFiddle show two charts controlled by the drawAll() function, which has a variable x in it. I want the second chart (cvs2) which uses x=null to not include plotting that null but simply draw the red line/area between 100 and 200, resulting a similar chart to the first one (cvs1).
<!DOCTYPE HTML>
<html>
<head>
<script src='https://www.rgraph.net/libraries/RGraph.common.core.js'></script>
<script src='https://www.rgraph.net/libraries/RGraph.common.dynamic.js'></script>
<script src='https://www.rgraph.net/libraries/RGraph.common.effects.js'></script>
<script src='https://www.rgraph.net/libraries/RGraph.common.key.js'></script>
<script src='https://www.rgraph.net/libraries/RGraph.common.tooltips.js'></script>
<script src='https://www.rgraph.net/libraries/RGraph.drawing.rect.js'></script>
<script src='https://www.rgraph.net/libraries/RGraph.line.js'></script>
<script src='//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js'>
</script>
</head>
<body>
<canvas id='cvs1' width='900' height='300' style='border:solid 1pt red'>
[No canvas support]
</canvas>
<hr>
<canvas id='cvs2' width='900' height='300' style='border:solid 1pt blue'>
[No canvas support]
</canvas>
<script type='text/Javascript'>
drawAll();
$(window).resize(function() {
drawAll();
});
function drawAll() {
var x=150;
var data = [[0, 50, 100, x, 200],[10,20,30,40,50]];
drawChart('cvs1', data);
x=null;
var data = [[0, 50, 100, x, 200],[10,20,30,40,50]];
drawChart('cvs2', data);
}
function drawChart(canvasId, data) {
var canvas = document.getElementById(canvasId);
RGraph.Reset(canvas);
canvas.width = $(window).width() * 0.9;
var text_size = Math.min(10, ($(window).width() / 1000) * 20 );
var linewidth = $(window).width() > 500 ? 2 : 1;
linewidth = $(window).width() > 750 ? 3 : linewidth;
var line = new RGraph.Line(canvasId, data);
line.set('chart.text.size', text_size);
line.Set('chart.background.barcolor1', 'rgba(255,255,255,1)');
line.Set('chart.background.barcolor2', 'rgba(255,255,255,1)');
line.Set('chart.background.grid.color', 'rgba(238,238,238,1)');
line.Set('chart.colors', [ 'red', 'green', 'blue']);
line.Set('chart.linewidth', 1);
line.Set('chart.hmargin', 15);
line.Set('chart.labels', ['Q1\n2017','Q2','Q3','Q4','Q1\n2018']);
line.Set('chart.gutter.left',40);
line.Set('chart.gutter.right',10);
line.Set('chart.gutter.bottom',50);
line.Set('chart.filled', true);
line.Set('chart.filled.accumulative',true);
line.Set('chart.key', ['ABC', 'DEF']);
line.Set('chart.tickmarks.dot.color','white');
line.Set('chart.backgroundGridAutofitNumvlines',data.length);
line.Set('key.position','gutter'); // or graph
line.Set('chart.ymin',0);
line.Set('chart.ymax',250);
line.Set('chart.numyticks',5);
line.Set('chart.key.position.x',50);
line.Set('chart.key.position.y',10);
line.draw();
}
</script>
</body>
</html>
So, how do you tell RGraph to just draw the points with data and ignore those without whilst keeping all the date points?
Thanks
Abe
You can use null values in your data. The behaviour is slightly different for a single dataset vs multiple data sets though:
var data = [4,8,6,3,5,4,2,null,8,6,3,5,8,null,4,9,8];
Well it seems that RGraph doesn't do it, so I've resorted to ChartJS and on the whole it works - see https://jsfiddle.net/Abeeee/6xrk1m23/41/
<script type='text/JavaScript' src='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.js'></script>
<div style="width:100%; height:300px">
<canvas id="canvas" style='width:100%; height:300px'></canvas>
</div>
<button id='on'>
Span Gaps=true
</button>
<button id='off'>
Span Gaps=false
</button>
var config = {
type: 'line',
data: {
labels: ['Jan\n2018', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
datasets: [{
label: 'Red',
borderColor: '#FF0000',
backgroundColor: '#FF0000',
data: [
10, 20, 30, 40, 50, 60, undefined, 80, 90, 100, 90, 80
],
}, {
label: 'Blue',
borderColor: '#0000FF',
backgroundColor: '#0000FF',
data: [
10, 20, undefined, 40, 50, 60, 70, 80, 92, undefined, 90, 80
],
}]
},
options: {
spanGaps: true,
responsive: true,
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Line Chart - Stacked Area'
},
tooltips: {
mode: 'index',
},
hover: {
mode: 'index'
},
scales: {
xAxes: [{
scaleLabel: {
display: true,
labelString: 'Month'
}
}],
yAxes: [{
stacked: true,
scaleLabel: {
display: true,
labelString: 'Value'
}
}]
}
}
};
var ctx1 = document.getElementById('canvas').getContext('2d');
var myChart = new Chart(ctx1, config);
$("#on").on("click", function() {
myChart.options.spanGaps=true;
myChart.update();
});
$("#off").on("click", function() {
myChart.options.spanGaps=false;
myChart.update();
});
Use the buttons to switch spanGaps on and off.
Note, I say on the whole, as it fixes my problem (of underlying data gaps), but it seems to fail to span if the dataset is sitting on top of another (a ChartJS bug perhaps?)
Related
I am experimenting with Chart.js to build radar charts. I mastered the basics (see basic chart below), but I would like to use the x y coordinates of the graph to place texts directly on the canvas.
After some digging, I found out that it is not possible to use getValueForPixel or getPixelForTick in a radar chart. See this github issue. In the connecting thread, a new method getValueForDistanceFromCenter is introduced.
As I understand it, it would be possible to calculate the distance from the center with this method, and use it to get coordinates. I searched the Chart.js documentation and other sites, but cannot find any code examples or information on how to implement this.
Can somebody point me in the right direction how to implement the method in the code?
var data = {
labels: ["Ball Skills", "Shooting", "Physical"],
datasets: [{
label: [`ikke`, `jij`],
backgroundColor: "rgba(38,120,255,0.2)",
borderColor: "rgba(38,120,255, 1)",
data: [90, 90, 90]
}]
};
var options = {
responsive: true,
tooltips: false,
title: {
text: 'Basic example',
display: true,
position: `bottom`,
},
scale: {
angleLines: {
display: true
},
ticks: {
suggestedMin: 0,
suggestedMax: 100,
stepSize: 25,
maxTicksLimit: 11,
display: false,
}
},
legend: {
labels: {
padding: 10,
fontSize: 14,
lineHeight: 30,
},
},
};
var myChart = new Chart(document.getElementById("chart"), {
type: 'radar',
data: data,
options: options
});
The radialLinear scale (in version 2.9.4 that I have seen your are using version 2) there is the method getValueForDistanceFromCenter(value) to get the distance from center but there is another method getPointPositionForValue(index, value) which can provide you the point at a specif index of your data.
To use them and to draw what you want on chart using those points, you need to implement a plugin.
In the below snippet, I'm drawing a rect between the points at a specific value.
const ctx = document.getElementById("myChart");
const data = {
labels: ["Ball Skills", "Shooting", "Physical"],
datasets: [{
label: [`ikke`, `jij`],
backgroundColor: "rgba(38,120,255,0.2)",
borderColor: "rgba(38,120,255, 1)",
data: [50, 50, 50]
}]
};
const options = {
responsive: true,
tooltips: false,
title: {
text: 'Basic example',
display: true,
position: `bottom`,
},
scale: {
angleLines: {
display: true
},
ticks: {
suggestedMin: 0,
suggestedMax: 100,
stepSize: 25,
maxTicksLimit: 11,
display: false,
}
},
legend: {
labels: {
padding: 10,
fontSize: 14,
lineHeight: 30,
},
},
};
const plugin = {
id: 'getDistance',
afterDraw(chart) {
const c = chart.ctx;
const rScale = chart.scale;
c.save();
chart.data.datasets[0].data.forEach(function(item, index) {
const point = rScale.getPointPositionForValue(0.5 + index, 50);
c.beginPath();
c.fillStyle = 'red';
c.fillRect(point.x - 5, point.y - 5, 10, 10);
c.fill();
});
c.restore();
}
};
const myChart = new Chart(ctx, {
type: 'radar',
plugins: [plugin],
data: data,
options: options
});
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.4/dist/Chart.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"/>
</div>
</body>
</html>
I've got a problem with chartJS. I'm calling a function to create a new chart. The creation works, but I would like to destroy any previous charts, so that I get a new one when calling a function.
This is my code at the moment:
var chartID;
function addData(chartType,data) {
for (var i = 0; i < data.length; i++) {
dataLabels.push(data[i][0]);
dataPoints.push(data[i][1]);
//console.log(data[i][1]);
}
if(chartID){
console.log('destroy');
chartID.destroy();
}
var ctx = document.getElementById('chart01').getContext('2d');
chartID = new Chart(ctx, {
type: chartType,
data: {
labels: dataLabels,
datasets: [{
label: 'Labels',
data: dataPoints,
backgroundColor: '#333'
}]
},
options: {
maintainAspectRatio: false,
aspectRatio: 1
}
});
}
Even I had the same issue earlier. I simply added a condition to check the chart variable is empty or not.
if(chartID != null){
chartID.destroy();
}
Include this at the top of the function. It'll work fine as you are declaring chartID globally. This way you don't need to redeclare the chart again.
Try this:
const chartCanvas = document.getElementById('myChart');
if( window.lineChart != undefined){
window.lineChart.destroy();
}
window.lineChart = new Chart(chartCanvas,{
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
datasets: [
{
label: 'Cases',
data: [23,42,22,45,56,77,33,22,46,77,32,44],
fill: false,
// backgroundColor: 'red',
borderColor: ['rgb(255, 255, 0)'],
lineTension: 0.2,
borderWidth: 1.5
}
]
},
options:{
title: {
display: true,
text: "Temperature variation",
fontFamily: 'Arial',
fontSize: 16
},
legend: {
display: true,
position: "right",
labels: {
boxWidth:10
}
},
//stacked - start with 0 as minimum value for y-axis
scales:{
yAxes: [{
stacked: true,
gridLines:{
display: true,
color: '#FFFFFF',
lineWidth: 1,
zeroLineColor: 'blue',
zeroLineWidth: 2,
drawBorder: false // this to remove the ghost line that appears
// when you add zeroLine x-axis
}
}],
xAxes: [{
gridLines:{
display: true,
zeroLineColor: 'blue',
zeroLineWidth: 1,
color: 'transparent'
}
}]
}
}
});
----------------- Added code sample above ------------------
I had some issues with ChartJs. Somehow, it created a new chart with the previous chart still in the canvas which shows up when you hover.
This worked for me:
if( window.chartID!= undefined){
window.chartID.destroy();
}
chartID = new Chart(ctx, {...});
I am creating multiple charts on click.
but before creating chart I just destroy any previous charts
so , thats how it looks
var chartStatus
// on one onclick
if (chartStatus) { chartStatus.destroy(); }
chartStatus = new Chart(document.getElementById("co2Chart"), co2Config);
// on another onclick
if (chartStatus) { chartStatus.destroy(); }
chartStatus = new Chart(document.getElementById("tempChart"), tempConfig);
This question already has answers here:
Chart.js Picture inside doughnut segment
(2 answers)
Closed 3 years ago.
I have draw a doughnut chart using Chart.js https://www.chartjs.org/docs/latest/charts/doughnut.html and i want to add image (i.e .png .svg) inside of every slice of doughnut chart as well as gradient background color.
this goal i want to achieve...image link here
html code here....
<canvas id="myChart" width="600" height="400"></canvas>
js code here
var ctx = $('#myChart');
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Instagram: 35% ($38.21, 100 items)',
'Pinterest: 20% ($23.98, 69 items)',
'Direct: 15% ($17.77, 48 items)',
'Facebook: 12% ($13.54, 41 items)',
'Twitter: 10% ($11.02, 35 items)',
'youtube: 8% ($9.63, 21 items)'],
datasets: [{
data: [35, 20, 15, 12, 10, 8],
backgroundColor: [
'#ff0',
'#BD081C',
'#232323',
'#1877F2',
'#1DA1F2',
'#FF0000'
]
}]
},
options: {
rotation:-0.2 * Math.PI,
responsive: false,
scales: {
Axes: [{
gridLines: {
drawBorder: false,
},
}]
},
legend: {
display: true,
position: "right",
align: "center",
onClick: null,
fontSize: 30,
fullWidth:true,
labels: {
fontColor: '#000',
fontSize:16,
padding:30,
}
},
}
});
Do something like this
var ctx=myChart.width/2;
var cy=myChart.height/2;
ctx.translate(cx,cy);
var startAngle = myChart.segments[thisWedgeIndex].startAngle;
var endAngle = myChart.segments[thisWedgeIndex].endAngle;
var midAngle = startAngle+(endAngle-startAngle)/2;
ctx.rotate(midAngle);//mid angle rotation
//inner radious
var midWedgeRadius=myChart.innerRadius+(chart.radius-chart.innerRadius)/2;
context.translate(midWedgeRadius,0);
context.setTransform(1,0,0,1,0,0);//rotate
I have an HTML page with around 10 charts generated by chart.js (so these are canvas elements). I want to be able to export the page content into a PDF file.
I've tried using jsPDF's .fromHTML function, but it doesn't seem to support exporting the canvas contents. (Either that or I'm doing it wrong). I just did something like:
$(".test").click(function() {
var doc = new jsPDF()
doc.fromHTML(document.getElementById("testExport"));
doc.save('a4.pdf')
});
Any alternative approaches would be appreciated.
You should use html2canvas (to support canvas export and get a better representation of html elements), along with jsPDF.
Here is an example :
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
datasets: [{
label: 'DST',
data: [3, 1, 4, 2, 5],
backgroundColor: 'rgba(0, 119, 290, 0.2)',
borderColor: 'rgba(0, 119, 290, 0.6)',
fill: false
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
stepSize: 1
}
}]
}
}
});
function saveAsPDF() {
html2canvas(document.getElementById("chart-container"), {
onrendered: function(canvas) {
var img = canvas.toDataURL(); //image data of canvas
var doc = new jsPDF();
doc.addImage(img, 10, 10);
doc.save('test.pdf');
}
});
}
#chart-container {
background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.5/jspdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<div id="chart-container">
ChartJS - Line Chart
<canvas id="ctx"></canvas>
</div><br>
<button onclick="saveAsPDF();">save as pdf</button>
I am creating a very simple chart with chart.js and stuck with the two small issues.
Below is the code that I am using to create the chart/graph
<div style="width: 400px; height: 400px;">
<canvas name="myChart" id="myChart" width="400px" height="400px"> </canvas>
</div>
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
animation: false,
data: {
labels: ["Service A", "Service B", "Service C"],
datasets: [{
label: 'Time In Service',
data: [180, 360, 180],
backgroundColor: [
'#0073CF',
'#FF0000',
'#7DC24B'
],
borderColor: [
'#fff',
'#fff',
'#fff'
],
borderWidth: 2
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
The current chart can be seen here Chart Generated
What is Need is something like Chart Needed
I want the x-axis labels in legend on right side
Currently the time is in seconds in data. I want to Show time spend on x-axis in hours:min
Any little help will be appreciated.
Have a try like this,
Need to modify your data structure a little and set the y=axis properties for displaying the required label format.
P.S : you need to use the latest chart.js library since the position right functionality was recently added and also i have increased the second value in your given example to display some meaningful data in hh:mm format.
function formatTime(secs)
{
var hours = Math.floor(secs / (60 * 60));
var divisor_for_minutes = secs % (60 * 60);
var minutes = Math.floor(divisor_for_minutes / 60);
var divisor_for_seconds = divisor_for_minutes % 60;
var seconds = Math.ceil(divisor_for_seconds);
return hours + ":" + minutes;
}
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
animation: false,
data: {
labels: ["Time"],
datasets: [{
label: "Service A",
data: [1800],
backgroundColor: '#0073CF',
borderColor: '#fff',
borderWidth: 2
},
{
label: "Service B",
data: [36000],
backgroundColor: '#FF0000',
borderColor: '#fff',
borderWidth: 2
},
{
label: "Service C",
data: [8000],
backgroundColor: '#7DC24B',
borderColor: '#fff',
borderWidth: 2
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true,
callback: function(label, index, labels) {
return formatTime(label);
}
}
}]
},
legend: {
position: "right",
display:true
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js"></script>
<div style="width: 400px; height: 400px;">
<canvas name="myChart" id="myChart" width="400px" height="400px"> </canvas>
</div>