PdfViewer.tsx 4.0 KB

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