Chart support for Reveal.js

This commit is contained in:
Oliver Kennedy 2018-01-19 01:18:06 -05:00
parent 063c35e8ac
commit 1d80613c10
4 changed files with 14387 additions and 0 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,170 @@
# Chart
A plugin for [Reveal.js](https://github.com/hakimel/reveal.js) allowing to easily add charts using [Chart.js v2.7](http://www.chartjs.org/).
[Check out the live demo](https://rajgoel.github.io/reveal.js-demos/chart-demo.html)
## Installation
Copy the files ```Chart.min.js``` and ```csv2chart.js``` into the plugin folder of your reveal.js presentation, i.e. ```plugin/chart```.
Add the plugins to the dependencies in your presentation, as below.
```javascript
Reveal.initialize({
// ...
dependencies: [
// ...
{ src: 'plugin/chart/Chart.min.js' },
{ src: 'plugin/chart/csv2chart.js' },
// ...
]
});
```
## Configuration
The plugin has several parameters that you can set for your presentation by providing an ```chart``` option in the reveal.js initialization options.
Note that all configuration parameters are optional and the defaults of [Chart.js 2.7](http://nnnick.github.io/Chart.js/docs-v2/) will be used for parameters that are not specified.
```javascript
Reveal.initialize({
// ...
chart: {
defaults: {
global: {
title: { fontColor: "#FFF" },
legend: {
labels: { fontColor: "#FFF" },
},
},
scale: {
scaleLabel: { fontColor: "#FFF" },
gridLines: { color: "#FFF", zeroLineColor: "#FFF" },
ticks: { fontColor: "#FFF" },
}
},
line: { borderColor: [ "rgba(20,220,220,.8)" , "rgba(220,120,120,.8)", "rgba(20,120,220,.8)" ], "borderDash": [ [5,10], [0,0] ]},
bar: { backgroundColor: [ "rgba(20,220,220,.8)" , "rgba(220,120,120,.8)", "rgba(20,120,220,.8)" ]},
pie: { backgroundColor: [ ["rgba(0,0,0,.8)" , "rgba(220,20,20,.8)", "rgba(20,220,20,.8)", "rgba(220,220,20,.8)", "rgba(20,20,220,.8)"] ]},
radar: { borderColor: [ "rgba(20,220,220,.8)" , "rgba(220,120,120,.8)", "rgba(20,120,220,.8)" ]},
},
// ...
});
```
The ```defaults``` parameter will overwrite ```Chart.defaults```. Furthermore, for any chart type, e.g. line, bar, etc., the parameters for the individual datasets can be specified. Where Chart.js allows to specify a single parameter for a particular dataset, the plugin allows to specify an array of values for this parameter, which will automatically be assigned to the different datasets. Note that if there are more datasets than elements in the array, the plugin will start again with the first value in the array.
## Usage
A chart can be included in a slide by adding a ```canvas``` element with the ```data-chart``` attribute set to the desired chart type.
The chart can be configured within the canvas body by a JSON string embedded into an HTML comment.
```html
<canvas data-chart="line">
<!--
{
"data": {
"labels": ["January"," February"," March"," April"," May"," June"," July"],
"datasets": [
{
"data":[65,59,80,81,56,55,40],
"label":"My first dataset","backgroundColor":"rgba(20,220,220,.8)"
},
{
"data":[28,48,40,19,86,27,90],
"label":"My second dataset","backgroundColor":"rgba(220,120,120,.8)"
}
]
},
"options": { "responsive": "true" }
}
-->
</canvas>
```
It is possible to provide the chart data by comma separated values and use the JSON string within the HTML comment to configure the chart layout.
```html
<canvas class="stretch" data-chart="line">
My first dataset, 65, 59, 80, 81, 56, 55, 40
<!-- This is a comment that will be ignored -->
My second dataset, 28, 48, 40, 19, 86, 27, 90
<!--
{
"data" : {
"labels" : ["Enero", "Febrero", "Marzo", "Avril", "Mayo", "Junio", "Julio"],
"datasets" : [{ "borderColor": "#0f0", "borderDash": ["5","10"] }, { "borderColor": "#0ff" } ]
}
}
-->
</canvas>
```
The layout configuration provided in ```chart``` parameter (see Configuration) will be used by default and only those parameters that are specified in a JSON string are used to overwrite the default values. If no JSON string is provided to configure the chart layout the default configuration is used. Note, that if no labels for the data points are provided by a JSON string, the plugin expects that the first row provides table headers.
```html
<canvas data-chart="line">
Month, January, February, March, April, May, June, July
My first dataset, 65, 59, 80, 81, 56, 55, 40
My second dataset, 28, 48, 40, 19, 86, 27, 90
</canvas>
```
The chart data can also be provided in an external CSV file. To include external data, the filename must be specified using the ```data-chart-src``` attribute of the ```canvas``` element. The CSV file is expected to only contain data values, whereas options for drawing the chart can be given as described above.
```html
<canvas data-chart="bar" data-chart-src="data.csv">
<!--
{
"data" : {
"datasets" : [{ "backgroundColor": "#0f0" }, { "backgroundColor": "#0ff" } ]
},
"options": { "responsive": true, "scales": { "xAxes": [{ "stacked": true }], "yAxes": [{ "stacked": true }] } }
}
-->
</canvas>
```
## Animation
The plugin recreates the charts on a slide change to show the Chart.js animations. These animation can be turned off globally in the configuration by
```javascript
Reveal.initialize({
// ...
chart: {
defaults: {
global: {
animation: null,
// ...
},
// ...
},
},
// ...
});
```
or within a chart, e.g. by
```html
<canvas class="stretch" data-chart="line">
<!--
{
"data": {
// ...
},
"options": { "responsive": "true", "animation": "" }
}
-->
</canvas>
```
## License
MIT licensed
Copyright (C) 2017 Asvin Goel

View file

@ -0,0 +1,168 @@
/*****************************************************************
** Author: Asvin Goel, goel@telematique.eu
**
** csv2chart.js is a plugin for reveal.js allowing to integrate
** Chart.js in reveal.js
**
** Version: 0.2
**
** License: MIT license (see LICENSE.md)
**
******************************************************************/
var RevealChart = window.RevealChart || (function(){
function parseJSON(str) {
var json;
try {
json = JSON.parse(str);
} catch (e) {
return null;
}
return json;
}
/*
* Recursively merge properties of two objects
*/
function mergeRecursive(obj1, obj2) {
for (var p in obj2) {
try {
// Property in destination object set; update its value.
if ( obj1[p].constructor==Object && obj2[p].constructor==Object ) {
obj1[p] = mergeRecursive(obj1[p], obj2[p]);
} else {
obj1[p] = obj2[p];
}
} catch(e) {
// Property in destination object not set; create it and set its value.
obj1[p] = obj2[p];
}
}
return obj1;
}
function createChart(canvas, CSV, comments) {
canvas.chart = null;
var ctx = canvas.getContext("2d");
var chartOptions = { responsive: true };
var chartData = { labels: null, datasets: []};
if ( comments !== null ) for (var j = 0; j < comments.length; j++ ){
comments[j] = comments[j].replace(/<!--/,'');
comments[j] = comments[j].replace(/-->/,'');
var config = parseJSON(comments[j]);
if ( config ) {
if ( config.data ) {
mergeRecursive( chartData, config.data);
}
if ( config.options ) {
mergeRecursive( chartOptions, config.options);
}
}
}
var lines = CSV.split('\n').filter(function(v){return v!==''});
// if labels are not defined, get them from first line
if ( chartData.labels === null && lines.length > 0 ) {
chartData.labels = lines[0].split(',');
chartData.labels.shift();
lines.shift();
}
// get data values
for (var j = 0; j < lines.length; j++ ){
if (chartData.datasets.length <= j) chartData.datasets[j] = {};
chartData.datasets[j].data = lines[j].split(','); //.filter(function(v){return v!==''});
chartData.datasets[j].label = chartData.datasets[j].data[0];
chartData.datasets[j].data.shift();
for (var k = 0; k < chartData.datasets[j].data.length; k++ ){
chartData.datasets[j].data[k] = Number(chartData.datasets[j].data[k]);
}
}
// add chart options
var config = chartConfig[canvas.getAttribute("data-chart")];
if ( config ) {
for (var j = 0; j < chartData.datasets.length; j++ ){
for (var attrname in config) {
if ( !chartData.datasets[j][attrname] ) {
chartData.datasets[j][attrname] = config[attrname][j%config[attrname].length];
}
}
}
}
canvas.chart = new Chart(ctx, { type: canvas.getAttribute("data-chart"), data: chartData, options: chartOptions });
}
var initializeCharts = function(){
// Get all canvases
var canvases = document.querySelectorAll("canvas");
for (var i = 0; i < canvases.length; i++ ){
// check if canvas has data-chart attribute
if ( canvases[i].hasAttribute("data-chart") ){
var CSV = canvases[i].innerHTML.trim();
var comments = CSV.match(/<!--[\s\S]*?-->/g);
CSV = CSV.replace(/<!--[\s\S]*?-->/g,'').replace(/^\s*\n/gm, "")
if ( ! canvases[i].hasAttribute("data-chart-src") ) {
createChart(canvases[i], CSV, comments);
}
else {
var canvas = canvases[i];
var xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.readyState === 4) {
createChart(canvas, xhr.responseText, comments);
}
else {
console.warn( 'Failed to get file ' + canvas.getAttribute("data-chart-src") +". ReadyState: " + xhr.readyState + ", Status: " + xhr.status);
}
};
xhr.open( 'GET', canvas.getAttribute("data-chart-src"), false );
try {
xhr.send();
}
catch ( error ) {
console.warn( 'Failed to get file ' + canvas.getAttribute("data-chart-src") + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + error );
}
}
}
}
}
function recreateChart(canvas) {
var config = canvas.chart.config;
canvas.chart.destroy();
setTimeout( function() { canvas.chart = new Chart(canvas, config); }, 500); // wait for slide transition
}
// check if chart option is given or not
var chartConfig = Reveal.getConfig().chart || {};
// set global chart options
var config = chartConfig["defaults"];
if ( config ) {
mergeRecursive(Chart.defaults, config);
}
Reveal.addEventListener('ready', function(){
initializeCharts();
Reveal.addEventListener('slidechanged', function(){
var canvases = Reveal.getCurrentSlide().querySelectorAll("canvas[data-chart]");
for (var i = 0; i < canvases.length; i++ ){
if ( canvases[i].chart && canvases[i].chart.config.options.animation ) {
recreateChart( canvases[i] );
}
}
});
});
})();