PdfViewer.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import React, { useEffect, useRef } from 'react';
  2. import queryString from 'query-string';
  3. import config from '../config';
  4. import apiPath from '../constants/apiPath';
  5. import { initialPdfFile, fetchXfdf } from '../apis';
  6. import PdfPages from './PdfPages';
  7. import { fetchPdf } from '../helpers/pdf';
  8. import { ProgressType, ScrollStateType } from '../constants/type';
  9. import { scrollIntoView } from '../helpers/utility';
  10. import { parseAnnotationFromXml } from '../helpers/annotation';
  11. import { parseWatermarkFromXml } from '../helpers/watermark';
  12. import useActions from '../actions';
  13. import useStore from '../store';
  14. const PdfViewer: React.FC = () => {
  15. const [{
  16. viewport,
  17. pdf,
  18. scale,
  19. currentPage,
  20. totalPage,
  21. }, dispatch] = useStore();
  22. const {
  23. setTotalPage,
  24. setPdf,
  25. setProgress,
  26. setViewport,
  27. setCurrentPage,
  28. setInfo,
  29. addAnnots,
  30. changeScale,
  31. updateWatermark,
  32. } = useActions(dispatch);
  33. const currentPageRef = useRef(0);
  34. const setLoadingProgress = (totalSize: number) => (progress: ProgressType): void => {
  35. setProgress({
  36. total: totalSize,
  37. loaded: progress.loaded,
  38. });
  39. };
  40. const getViewport = async (pdfEle: any, s: number): Promise<any> => {
  41. const page = await pdfEle.getPage(1);
  42. const iViewport = page.getViewport({ scale: s });
  43. iViewport.width = Math.round(iViewport.width);
  44. iViewport.height = Math.round(iViewport.height);
  45. setViewport(iViewport);
  46. };
  47. const getXfdfFile = (token: string): void => {
  48. fetchXfdf(token)
  49. .then((xfdf) => {
  50. const annotations = parseAnnotationFromXml(xfdf);
  51. const watermark = parseWatermarkFromXml(xfdf);
  52. addAnnots([...annotations, watermark]);
  53. updateWatermark(watermark.obj_attr);
  54. })
  55. .catch((error) => {
  56. console.log(error);
  57. });
  58. };
  59. const pdfGenerator = async (): Promise<any> => {
  60. const parsed = queryString.parse(window.location.search);
  61. if (parsed.token) {
  62. const token = parsed.token as string;
  63. const result = await initialPdfFile(token);
  64. getXfdfFile(token);
  65. setInfo({
  66. token: parsed.token,
  67. id: result.data.transaction_id,
  68. });
  69. const iPdf = await fetchPdf(
  70. `${config.API_HOST}${apiPath.getOriginalPdfFile}?transaction_id=${result.data.transaction_id}`,
  71. setLoadingProgress(result.data.size),
  72. );
  73. setTotalPage(iPdf.numPages);
  74. setPdf(iPdf);
  75. const page = await iPdf.getPage(1);
  76. const iViewport = page.getViewport({ scale: 1 });
  77. iViewport.width = Math.round(iViewport.width);
  78. iViewport.height = Math.round(iViewport.height);
  79. const screenWidth = window.document.body.offsetWidth - 5;
  80. const originPdfWidth = iViewport.width;
  81. const rate = (screenWidth / originPdfWidth).toFixed(2);
  82. changeScale(rate);
  83. }
  84. };
  85. const changePdfContainerScale = (): void => {
  86. for (let i = 1; i <= totalPage; i += 1) {
  87. const ele: HTMLDivElement = document.getElementById(`page_${i}`) as HTMLDivElement;
  88. if (ele) {
  89. ele.style.width = `${viewport.width}px`;
  90. ele.style.height = `${viewport.height}px`;
  91. if (i === currentPageRef.current) {
  92. scrollIntoView(ele);
  93. }
  94. }
  95. }
  96. };
  97. const scrollToUpdate = (state: ScrollStateType): void => {
  98. const ele: HTMLDivElement = document.getElementById('page_1') as HTMLDivElement;
  99. const page = Math.round((state.lastY + ele.offsetHeight / 1.4) / (ele.offsetHeight + 50));
  100. if (page !== currentPageRef.current) {
  101. setCurrentPage(page);
  102. }
  103. };
  104. useEffect(() => {
  105. pdfGenerator();
  106. }, []);
  107. useEffect(() => {
  108. currentPageRef.current = currentPage;
  109. }, [currentPage]);
  110. useEffect(() => {
  111. if (pdf) {
  112. changePdfContainerScale();
  113. }
  114. }, [viewport]);
  115. useEffect(() => {
  116. if (pdf) {
  117. getViewport(pdf, scale);
  118. }
  119. }, [scale]);
  120. return (
  121. viewport.width ? (
  122. <PdfPages scrollToUpdate={scrollToUpdate} />
  123. ) : null
  124. );
  125. };
  126. export default PdfViewer;