elzi elzi - 6 months ago 524
jQuery Question

Chart.js 2.0 - How to change default appearance of canvas/chart elements

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.

 

Related Links





 

Code - JSBin



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%;
}


 

What I'm trying to do




  1. Remove the grid line up the y-axis

  2. Remove the points on the first and last items of the dataset that meet the left/right edge of the chart

  3. Inset the y-axis scale labels

  4. Make x-axis grid lines overlay on top of the line data fill



 

Screenshots



Current State
current-state-ss

Desired State (Approximate)
desired-state-ss

 

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

Answer

1.Remove the grid line up the y-axis

Just set display to false for options.scales.yAxes. This will remove all the gridLines and labels too - we'll draw them using a 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

You originally had 2 options here (either set the fill to a slightly transparent value) or use a plugin. Since we need the plugin for a couple of the previous steps, let's just use that to draw the gridLines on our own.

First set gridLines.display to false for options.scales.yAxes since we are drawing it ourselves

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;

        // 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);
    },
})

Updated version of your JSBin will all the above applied - http://jsbin.com/qozedobohe/1/edit?output