-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Sean
committed
Feb 9, 2017
1 parent
05715fe
commit 95a6e36
Showing
8 changed files
with
700 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# chartjs-plugin-downsample | ||
|
||
Plugin for downsampling data in Chart.js, based off of [sveinn-steinarsson/flot-downsample](https://github.com/sveinn-steinarsson/flot-downsample). | ||
|
||
## Configuration | ||
|
||
The configuration for this plugin lives in chartInstance.options.downsample. This looks like the following while setting up your chart: | ||
|
||
``` | ||
{ | ||
options: { | ||
downsample: { | ||
enabled: true, | ||
threshold: 500 // max number of points to display per dataset | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### Additional Options | ||
|
||
| Option | Default | Description | | ||
| --------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | ||
| auto | true | If true, downsamples data automatically every update. Otherwise, chart will have to be manually downsampled with `.downsample()` | | ||
| onInit | true | If true, downsamples data when the chart is initialized. | | ||
| restoreOriginalData | true | If true, replaces the downsampled data with the original data after each update. This is, mainly, for compatibility with other plugins. | | ||
| preferOriginalData | false | If true, downsamples original data instead of data. This option can clash with dynamically-added data. If false, data cannot be "un-downscaled". | | ||
|
||
## Methods | ||
|
||
| Method | Description | | ||
|------------------------------------------------ |------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| chartInstance.downsample(*var threshold = null*) | Manually downsamples the data on the given chart. If a threshold is passed, updates the threshold in the chart config to the given value. | | ||
|
||
## Optimal Performance | ||
|
||
This plugin was created because of performance issues while loading lots of data in a chart with [pan/zoom capabilites](https://github.com/chartjs/chartjs-plugin-zoom/). | ||
|
||
If options are not changed from their defaults, data will be downsampled every time the user pans or zooms - this is probably not what you want. For a more performant configuration, try this: | ||
|
||
``` | ||
{ | ||
options: { | ||
downsample: { | ||
enabled: true, | ||
threshold: <YOUR THRESHOLD HERE>, // change this | ||
auto: false, // don't re-downsample the data every move | ||
onInit: true, // but do resample it when we init the chart (this is default) | ||
preferOriginalData: true, // use our original data when downscaling so we can downscale less, if we need to. | ||
restoreOriginalData: false, // if auto is false and this is true, original data will be restored on pan/zoom - that isn't what we want. | ||
} | ||
} | ||
} | ||
``` | ||
|
||
## License | ||
|
||
chartjs-plugin-downsample is released under the terms of [the MIT License](http://www.opensource.org/licenses/MIT). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
var gulp = require('gulp'); | ||
var browserify = require('browserify'); | ||
var source = require('vinyl-source-stream'); | ||
var merge = require('merge-stream'); | ||
var streamify = require('gulp-streamify'); | ||
var uglify = require('gulp-uglify'); | ||
var insert = require('gulp-insert'); | ||
var concat = require('gulp-concat'); | ||
var buffer = require('vinyl-buffer'); | ||
|
||
var header = "/* chartjs-plugin-downsample | AlbinoDrought | MIT License | https://github.com/AlbinoDrought/chartjs-plugin-downsample/blob/master/LICENSE | Based on flot-downsample, https://github.com/sveinn-steinarsson/flot-downsample/ */\n"; | ||
var outDir = "./"; | ||
|
||
gulp.task('build', buildTask); | ||
|
||
function buildTask() { | ||
var build = browserify('./src/chartjs-plugin-downsample.js') | ||
.ignore('chart.js') | ||
.bundle() | ||
.pipe(source('chartjs-plugin-downsample.js')) | ||
.pipe(buffer()) | ||
.pipe(insert.prepend(header)) | ||
.pipe(gulp.dest(outDir)) | ||
// min build | ||
.pipe(streamify(uglify())) | ||
.pipe(insert.prepend(header)) | ||
.pipe(streamify(concat('chartjs-plugin-downsample.min.js'))) | ||
.pipe(gulp.dest(outDir)); | ||
|
||
return build; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"name": "chartjs-plugin-downsample", | ||
"version": "1.0.2", | ||
"description": "Chart.js plugin to downsample chart data", | ||
"main": "src/chartjs-plugin-downsample.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"author": "AlbinoDrought", | ||
"license": "MIT", | ||
"dependencies": { | ||
"chart.js": "^2.5.0" | ||
}, | ||
"devDependencies": { | ||
"browserify": "^14.0.0", | ||
"chartjs-plugin-zoom": "^0.4.5", | ||
"gulp": "^3.9.1", | ||
"gulp-concat": "^2.6.1", | ||
"gulp-insert": "^0.5.0", | ||
"gulp-streamify": "^1.0.2", | ||
"gulp-uglify": "^2.0.1", | ||
"merge-stream": "^1.0.1", | ||
"vinyl-buffer": "^1.0.0", | ||
"vinyl-source-stream": "^1.1.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
<!doctype html> | ||
<html> | ||
|
||
<head> | ||
<title>Scatter Chart</title> | ||
<script src="../node_modules/chart.js/dist/Chart.bundle.js"></script> | ||
<script src="../chartjs-plugin-downsample.js"></script> | ||
<style> | ||
canvas { | ||
-moz-user-select: none; | ||
-webkit-user-select: none; | ||
-ms-user-select: none; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
<div style="width:75%"> | ||
<div> | ||
<canvas id="canvas"></canvas> | ||
<div> | ||
<label for="threshold">Threshold: </label> | ||
<input type="range" id="threshold" min="1" max="0" value="0" step="1" style="width: 100%" /> | ||
<span id="thresholdCurrent">0</span> | ||
</div> | ||
</div> | ||
</div> | ||
<script> | ||
var scalingFactor = function(value) { | ||
return (value * 0.9) + (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 10); | ||
}; | ||
var randomColor = function (opacity) { | ||
return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')'; | ||
}; | ||
|
||
var generateData = function (count) { | ||
var data = []; | ||
|
||
var y = 0; | ||
for (var i = 0; i < count; i++) { | ||
y = scalingFactor(y); | ||
data.push({ | ||
x: i, | ||
y: y, | ||
}); | ||
} | ||
|
||
return data; | ||
}; | ||
|
||
var generateDataset = function(name, dataCount) { | ||
return { | ||
label: name, | ||
data: generateData(dataCount), | ||
borderColor: randomColor(1), | ||
borderWidth: 2, | ||
fill: false, | ||
}; | ||
}; | ||
|
||
var config = { | ||
type: 'line', | ||
data: { | ||
datasets: [generateDataset("Foo", 500), generateDataset("Bar", 500)] | ||
}, | ||
options: { | ||
responsive: true, | ||
title:{ | ||
display:true, | ||
text: 'Chart.js Downsample Plugin' | ||
}, | ||
legend: { | ||
display: false | ||
}, | ||
scales: { | ||
xAxes: [{ | ||
type: 'linear', | ||
position: 'bottom', | ||
}] | ||
}, | ||
downsample: { | ||
enabled: true, | ||
threshold: 100, | ||
}, | ||
animation: { | ||
duration: 0, | ||
}, | ||
elements: { | ||
point: { | ||
radius: 0, // disable points | ||
} | ||
} | ||
} | ||
}; | ||
|
||
window.onload = function () { | ||
var ctx = document.getElementById("canvas").getContext("2d"); | ||
window.myLine = new Chart(ctx, config); | ||
|
||
var slider = document.getElementById("threshold"), | ||
thresholdCurrent = document.getElementById("thresholdCurrent"); | ||
|
||
slider.max = config.data.datasets[0].data.length; | ||
slider.value = thresholdCurrent.innerHTML = config.options.downsample.threshold; | ||
|
||
slider.oninput = function() { | ||
window.myLine.options.downsample.threshold = thresholdCurrent.innerHTML = slider.value; | ||
window.myLine.update(); | ||
}; | ||
}; | ||
|
||
</script> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
<!doctype html> | ||
<html> | ||
|
||
<head> | ||
<title>Scatter Chart</title> | ||
<script src="../node_modules/chart.js/dist/Chart.bundle.js"></script> | ||
<script src="../chartjs-plugin-downsample.js"></script> | ||
<style> | ||
canvas { | ||
-moz-user-select: none; | ||
-webkit-user-select: none; | ||
-ms-user-select: none; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
<div style="width:75%"> | ||
<div> | ||
<canvas id="canvas"></canvas> | ||
<div> | ||
<label for="threshold">Threshold (total): </label> | ||
<input type="range" id="threshold" min="1" max="0" value="0" step="1" style="width: 100%" /> | ||
<span id="thresholdCurrent">0</span> | ||
</div> | ||
<div> | ||
<button type="button" onclick="addDataset(window.myLine);">Add Dataset</button> | ||
</div> | ||
</div> | ||
</div> | ||
<script> | ||
var scalingFactor = function(value) { | ||
return (value * 0.9) + (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 10); | ||
}; | ||
var randomColor = function (opacity) { | ||
return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')'; | ||
}; | ||
|
||
var generateData = function (count) { | ||
var data = []; | ||
|
||
var y = 0; | ||
for (var i = 0; i < count; i++) { | ||
y = scalingFactor(y); | ||
data.push({ | ||
x: i, | ||
y: y, | ||
}); | ||
} | ||
|
||
return data; | ||
}; | ||
|
||
var threshold = 0; | ||
|
||
var generateDataset = function(name, dataCount) { | ||
return { | ||
label: name, | ||
data: generateData(dataCount), | ||
borderColor: randomColor(1), | ||
borderWidth: 2, | ||
fill: false, | ||
}; | ||
}; | ||
|
||
var updateChart = function(chart) { | ||
chart.options.downsample.threshold = Math.floor(threshold / chart.data.datasets.length); | ||
chart.update(); | ||
}; | ||
|
||
var addDataset = function(chart) { | ||
chart.data.datasets.push(generateDataset( | ||
Math.floor(Math.random() * 1337), 500 | ||
)); | ||
|
||
updateChart(chart); | ||
}; | ||
|
||
var config = { | ||
type: 'line', | ||
data: { | ||
datasets: [generateDataset("Foo", 500), generateDataset("Bar", 500)] | ||
}, | ||
options: { | ||
responsive: true, | ||
title:{ | ||
display:true, | ||
text: 'Chart.js Downsample Plugin' | ||
}, | ||
legend: { | ||
display: false | ||
}, | ||
scales: { | ||
xAxes: [{ | ||
type: 'linear', | ||
position: 'bottom', | ||
}] | ||
}, | ||
downsample: { | ||
enabled: true, | ||
threshold: 50, | ||
preferOriginalData: false, | ||
}, | ||
animation: { | ||
duration: threshold, | ||
}, | ||
elements: { | ||
point: { | ||
radius: 0, // disable points | ||
} | ||
} | ||
} | ||
}; | ||
|
||
window.onload = function () { | ||
var ctx = document.getElementById("canvas").getContext("2d"); | ||
window.myLine = new Chart(ctx, config); | ||
|
||
var slider = document.getElementById("threshold"), | ||
thresholdCurrent = document.getElementById("thresholdCurrent"); | ||
|
||
slider.max = 500; | ||
slider.value = thresholdCurrent.innerHTML = config.options.downsample.threshold; | ||
|
||
slider.oninput = function() { | ||
threshold = thresholdCurrent.innerHTML = slider.value; | ||
updateChart(window.myLine); | ||
}; | ||
}; | ||
|
||
</script> | ||
</body> | ||
|
||
</html> |
Oops, something went wrong.