[export] export buttons for all charts :D

This commit is contained in:
Prateeksha Singh 2018-04-17 11:09:56 +05:30
parent 8e45278303
commit eb3cd64b1b
13 changed files with 138 additions and 90 deletions

View File

@ -1278,6 +1278,37 @@ function runSMILAnimation(parent, svgElement, elementsToAnimate) {
const CSSTEXT = ".chart-container{position:relative;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Cantarell','Fira Sans','Droid Sans','Helvetica Neue',sans-serif}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.graph-svg-tip{position:absolute;z-index:99999;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.graph-svg-tip ul{padding-left:0;display:flex}.graph-svg-tip ol{padding-left:0;display:flex}.graph-svg-tip ul.data-point-list li{min-width:90px;flex:1;font-weight:600}.graph-svg-tip strong{color:#dfe2e5;font-weight:600}.graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:' ';border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}"; const CSSTEXT = ".chart-container{position:relative;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Cantarell','Fira Sans','Droid Sans','Helvetica Neue',sans-serif}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.graph-svg-tip{position:absolute;z-index:99999;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.graph-svg-tip ul{padding-left:0;display:flex}.graph-svg-tip ol{padding-left:0;display:flex}.graph-svg-tip ul.data-point-list li{min-width:90px;flex:1;font-weight:600}.graph-svg-tip strong{color:#dfe2e5;font-weight:600}.graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:' ';border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}";
function downloadFile(filename, data) {
var a = document.createElement('a');
a.style = "display: none";
var blob = new Blob(data, {type: "image/svg+xml; charset=utf-8"});
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function(){
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 300);
}
function prepareForExport(svg) {
let clone = svg.cloneNode(true);
clone.classList.add('chart-container');
clone.setAttribute('xmlns', "http://www.w3.org/2000/svg");
clone.setAttribute('xmlns:xlink', "http://www.w3.org/1999/xlink");
let styleEl = $.create('style', {
'innerHTML': CSSTEXT
});
clone.insertBefore(styleEl, clone.firstChild);
let container = $.create('div');
container.appendChild(clone);
return container.innerHTML;
}
class BaseChart { class BaseChart {
constructor(parent, options) { constructor(parent, options) {
@ -1322,8 +1353,8 @@ class BaseChart {
this.setMargins(); this.setMargins();
// Bind window events // Bind window events
window.addEventListener('resize', () => this.draw(true)); window.addEventListener('resize', () => this.boundDrawFn);
window.addEventListener('orientationchange', () => this.draw(true)); window.addEventListener('orientationchange', () => this.boundDrawFn);
} }
validateColors(colors, type) { validateColors(colors, type) {
@ -1597,45 +1628,18 @@ class BaseChart {
return new Chart(this.parent, args); return new Chart(this.parent, args);
} }
boundDrawFn() {
this.draw(true);
}
unbindWindowEvents(){ unbindWindowEvents(){
window.removeEventListener('resize', () => this.draw(true)); window.removeEventListener('resize', () => this.boundDrawFn);
window.removeEventListener('orientationchange', () => this.draw(true)); window.removeEventListener('orientationchange', () => this.boundDrawFn);
} }
export() { export() {
let chartSvg = this.prepareForExport(); let chartSvg = prepareForExport(this.svg);
this.downloadFile(this.title || 'Chart', [chartSvg]); downloadFile(this.title || 'Chart', [chartSvg]);
}
downloadFile(filename, data) {
var a = document.createElement('a');
a.style = "display: none";
var blob = new Blob(data, {type: "image/svg+xml; charset=utf-8"});
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function(){
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 300);
}
prepareForExport() {
let clone = this.svg.cloneNode(true);
clone.classList.add('chart-container');
clone.setAttribute('xmlns', "http://www.w3.org/2000/svg");
clone.setAttribute('xmlns:xlink', "http://www.w3.org/1999/xlink");
let styleEl = $.create('style', {
'innerHTML': CSSTEXT
});
clone.insertBefore(styleEl, clone.firstChild);
let container = $.create('div');
container.appendChild(clone);
return container.innerHTML;
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -88,7 +88,9 @@ Array.prototype.slice.call(
}); });
}); });
aggrChart.export(); document.querySelector('.export-aggr').addEventListener('click', (e) => {
aggrChart.export();
});
// Update values chart // Update values chart
// ================================================================================ // ================================================================================
@ -179,6 +181,10 @@ chartUpdateButtons.querySelector('[data-update="remove"]').addEventListener("cli
updateChart.removeDataPoint(); updateChart.removeDataPoint();
}); });
document.querySelector('.export-update').addEventListener('click', (e) => {
updateChart.export();
});
// Trends Chart // Trends Chart
// ================================================================================ // ================================================================================
@ -199,7 +205,7 @@ let plotChartArgs = {
} }
}; };
new Chart("#chart-trends", plotChartArgs); let trendsChart = new Chart("#chart-trends", plotChartArgs);
Array.prototype.slice.call( Array.prototype.slice.call(
document.querySelectorAll('.chart-plot-buttons button') document.querySelectorAll('.chart-plot-buttons button')
@ -227,6 +233,10 @@ Array.prototype.slice.call(
}); });
}); });
document.querySelector('.export-trends').addEventListener('click', (e) => {
trendsChart.export();
});
// Event chart // Event chart
// ================================================================================ // ================================================================================
@ -275,7 +285,7 @@ let heatmapArgs = {
colors: HEATMAP_COLORS_BLUE, colors: HEATMAP_COLORS_BLUE,
legendScale: [0, 1, 2, 4, 5] legendScale: [0, 1, 2, 4, 5]
}; };
new Chart("#chart-heatmap", heatmapArgs); let heatmapChart = new Chart("#chart-heatmap", heatmapArgs);
Array.prototype.slice.call( Array.prototype.slice.call(
document.querySelectorAll('.heatmap-mode-buttons button') document.querySelectorAll('.heatmap-mode-buttons button')
@ -345,3 +355,7 @@ Array.prototype.slice.call(
btn.classList.add('active'); btn.classList.add('active');
}); });
}); });
document.querySelector('.export-heatmap').addEventListener('click', (e) => {
heatmapChart.export();
});

View File

@ -49,6 +49,12 @@ var HEATMAP_COLORS_YELLOW = ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001
// Universal constants // Universal constants
/**
* Returns the value of a number upto 2 decimal places.
* @param {Number} d Any number
*/
/** /**
* Returns whether or not two given arrays are equal. * Returns whether or not two given arrays are equal.
* @param {Array} arr1 First array * @param {Array} arr1 First array
@ -118,7 +124,6 @@ var MONTH_NAMES_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
// https://stackoverflow.com/a/11252167/6495043
function clone(date) { function clone(date) {
@ -159,6 +164,8 @@ function addDays(date, numberOfDays) {
date.setDate(date.getDate() + numberOfDays); date.setDate(date.getDate() + numberOfDays);
} }
// Composite Chart
// ================================================================================
var reportCountList = [152, 222, 199, 287, 534, 709, 1179, 1256, 1632, 1856, 1850]; var reportCountList = [152, 222, 199, 287, 534, 709, 1179, 1256, 1632, 1856, 1850];
var lineCompositeData = { var lineCompositeData = {
@ -378,7 +385,9 @@ Array.prototype.slice.call(document.querySelectorAll('.aggr-type-buttons button'
}); });
}); });
aggrChart.export(); document.querySelector('.export-aggr').addEventListener('click', function (e) {
aggrChart.export();
});
// Update values chart // Update values chart
// ================================================================================ // ================================================================================
@ -465,6 +474,10 @@ chartUpdateButtons.querySelector('[data-update="remove"]').addEventListener("cli
updateChart.removeDataPoint(); updateChart.removeDataPoint();
}); });
document.querySelector('.export-update').addEventListener('click', function (e) {
updateChart.export();
});
// Trends Chart // Trends Chart
// ================================================================================ // ================================================================================
@ -485,7 +498,7 @@ var plotChartArgs = {
} }
}; };
new Chart("#chart-trends", plotChartArgs); var trendsChart = new Chart("#chart-trends", plotChartArgs);
Array.prototype.slice.call(document.querySelectorAll('.chart-plot-buttons button')).map(function (el) { Array.prototype.slice.call(document.querySelectorAll('.chart-plot-buttons button')).map(function (el) {
el.addEventListener('click', function (e) { el.addEventListener('click', function (e) {
@ -510,6 +523,10 @@ Array.prototype.slice.call(document.querySelectorAll('.chart-plot-buttons button
}); });
}); });
document.querySelector('.export-trends').addEventListener('click', function (e) {
trendsChart.export();
});
// Event chart // Event chart
// ================================================================================ // ================================================================================
@ -556,7 +573,7 @@ var heatmapArgs = {
colors: HEATMAP_COLORS_BLUE, colors: HEATMAP_COLORS_BLUE,
legendScale: [0, 1, 2, 4, 5] legendScale: [0, 1, 2, 4, 5]
}; };
new Chart("#chart-heatmap", heatmapArgs); var heatmapChart = new Chart("#chart-heatmap", heatmapArgs);
Array.prototype.slice.call(document.querySelectorAll('.heatmap-mode-buttons button')).map(function (el) { Array.prototype.slice.call(document.querySelectorAll('.heatmap-mode-buttons button')).map(function (el) {
el.addEventListener('click', function (e) { el.addEventListener('click', function (e) {
@ -617,5 +634,9 @@ Array.prototype.slice.call(document.querySelectorAll('.heatmap-color-buttons but
}); });
}); });
document.querySelector('.export-heatmap').addEventListener('click', function (e) {
heatmapChart.export();
});
}()); }());
//# sourceMappingURL=index.min.js.map //# sourceMappingURL=index.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -100,7 +100,7 @@
<button type="button" class="btn btn-sm btn-secondary" data-type='pie'>Pie Chart</button> <button type="button" class="btn btn-sm btn-secondary" data-type='pie'>Pie Chart</button>
<button type="button" class="btn btn-sm btn-secondary" data-type='percentage'>Percentage Chart</button> <button type="button" class="btn btn-sm btn-secondary" data-type='percentage'>Percentage Chart</button>
</div> </div>
<button type="button" class="btn btn-sm btn-tertiary" data-type='export'>Export</button> <button type="button" class="btn btn-sm btn-tertiary export-aggr">Export</button>
<!-- <p class="text-muted"> <!-- <p class="text-muted">
<a target="_blank" href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts">Why Percentage?</a> <a target="_blank" href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts">Why Percentage?</a>
</p> --> </p> -->
@ -117,6 +117,7 @@
<button type="button" class="btn btn-sm btn-secondary" data-update="random">Random Data</button> <button type="button" class="btn btn-sm btn-secondary" data-update="random">Random Data</button>
<button type="button" class="btn btn-sm btn-secondary" data-update="add">Add Value</button> <button type="button" class="btn btn-sm btn-secondary" data-update="add">Add Value</button>
<button type="button" class="btn btn-sm btn-secondary" data-update="remove">Remove Value</button> <button type="button" class="btn btn-sm btn-secondary" data-update="remove">Remove Value</button>
<button type="button" class="btn btn-sm btn-tertiary export-update">Export</button>
</div> </div>
</div> </div>
</div> </div>
@ -133,6 +134,7 @@
<button type="button" class="btn btn-sm btn-secondary active" data-type="heatline">HeatLine</button> <button type="button" class="btn btn-sm btn-secondary active" data-type="heatline">HeatLine</button>
<button type="button" class="btn btn-sm btn-secondary" data-type="regionFill">Region</button> <button type="button" class="btn btn-sm btn-secondary" data-type="regionFill">Region</button>
</div> </div>
<button type="button" class="btn btn-sm btn-tertiary export-trends">Export</button>
<!-- <pre><code class="hljs javascript margin-vertical-px"> ... <!-- <pre><code class="hljs javascript margin-vertical-px"> ...
lineOptions: 'line', // Line Chart specific properties: lineOptions: 'line', // Line Chart specific properties:
@ -192,6 +194,7 @@
<button type="button" class="btn btn-sm btn-secondary active" data-color="blue">Blue</button> <button type="button" class="btn btn-sm btn-secondary active" data-color="blue">Blue</button>
<button type="button" class="btn btn-sm btn-secondary" data-color="halloween">GitHub's Halloween</button> <button type="button" class="btn btn-sm btn-secondary" data-color="halloween">GitHub's Halloween</button>
</div> </div>
<button type="button" class="btn btn-sm btn-tertiary export-heatmap">Export</button>
<pre><code class="hljs javascript margin-vertical-px"> let heatmap = new Chart("#heatmap", { <pre><code class="hljs javascript margin-vertical-px"> let heatmap = new Chart("#heatmap", {
type: 'heatmap', type: 'heatmap',
height: 115, height: 115,

View File

@ -6,8 +6,8 @@ import { BASE_CHART_TOP_MARGIN, BASE_CHART_LEFT_MARGIN,
ALL_CHART_TYPES, COMPATIBLE_CHARTS, DATA_COLOR_DIVISIONS} from '../utils/constants'; ALL_CHART_TYPES, COMPATIBLE_CHARTS, DATA_COLOR_DIVISIONS} from '../utils/constants';
import { getColor, isValidColor } from '../utils/colors'; import { getColor, isValidColor } from '../utils/colors';
import { runSMILAnimation } from '../utils/animation'; import { runSMILAnimation } from '../utils/animation';
import { downloadFile, prepareForExport } from '../utils/export';
import { Chart } from '../chart'; import { Chart } from '../chart';
import { CSSTEXT } from '../../css/chartsCss';
export default class BaseChart { export default class BaseChart {
constructor(parent, options) { constructor(parent, options) {
@ -53,8 +53,8 @@ export default class BaseChart {
this.setMargins(); this.setMargins();
// Bind window events // Bind window events
window.addEventListener('resize', () => this.draw(true)); window.addEventListener('resize', () => this.boundDrawFn);
window.addEventListener('orientationchange', () => this.draw(true)); window.addEventListener('orientationchange', () => this.boundDrawFn);
} }
validateColors(colors, type) { validateColors(colors, type) {
@ -328,44 +328,17 @@ export default class BaseChart {
return new Chart(this.parent, args); return new Chart(this.parent, args);
} }
boundDrawFn() {
this.draw(true);
}
unbindWindowEvents(){ unbindWindowEvents(){
window.removeEventListener('resize', () => this.draw(true)); window.removeEventListener('resize', () => this.boundDrawFn);
window.removeEventListener('orientationchange', () => this.draw(true)); window.removeEventListener('orientationchange', () => this.boundDrawFn);
} }
export() { export() {
let chartSvg = this.prepareForExport(); let chartSvg = prepareForExport(this.svg);
this.downloadFile(this.title || 'Chart', [chartSvg]); downloadFile(this.title || 'Chart', [chartSvg]);
}
downloadFile(filename, data) {
var a = document.createElement('a');
a.style = "display: none";
var blob = new Blob(data, {type: "image/svg+xml; charset=utf-8"});
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function(){
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 300);
}
prepareForExport() {
let clone = this.svg.cloneNode(true);
clone.classList.add('chart-container');
clone.setAttribute('xmlns', "http://www.w3.org/2000/svg");
clone.setAttribute('xmlns:xlink', "http://www.w3.org/1999/xlink");
let styleEl = $.create('style', {
'innerHTML': CSSTEXT
});
clone.insertBefore(styleEl, clone.firstChild);
let container = $.create('div');
container.appendChild(clone);
return container.innerHTML;
} }
} }

33
src/js/utils/export.js Normal file
View File

@ -0,0 +1,33 @@
import { $ } from '../utils/dom';
import { CSSTEXT } from '../../css/chartsCss';
export function downloadFile(filename, data) {
var a = document.createElement('a');
a.style = "display: none";
var blob = new Blob(data, {type: "image/svg+xml; charset=utf-8"});
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function(){
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 300);
}
export function prepareForExport(svg) {
let clone = svg.cloneNode(true);
clone.classList.add('chart-container');
clone.setAttribute('xmlns', "http://www.w3.org/2000/svg");
clone.setAttribute('xmlns:xlink', "http://www.w3.org/1999/xlink");
let styleEl = $.create('style', {
'innerHTML': CSSTEXT
});
clone.insertBefore(styleEl, clone.firstChild);
let container = $.create('div');
container.appendChild(clone);
return container.innerHTML;
}