PdfViewer.tsx 4.1 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 { 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. if (watermark.obj_attr.type) {
  53. addAnnots([...annotations, watermark]);
  54. updateWatermark(watermark.obj_attr);
  55. } else {
  56. addAnnots(annotations);
  57. }
  58. })
  59. .catch((error) => {
  60. console.log(error);
  61. });
  62. };
  63. const pdfGenerator = async (): Promise<any> => {
  64. const parsed = queryString.parse(window.location.search);
  65. if (parsed.token) {
  66. const token = parsed.token as string;
  67. const result = await initialPdfFile(token);
  68. getXfdfFile(token);
  69. setInfo({
  70. token: parsed.token,
  71. id: result.data.transaction_id,
  72. });
  73. const iPdf = await fetchPdf(
  74. `${config.API_HOST}${apiPath.getOriginalPdfFile}?transaction_id=${result.data.transaction_id}`,
  75. setLoadingProgress(result.data.size),
  76. );
  77. setTotalPage(iPdf.numPages);
  78. setPdf(iPdf);
  79. const page = await iPdf.getPage(1);
  80. const iViewport = page.getViewport({ scale: 1 });
  81. iViewport.width = Math.round(iViewport.width);
  82. iViewport.height = Math.round(iViewport.height);
  83. const screenWidth = window.document.body.offsetWidth - 5;
  84. const originPdfWidth = iViewport.width;
  85. const rate = (screenWidth / originPdfWidth).toFixed(2);
  86. changeScale(rate);
  87. }
  88. };
  89. const changePdfContainerScale = (): void => {
  90. for (let i = 1; i <= totalPage; i += 1) {
  91. const ele: HTMLDivElement = document.getElementById(`page_${i}`) 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('page_1') as HTMLDivElement;
  103. const page = Math.round((state.lastY + ele.offsetHeight / 1.4) / (ele.offsetHeight + 50));
  104. if (page !== currentPageRef.current) {
  105. setCurrentPage(page);
  106. }
  107. };
  108. useEffect(() => {
  109. pdfGenerator();
  110. }, []);
  111. useEffect(() => {
  112. currentPageRef.current = currentPage;
  113. }, [currentPage]);
  114. useEffect(() => {
  115. if (pdf) {
  116. changePdfContainerScale();
  117. }
  118. }, [viewport]);
  119. useEffect(() => {
  120. if (pdf) {
  121. getViewport(pdf, scale);
  122. }
  123. }, [scale]);
  124. return (
  125. viewport.width ? (
  126. <PdfPages scrollToUpdate={scrollToUpdate} />
  127. ) : null
  128. );
  129. };
  130. export default PdfViewer;