mirror of
https://github.com/PeWu/topola-viewer.git
synced 2026-08-02 17:11:48 +00:00
Added 'Download PDF' option using jsPDF.
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
"detect-browser": "^4.1.0",
|
"detect-browser": "^4.1.0",
|
||||||
"file-saver": "^2.0.1",
|
"file-saver": "^2.0.1",
|
||||||
"history": "^4.7.2",
|
"history": "^4.7.2",
|
||||||
|
"jspdf": "^1.5.3",
|
||||||
"md5": "^2.2.1",
|
"md5": "^2.2.1",
|
||||||
"query-string": "^5.1.1",
|
"query-string": "^5.1.1",
|
||||||
"react": "latest",
|
"react": "latest",
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
"@types/file-saver": "^2.0.0",
|
"@types/file-saver": "^2.0.0",
|
||||||
"@types/history": "^4.7.2",
|
"@types/history": "^4.7.2",
|
||||||
"@types/jest": "*",
|
"@types/jest": "*",
|
||||||
|
"@types/jspdf": "^1.2.2",
|
||||||
"@types/md5": "^2.1.33",
|
"@types/md5": "^2.1.33",
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"@types/query-string": "^6.2.0",
|
"@types/query-string": "^6.2.0",
|
||||||
|
|||||||
@@ -169,8 +169,9 @@ export class App extends React.Component<RouteComponentProps, {}> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
onPrint={() => this.chartRef && this.chartRef.print()}
|
onPrint={() => this.chartRef && this.chartRef.print()}
|
||||||
onDownloadSvg={() => this.chartRef && this.chartRef.downloadSvg()}
|
onDownloadPdf={() => this.chartRef && this.chartRef.downloadPdf()}
|
||||||
onDownloadPng={() => this.chartRef && this.chartRef.downloadPng()}
|
onDownloadPng={() => this.chartRef && this.chartRef.downloadPng()}
|
||||||
|
onDownloadSvg={() => this.chartRef && this.chartRef.downloadSvg()}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import canvg from 'canvg';
|
import jsPDF from 'jspdf';
|
||||||
import {intlShape} from 'react-intl';
|
import {intlShape} from 'react-intl';
|
||||||
import {saveAs} from 'file-saver';
|
import {saveAs} from 'file-saver';
|
||||||
import {
|
import {
|
||||||
@@ -167,7 +167,7 @@ export class Chart extends React.PureComponent<ChartProps, {}> {
|
|||||||
saveAs(blob, 'topola.svg');
|
saveAs(blob, 'topola.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadPng() {
|
drawOnCanvas(): Promise<HTMLCanvasElement> {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
|
|
||||||
// Scale image for better quality.
|
// Scale image for better quality.
|
||||||
@@ -176,18 +176,41 @@ export class Chart extends React.PureComponent<ChartProps, {}> {
|
|||||||
canvas.height = svg.getBBox().height * 2;
|
canvas.height = svg.getBBox().height * 2;
|
||||||
|
|
||||||
const blob = new Blob([this.getSvgContents()], {type: 'image/svg+xml'});
|
const blob = new Blob([this.getSvgContents()], {type: 'image/svg+xml'});
|
||||||
|
|
||||||
const img = new Image();
|
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);
|
img.src = URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
return new Promise<HTMLCanvasElement>((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');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ interface State {
|
|||||||
interface Props {
|
interface Props {
|
||||||
showingChart: boolean;
|
showingChart: boolean;
|
||||||
onPrint: () => void;
|
onPrint: () => void;
|
||||||
onDownloadSvg: () => void;
|
onDownloadPdf: () => void;
|
||||||
onDownloadPng: () => void;
|
onDownloadPng: () => void;
|
||||||
|
onDownloadSvg: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TopBar extends React.Component<
|
export class TopBar extends React.Component<
|
||||||
@@ -161,6 +162,9 @@ export class TopBar extends React.Component<
|
|||||||
className="item"
|
className="item"
|
||||||
>
|
>
|
||||||
<Dropdown.Menu>
|
<Dropdown.Menu>
|
||||||
|
<Dropdown.Item onClick={() => this.props.onDownloadPdf()}>
|
||||||
|
<FormattedMessage id="menu.pdf_file" defaultMessage="PDF file" />
|
||||||
|
</Dropdown.Item>
|
||||||
<Dropdown.Item onClick={() => this.props.onDownloadPng()}>
|
<Dropdown.Item onClick={() => this.props.onDownloadPng()}>
|
||||||
<FormattedMessage id="menu.png_file" defaultMessage="PNG file" />
|
<FormattedMessage id="menu.png_file" defaultMessage="PNG file" />
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"menu.load_from_file": "Otwórz plik",
|
"menu.load_from_file": "Otwórz plik",
|
||||||
"menu.print": "Drukuj",
|
"menu.print": "Drukuj",
|
||||||
"menu.download": "Pobierz",
|
"menu.download": "Pobierz",
|
||||||
|
"menu.pdf_file": "Plik PDF",
|
||||||
"menu.png_file": "Plik PNG",
|
"menu.png_file": "Plik PNG",
|
||||||
"menu.svg_file": "Plik SVG",
|
"menu.svg_file": "Plik SVG",
|
||||||
"menu.github": "Źródła na GitHub",
|
"menu.github": "Źródła na GitHub",
|
||||||
|
|||||||
Reference in New Issue
Block a user