Skip to content

Commit

Permalink
Add support to fill between datasets (#4008)
Browse files Browse the repository at this point in the history
The `fill` option now accepts the index of the target dataset (number) or a string starting by "+" or "-" followed by a number representing the dataset index relative to the current one (e.g. `fill: "-2"` on dataset at index 3 will fill to dataset at index 1). It's also possible to "propagate" the filling to the target of an hidden dataset (`options.plugins.filler.propagate`). Fill boundaries `zero`, `top` and `bottom` have been deprecated and replaced by `origin`, `start` and `end`.

Implementation has been moved out of the line element into a new plugin (`src/plugins/plugin.filler.js`) and does not rely anymore on the deprecated model `scaleTop`, `scaleBottom` and `scaleZero` values. Drawing Bézier splines has been refactored in the canvas helpers (note that `Chart.helpers.canvas` is now an alias of `Chart.canvasHelpers`).

Add 3 new examples and extend utils with a pseudo-random number generator that can be initialized with `srand`. That makes possible to design examples starting always with the same initial data.
  • Loading branch information
simonbrunel authored Mar 18, 2017
1 parent 1ca0ffb commit 4b421a5
Show file tree
Hide file tree
Showing 49 changed files with 1,621 additions and 970 deletions.
66 changes: 66 additions & 0 deletions samples/area/analyser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* global Chart */

'use strict';

(function() {
Chart.plugins.register({
id: 'samples_filler_analyser',

beforeInit: function(chart, options) {
this.element = document.getElementById(options.target);
},

afterUpdate: function(chart) {
var datasets = chart.data.datasets;
var element = this.element;
var stats = [];
var meta, i, ilen, dataset;

if (!element) {
return;
}

for (i=0, ilen=datasets.length; i<ilen; ++i) {
meta = chart.getDatasetMeta(i).$filler;
if (meta) {
dataset = datasets[i];
stats.push({
fill: dataset.fill,
target: meta.fill,
visible: meta.visible,
index: i
});
}
}

this.element.innerHTML = '<table>' +
'<tr>' +
'<th>Dataset</th>' +
'<th>Fill</th>' +
'<th>Target (visibility)</th>' +
'</tr>' +
stats.map(function(stat) {
var target = stat.target;
var row =
'<td><b>' + stat.index + '</b></td>' +
'<td>' + JSON.stringify(stat.fill) + '</td>';

if (target === false) {
target = 'none';
} else if (isFinite(target)) {
target = 'dataset ' + target;
} else {
target = 'boundary "' + target + '"';
}

if (stat.visible) {
row += '<td>' + target + '</td>';
} else {
row += '<td>(hidden)</td>';
}

return '<tr>' + row + '</tr>';
}).join('') + '</table>';
}
});
}());
120 changes: 120 additions & 0 deletions samples/area/line-boundaries.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>area > boundaries | Chart.js sample</title>
<link rel="stylesheet" type="text/css" href="../style.css">
<script src="../../dist/Chart.bundle.js"></script>
<script src="../utils.js"></script>
<script src="analyser.js"></script>
</head>
<body>
<div class="content">
<div class="wrapper col-2"><canvas id="chart-0"></canvas></div>
<div class="wrapper col-2"><canvas id="chart-1"></canvas></div>
<div class="wrapper col-2"><canvas id="chart-2"></canvas></div>
<div class="wrapper col-2"><canvas id="chart-3"></canvas></div>

<div class="toolbar">
<button onclick="toggleSmooth(this)">Smooth</button>
<button onclick="randomize(this)">Randomize</button>
</div>
</div>

<script>
var presets = window.chartColors;
var utils = Samples.utils;
var inputs = {
min: -100,
max: 100,
count: 8,
decimals: 2,
continuity: 1
};

function generateData(config) {
return utils.numbers(utils.merge(inputs, config || {}));
}

function generateLabels(config) {
return utils.months(utils.merge({
count: inputs.count,
section: 3
}, config || {}));
}

var options = {
maintainAspectRatio: false,
spanGaps: false,
elements: {
line: {
tension: 0.000001
}
},
plugins: {
filler: {
propagate: false
}
},
scales: {
xAxes: [{
ticks: {
autoSkip: false,
maxRotation: 0
}
}]
}
};

[false, 'origin', 'start', 'end'].forEach(function(boundary, index) {

// reset the random seed to generate the same data for all charts
utils.srand(8);

new Chart('chart-' + index, {
type: 'line',
data: {
labels: generateLabels(),
datasets: [{
backgroundColor: utils.transparentize(presets.red),
borderColor: presets.red,
data: generateData(),
label: 'Dataset',
fill: boundary
}]
},
options: utils.merge(options, {
title: {
text: 'fill: ' + boundary,
display: true
}
})
});
});


function toggleSmooth(btn) {
var value = btn.classList.toggle('btn-on');
Chart.helpers.each(Chart.instances, function(chart) {
chart.options.elements.line.tension = value? 0.4 : 0.000001;
chart.update();
});
}

function randomize() {
var seed = utils.rand();
Chart.helpers.each(Chart.instances, function(chart) {
utils.srand(seed);

chart.data.datasets.forEach(function(dataset) {
dataset.data = generateData();
});

chart.update();
});
}
</script>
</body>
</html>
157 changes: 157 additions & 0 deletions samples/area/line-datasets.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>area > datasets | Chart.js sample</title>
<link rel="stylesheet" type="text/css" href="../style.css">
<script src="../../dist/Chart.bundle.js"></script>
<script src="../utils.js"></script>
<script src="analyser.js"></script>
</head>
<body>
<div class="content">
<div class="wrapper">
<canvas id="chart-0"></canvas>
</div>
<div class="toolbar">
<button onclick="togglePropagate(this)">Propagate</button>
<button onclick="toggleSmooth(this)">Smooth</button>
<button onclick="randomize(this)">Randomize</button>
</div>
<div id="chart-analyser" class="analyser"></div>
</div>

<script>
var presets = window.chartColors;
var utils = Samples.utils;
var inputs = {
min: 20,
max: 80,
count: 8,
decimals: 2,
continuity: 1
};

function generateData() {
return utils.numbers(inputs);
}

function generateLabels(config) {
return utils.months({count: inputs.count});
}

utils.srand(42);

var data = {
labels: generateLabels(),
datasets: [{
backgroundColor: utils.transparentize(presets.red),
borderColor: presets.red,
data: generateData(),
hidden: true,
label: 'D0'
}, {
backgroundColor: utils.transparentize(presets.orange),
borderColor: presets.orange,
data: generateData(),
label: 'D1',
fill: '-1'
}, {
backgroundColor: utils.transparentize(presets.yellow),
borderColor: presets.yellow,
data: generateData(),
hidden: true,
label: 'D2',
fill: 1
}, {
backgroundColor: utils.transparentize(presets.green),
borderColor: presets.green,
data: generateData(),
label: 'D3',
fill: '-1'
}, {
backgroundColor: utils.transparentize(presets.blue),
borderColor: presets.blue,
data: generateData(),
label: 'D4',
fill: '-1'
}, {
backgroundColor: utils.transparentize(presets.grey),
borderColor: presets.grey,
data: generateData(),
label: 'D5',
fill: '+2'
}, {
backgroundColor: utils.transparentize(presets.purple),
borderColor: presets.purple,
data: generateData(),
label: 'D6',
fill: false
}, {
backgroundColor: utils.transparentize(presets.red),
borderColor: presets.red,
data: generateData(),
label: 'D7',
fill: 8
}, {
backgroundColor: utils.transparentize(presets.orange),
borderColor: presets.orange,
data: generateData(),
hidden: true,
label: 'D8',
fill: 'end'
}]
};

var options = {
maintainAspectRatio: false,
spanGaps: false,
elements: {
line: {
tension: 0.000001
}
},
scales: {
yAxes: [{
stacked: true
}]
},
plugins: {
filler: {
propagate: false
},
samples_filler_analyser: {
target: 'chart-analyser'
}
}
};

var chart = new Chart('chart-0', {
type: 'line',
data: data,
options: options
});

function togglePropagate(btn) {
var value = btn.classList.toggle('btn-on');
chart.options.plugins.filler.propagate = value;
chart.update();
}

function toggleSmooth(btn) {
var value = btn.classList.toggle('btn-on');
chart.options.elements.line.tension = value? 0.4 : 0.000001;
chart.update();
}

function randomize() {
chart.data.datasets.forEach(function(dataset) {
dataset.data = generateData();
});
chart.update();
}
</script>
</body>
</html>
Loading

0 comments on commit 4b421a5

Please sign in to comment.