From 730642fb4ed7224f57a5a7fb39a80f6c16344e1d Mon Sep 17 00:00:00 2001 From: Przemek Wiech Date: Sun, 3 Mar 2019 01:17:44 +0100 Subject: [PATCH] Added 'Download PDF' option using jsPDF. --- package.json | 2 ++ src/app.tsx | 3 ++- src/chart.tsx | 49 +++++++++++++++++++++++++++++----------- src/top_bar.tsx | 6 ++++- src/translations/pl.json | 1 + 5 files changed, 46 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index fcb783a..fbe1ad5 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "detect-browser": "^4.1.0", "file-saver": "^2.0.1", "history": "^4.7.2", + "jspdf": "^1.5.3", "md5": "^2.2.1", "query-string": "^5.1.1", "react": "latest", @@ -23,6 +24,7 @@ "@types/file-saver": "^2.0.0", "@types/history": "^4.7.2", "@types/jest": "*", + "@types/jspdf": "^1.2.2", "@types/md5": "^2.1.33", "@types/node": "*", "@types/query-string": "^6.2.0", diff --git a/src/app.tsx b/src/app.tsx index 8f3a0c4..b1374fd 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -169,8 +169,9 @@ export class App extends React.Component { ) } onPrint={() => this.chartRef && this.chartRef.print()} - onDownloadSvg={() => this.chartRef && this.chartRef.downloadSvg()} + onDownloadPdf={() => this.chartRef && this.chartRef.downloadPdf()} onDownloadPng={() => this.chartRef && this.chartRef.downloadPng()} + onDownloadSvg={() => this.chartRef && this.chartRef.downloadSvg()} /> )} /> diff --git a/src/chart.tsx b/src/chart.tsx index d5e15a5..cdbf122 100644 --- a/src/chart.tsx +++ b/src/chart.tsx @@ -1,6 +1,6 @@ import * as d3 from 'd3'; import * as React from 'react'; -import canvg from 'canvg'; +import jsPDF from 'jspdf'; import {intlShape} from 'react-intl'; import {saveAs} from 'file-saver'; import { @@ -167,7 +167,7 @@ export class Chart extends React.PureComponent { saveAs(blob, 'topola.svg'); } - downloadPng() { + drawOnCanvas(): Promise { const canvas = document.createElement('canvas'); // Scale image for better quality. @@ -176,18 +176,41 @@ export class Chart extends React.PureComponent { canvas.height = svg.getBBox().height * 2; const blob = new Blob([this.getSvgContents()], {type: 'image/svg+xml'}); - const img = new Image(); - img.onload = () => { - const ctx = canvas.getContext('2d')!; - ctx.drawImage(img, 0, 0, canvas.width, canvas.height); - const onBlob = (blob: Blob | null) => { - if (blob) { - saveAs(blob, 'topola.png'); - } - }; - canvas.toBlob(onBlob, 'image/png'); - }; img.src = URL.createObjectURL(blob); + + return new Promise((resolve) => { + img.onload = () => { + const ctx = canvas.getContext('2d')!; + const oldFill = ctx.fillStyle; + ctx.fillStyle = 'white'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = oldFill; + + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + resolve(canvas); + }; + }); + } + + downloadPng() { + const onBlob = (blob: Blob | null) => { + if (blob) { + saveAs(blob, 'topola.png'); + } + }; + this.drawOnCanvas().then((canvas) => canvas.toBlob(onBlob, 'image/png')); + } + + downloadPdf() { + this.drawOnCanvas().then((canvas) => { + const doc = new jsPDF({ + orientation: canvas.width > canvas.height ? 'l' : 'p', + unit: 'pt', + format: [canvas.width, canvas.height], + }); + doc.addImage(canvas, 'PNG', 0, 0, canvas.width, canvas.height, 'NONE'); + doc.save('topola.pdf'); + }); } } diff --git a/src/top_bar.tsx b/src/top_bar.tsx index 95f0380..1e8f938 100644 --- a/src/top_bar.tsx +++ b/src/top_bar.tsx @@ -24,8 +24,9 @@ interface State { interface Props { showingChart: boolean; onPrint: () => void; - onDownloadSvg: () => void; + onDownloadPdf: () => void; onDownloadPng: () => void; + onDownloadSvg: () => void; } export class TopBar extends React.Component< @@ -161,6 +162,9 @@ export class TopBar extends React.Component< className="item" > + this.props.onDownloadPdf()}> + + this.props.onDownloadPng()}> diff --git a/src/translations/pl.json b/src/translations/pl.json index d9a7fe8..51c2d92 100644 --- a/src/translations/pl.json +++ b/src/translations/pl.json @@ -3,6 +3,7 @@ "menu.load_from_file": "Otwórz plik", "menu.print": "Drukuj", "menu.download": "Pobierz", + "menu.pdf_file": "Plik PDF", "menu.png_file": "Plik PNG", "menu.svg_file": "Plik SVG", "menu.github": "Źródła na GitHub",