I'm using the new Chart.js and trying to accomplish several customizations. Versed in JS but new to canvas, I'm struggling a bit. I'll try to provide as much information as possible.
JavaScript
/**
* Chart.js Global Config
*/
Chart.defaults.global.pointHitDetectionRadius = 5;
window.count = 0;
/**
* Chart Data
* @type {Object}
*/
var lineChartData = {
labels: ["", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC", ""],
datasets: [{
label: "Students",
data: [ 200, 250,220,180,290,300,370,350,200,280,260,190,210, 200 ],
backgroundColor: "rgba(247,155,45,1.0)",
borderColor: "rgba(247,155,45,1.0)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
pointBorderColor: "rgba(245,245,245,1)",
pointBackgroundColor: "rgba(80,81,81,1)",
pointHoverBorderWidth: 5,
pointBorderWidth: 5,
pointRadius: 8,
pointHoverRadius: 9,
pointHitRadius: 8,
}]
};
/**
* Init
*/
window.onload = function() {
var $chart = $('#chart');
window.lineChart = new Chart($chart[0], {
type: 'line',
data: lineChartData,
options: {
showLines: true,
// Legend
legend : {
display: false
},
// title
title:{
display:false,
text:'Student Hours'
},
// Tooltips
tooltips: {
enabled: false,
},
// Scales
scales: {
yAxes: [{
id: 'y-axis-0',
gridLines: {
display: true,
lineWidth: 1,
color: "rgba(255,255,255,0.85)"
},
ticks: {
beginAtZero:true,
mirror:false,
suggestedMin: 0,
suggestedMax: 500,
},
afterBuildTicks: function(chart) {
}
}],
xAxes: [{
id: 'x-axis-0',
gridLines: {
display: false
},
ticks: {
beginAtZero: true
}
}]
},
}
});
};
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.3/Chart.bundle.min.js"></script>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
</head>
<body>
<div id="chartjs-container" class="chartjs-wrap">
<canvas id="chart"></canvas>
</div>
</body>
</html>
CSS
#chartjs-container {
width:80%;
margin:20px auto;
position: relative;
}
.chartjs-wrap {
background-color: rgba(250, 210, 162, 1.0);
}
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
height:100%;
}
Any help pointing me in the right direction would be great. Is there an equivalent on "Inspect Element" for canvas? These fixes would be trivial in CSS but I'm unsure on how to debug.
Cheers
1.Remove the grid line up the y-axis
Just set display
to false for options.scales.yAxes
. This will remove all the labels too - we'll call the library method to draw the labels (without drawing the y-axis) in the plugin (see Step 4)
2.Remove the points on the first and last items of the dataset that meet the left/right edge of the chart
Just pass in an array to pointRadius
and pointHoverRadius
instead of a number. The following arrays will hide the first and last points (with your data)
...
pointRadius: [0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0],
pointHoverRadius: [0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0],
...
You might have to generate this using a script if your data length is dynamic.
3.Inset the y-axis scale labels
Set ticks.mirror
for options.scales.yAxes
to true. The plugin (from Step 4) will then just call the library draw
method for the scale.
4.Make x-axis grid lines overlay on top of the line data fill
To make the gridLines appear (like it is) over the fill but under the points, the easiest way would be to draw it under the fill and set the fill to a slightly transparent value.
backgroundColor: "rgba(247,155,45,0.4)",
We have to draw the gridLines on our own since we don't want them to start from the edge. So set gridLines.display
to false for options.scales.yAxes
and register the following plugin
Chart.pluginService.register({
afterDraw: function (chart, easingDecimal) {
var yScale = chart.scales['y-axis-0'];
var helpers = Chart.helpers;
var chartArea = chart.chartArea;
// draw labels - all we do is turn on display and call scale.draw
yScale.options.display = true;
yScale.draw.apply(yScale, [chartArea]);
yScale.options.display = false;
yScale.ctx.save();
// draw under the fill
yScale.ctx.globalCompositeOperation = 'destination-over';
// draw the grid lines - simplified version of library code
helpers.each(yScale.ticks, function (label, index) {
if (label === undefined || label === null) {
return;
}
var yLineValue = this.getPixelForTick(index);
yLineValue += helpers.aliasPixel(this.ctx.lineWidth);
this.ctx.lineWidth = this.options.gridLines.lineWidth;
this.ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
this.ctx.beginPath();
this.ctx.moveTo(chartArea.left + 40, yLineValue);
this.ctx.lineTo(chartArea.right, yLineValue);
this.ctx.stroke();
}, yScale);
yScale.ctx.restore();
},
})
Plugins will be called for all charts. If you want to skip the above logic for some charts, all you have to is set some property on the options
object and check for it before you run your logic (e.g. yAxis.options.custom
at the same level as yAxis.options.display
If you want to hide the 0 and 500 labels, you can set ticks.callback
for options.scales.yAxes
, like so
callback: function(value) {
if (value !== 0 && value !== 500)
return '' + value;
},
Note that it works as long as your scale is within the suggestedMin and suggestedMax. If your data goes outside these bounds, you'll have to use the scale properties.
To make the x-axis label background white, just add the below bit to the end of the plugin's afterDraw
method
yScale.ctx.save();
yScale.ctx.fillStyle = 'white';
yScale.ctx.globalCompositeOperation = 'destination-over';
yScale.ctx.fillRect(0, yScale.bottom, chartArea.right, chartArea.bottom);
yScale.ctx.restore();
It just draws a white rectangle under the canvas content. Because your background color is set via the CSS, the rectangle is on top of the background color and everything is shiny.
You also have to move your background-color from your .chartjs-wrap to your canvas (otherwise you get a orange border at the bottom)
canvas {
background-color: rgba(250, 210, 162, 1.0);
...
Updated version of your JSBin will all the above applied - http://jsbin.com/parucayara/1/edit?output