integrated html2canvas and jsPDF to generate PDFs

This commit is contained in:
Amruth Pillai
2020-03-31 20:53:25 +05:30
parent d91aafce91
commit 719ef17501
10 changed files with 272 additions and 17 deletions

View File

@ -1,23 +1,31 @@
import React, { useEffect, useContext, Suspense } from 'react';
import React, { useRef, useEffect, useContext, Suspense } from 'react';
import { useTranslation } from 'react-i18next';
import AppContext from '../../context/AppContext';
import PageContext from '../../context/PageContext';
import LeftSidebar from '../LeftSidebar/LeftSidebar';
import RightSidebar from '../RightSidebar/RightSidebar';
import templates from '../../templates';
const App = () => {
const pageRef = useRef(null);
const { i18n } = useTranslation();
const context = useContext(AppContext);
const { state, dispatch } = context;
const { theme, settings } = state;
const pageContext = useContext(PageContext);
const { setPageElement } = pageContext;
useEffect(() => {
setPageElement(pageRef);
i18n.changeLanguage(settings.language);
const storedState = JSON.parse(localStorage.getItem('state'));
dispatch({ type: 'import_data', payload: storedState });
}, [dispatch, i18n, settings.language]);
}, [dispatch, setPageElement, i18n, settings.language]);
return (
<Suspense fallback="Loading...">
@ -25,11 +33,7 @@ const App = () => {
<LeftSidebar />
<div className="z-0 h-screen col-span-3 flex justify-center items-center overflow-scroll">
<div
id="page"
className="animated fadeIn my-auto shadow-2xl"
style={{ animationDelay: '500ms' }}
>
<div id="page" ref={pageRef} className="my-auto shadow-2xl">
{templates.find(x => theme.layout.toLowerCase() === x.key).component()}
</div>
</div>

View File

@ -43,7 +43,7 @@ const RightSidebar = () => {
name: t('about.title'),
},
];
const [currentTab, setCurrentTab] = useState(tabs[0].key);
const [currentTab, setCurrentTab] = useState(tabs[3].key);
const onChange = (key, value) => {
dispatch({

View File

@ -1,9 +1,16 @@
/* eslint-disable new-cap */
/* eslint-disable jsx-a11y/anchor-has-content */
/* eslint-disable jsx-a11y/anchor-is-valid */
import React, { useRef } from 'react';
import React, { useRef, useContext } from 'react';
import { useTranslation, Trans } from 'react-i18next';
import html2canvas from 'html2canvas';
import * as jsPDF from 'jspdf';
import PageContext from '../../../context/PageContext';
const ActionsTab = ({ data, theme, dispatch }) => {
const pageContext = useContext(PageContext);
const { pageElement } = pageContext;
const { t } = useTranslation('rightSidebar');
const fileInputRef = useRef(null);
@ -17,6 +24,35 @@ const ActionsTab = ({ data, theme, dispatch }) => {
fr.readAsText(event.target.files[0]);
};
const printAsPdf = () => {
pageElement.current.style.maxHeight = 'fit-content';
pageElement.current.style.overflow = 'visible';
html2canvas(pageElement.current, {
useCORS: true,
allowTaint: true,
}).then(canvas => {
pageElement.current.style.maxHeight = '29.7cm';
pageElement.current.style.overflow = 'scroll';
const image = canvas.toDataURL('image/jpeg', 1.0);
const doc = new jsPDF('p', 'px', 'a4');
const pageWidth = doc.internal.pageSize.getWidth();
const pageHeight = doc.internal.pageSize.getHeight();
const widthRatio = pageWidth / canvas.width;
const heightRatio = pageHeight / canvas.height;
const ratio = widthRatio > heightRatio ? heightRatio : widthRatio;
const canvasWidth = canvas.width * ratio;
const canvasHeight = canvas.height * ratio;
const marginX = (pageWidth - canvasWidth) / 2;
const marginY = (pageHeight - canvasHeight) / 2;
doc.addImage(image, 'JPEG', marginX, marginY, canvasWidth, canvasHeight);
doc.output('dataurlnewwindow');
});
};
const exportToJson = () => {
const backupObj = { data, theme };
const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(backupObj))}`;
@ -90,7 +126,7 @@ const ActionsTab = ({ data, theme, dispatch }) => {
<button
type="button"
onClick={() => window.print()}
onClick={printAsPdf}
className="mt-4 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex justify-center items-center">