Pascal S
Pascal S

Reputation: 33

How to label x-Axis in Chart.js by days?

I'm currently trying to fetch data from blockchain.info and to display it on a Chart.js in a simple JavaScript file.

It works just fine if my xAxes type is 'linear', but in that case the labels on the x-Axis are displayed with the numeric unix timestamp.

xAxes: [{
    type: 'linear',
    time: {
        unit: 'day',
        tooltipFormat: 'lll',
    }
}]

I'd prefer the labels to be displayed in days (e.g. 27 Jan 2018) or grouped by months (30 points on the chart with 1 label -> month). For that reason I changed the xAxes type to 'time', which then results in the following error:

"Uncaught Error: Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com".

I've played around with momentjs and inclused it by the script tag. Unfortunately I wasn't able to solve the issue.

The data in my JSON looks like this:

{
  "status": "ok",
  "name": "Confirmed Transactions Per Day",
  "unit": "Transactions",
  "period": "day",
  "description": "The number of daily confirmed Bitcoin transactions.",
  "values": [
    {
      "x": 1442534400, // Unix timestamp (2015-09-18T00:00:00+00:00)
      "y": 188330.0
    },
    ...
}

Here's my complete code:

    var requestURL = 'https://blockchain.info/de/charts/market-price?format=json&cors=true';
    var request = new XMLHttpRequest();

    request.open('GET', requestURL);
    request.responseType = 'json';
    request.send();
    request.onload = function() {
        var response = request.response;
        drawChart(response);
    }

    function drawChart(jsonObj) {

        var ctx = document.getElementById("myChart");
        var myChart = new Chart(ctx, {
            type: 'line',
            data: {
                labels: jsonObj["values"],
                datasets: [{
                    label: jsonObj["name"],
                    data: jsonObj["values"],
                }]
            },
            options: {
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero:true
                        }
                    }],
                    xAxes: [{
                        type: 'time',
                        time: {
                            unit: 'day',
                            tooltipFormat: 'lll',
                        }
                    }]                    
                }
            }
        });            
    }   
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<script src="node_modules/chart.js/dist/Chart.js"></script>
<script srx="myChart.js"></script>
<body>
    <canvas id="myChart" width="100%" height="100%"></canvas>
</body>
</html>

Upvotes: 2

Views: 16604

Answers (3)

Le Roi L&#233;zard
Le Roi L&#233;zard

Reputation: 51

I run your script, works fine with some enhancements in the way that each point shows the money but since the query returns 365 elements is too much data to show in the chart, that's why I think there are overlaying labels. I noticed that each value in the array has the same date (Sat Jan 17 1970 xx:yy:zz and Sun Jan 18 1970 qq:ww:ee) but different time.. then I group the data by these dates like this: enter image description here

here's the entire script.

$('#getData').on('click', function(){
		var requestURL = 'https://blockchain.info/de/charts/market-price?format=json&cors=true';    
		var request = new XMLHttpRequest();
		let newData = [], labels = [];
		let sameDate = "", previousDate = "", value = 0;
		request.open('GET', requestURL);
		request.responseType = 'json';
		request.send();
		request.onload = function() {
			
			// Group the Data by Day
			request.response.values.forEach(function(item,i){
				if (previousDate !== getDateFormat(moment(item.x)._d) )
				{
					value = 0;
					value = item.y;
					
					sameDate = getDateFormat(moment(item.x)._d);
					
					request.response.values.forEach(function(ele, j){
						if ( j > i){
							if (sameDate === getDateFormat(moment(ele.x)._d)){
								value+= ele.y;
								previousDate = getDateFormat(moment(ele.x)._d);
							}
						}
						
					});
					newData.push({x:sameDate, y:value});
					labels.push(sameDate);
				}
			});
			
		    drawChart(newData,labels);
		}

		function getDateFormat(momentType)
		{
			console.log(momentType);
			return momentType.getDate()+"-"+(momentType.getMonth()+1)+"-"+momentType.getUTCFullYear();
		}

		function drawChart(jsonObj,label) {

		    var ctx = document.getElementById("myChart");
		    var myChart = new Chart(ctx, {
		        type: 'line',
		        data: {
		            labels: label,
		            datasets: [{
		            	label: "Average USD",
		            	data:jsonObj}]
		        },
		        options: {
		            scales: {
		                yAxes: [{
		                    ticks: {
		                        beginAtZero:true
		                    }
		                }],
		                xAxes: [{
		                    display: true,
		                    scaleLabel: {
		                        display: true,
		                        labelString: 'value'
		                    }                        
		                }]                    
		            },
		            plugins: {
		            	datalabels:{
		            		borderRadius: 4,
							color: 'black',
							anchor: 'end',
							align: 'end',
							backgroundColor: function(context) {
								return context.dataset.borderColor;
							},
							formatter: function(value, context){
								// show the value on the point
								return Number(value.y).toFixed(2);
							},
		            	}
		            }
		        }
		    });            
		}    
	});

Upvotes: 0

Pascal S
Pascal S

Reputation: 33

In addition, here's my entire script.

    var requestURL = 'https://blockchain.info/de/charts/market-price?format=json&cors=true';    
var request = new XMLHttpRequest();

request.open('GET', requestURL);
request.responseType = 'json';
request.send();
request.onload = function() {
    var response = request.response;
    drawChart(response);
}

function fillLabel(jsonObj){
    var label = [];
    var arr = jsonObj["values"];
    arr.forEach(element => {
        label.push((element.x));    
    });    
    return label;
}

function drawChart(jsonObj) {

    var ctx = document.getElementById("myChart");
    var myChart = new Chart(ctx, {
        type: 'line',
        data: {
            labels: fillLabel(jsonObj),
            datasets: [{
                label: jsonObj["name"],
                data: jsonObj["values"],
            }]
        },
        options: {
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero:true
                    }
                }],
                xAxes: [{
                    type: 'time',
                    time: {
                        unit: 'second',
                        displayFormats: {
                            millisecond: 'h:mm:ss.SSS a',
                            second: 'D MMM',
                            minute: 'D MMM',
                            hour: 'hA',
                            day: 'MMM D',
                            week: 'll',
                            month: 'MMM YYYY',
                            quarter: '[Q]Q - YYYY',
                            year: 'YYYY'
                        },                            
                    },
                    display: true,
                    scaleLabel: {
                        display: true,
                        labelString: 'value'
                    }                        
                }]                    
            }
        }
    });            
}    

Upvotes: 0

Le Roi L&#233;zard
Le Roi L&#233;zard

Reputation: 51

the arrays that fill the chart

In the image above you can see the data, notice that I separate it in three arrays, in the chart I have two datasets (Ingreso(x[date],y[value]), Egreso(x[date],y[vlue])) and "Label" that is the one that fills the x-Axis label. And here is how I did it !

the code

so in the label option I fill with my label array with the dates

enter image description here

Upvotes: 1

Related Questions