PdfViewer.tsx 4.1 KB

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