PdfViewer.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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 } 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, fetchXfdf } from '../helpers/annotation';
  11. import useActions from '../actions';
  12. import useStore from '../store';
  13. const PdfViewer: React.FunctionComponent = () => {
  14. const [{
  15. viewport,
  16. pdf,
  17. scale,
  18. currentPage,
  19. totalPage,
  20. }, dispatch] = useStore();
  21. const {
  22. setTotalPage,
  23. setPdf,
  24. setProgress,
  25. setViewport,
  26. setCurrentPage,
  27. setInfo,
  28. addAnnotation,
  29. changeScale,
  30. } = useActions(dispatch);
  31. const currentPageRef = useRef(0);
  32. const setLoadingProgress = (totalSize: number) => (progress: ProgressType): 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 pdfGenerator = async (): Promise<any> => {
  46. const parsed = queryString.parse(window.location.search);
  47. const result = await initialPdfFile(parsed.token as string);
  48. fetchXfdf(parsed.token as string).then((res) => {
  49. if (res) {
  50. const annot = parseAnnotationFromXml(res);
  51. addAnnotation(annot, false);
  52. }
  53. });
  54. if (result.data) {
  55. setInfo({
  56. token: parsed.token,
  57. id: result.data.transaction_id,
  58. });
  59. const iPdf = await fetchPdf(
  60. `${config.API_HOST}${apiPath.getOriginalPdfFile}?transaction_id=${result.data.transaction_id}`,
  61. setLoadingProgress(result.data.size),
  62. );
  63. setTotalPage(iPdf.numPages);
  64. setPdf(iPdf);
  65. const page = await iPdf.getPage(1);
  66. const iViewport = page.getViewport({ scale: 1 });
  67. iViewport.width = Math.round(iViewport.width);
  68. iViewport.height = Math.round(iViewport.height);
  69. const screenwidth = window.screen.width - 200;
  70. const originPdfWidth = iViewport.width / 1;
  71. const rate = screenwidth / originPdfWidth;
  72. changeScale(rate);
  73. }
  74. };
  75. const changePdfContainerScale = (): void => {
  76. for (let i = 1; i <= totalPage; i += 1) {
  77. const ele: HTMLDivElement = document.getElementById(`page_${i}`) as HTMLDivElement;
  78. if (ele) {
  79. ele.style.width = `${viewport.width}px`;
  80. ele.style.height = `${viewport.height}px`;
  81. if (i === currentPageRef.current) {
  82. scrollIntoView(ele);
  83. }
  84. }
  85. }
  86. };
  87. const scrollToUpdate = (state: ScrollStateType): void => {
  88. const ele: HTMLDivElement = document.getElementById('page_1') as HTMLDivElement;
  89. const page = Math.round((state.lastY + ele.offsetHeight / 1.4) / (ele.offsetHeight + 40));
  90. if (page !== currentPageRef.current) {
  91. setCurrentPage(page);
  92. }
  93. };
  94. useEffect(() => {
  95. pdfGenerator();
  96. }, []);
  97. useEffect(() => {
  98. currentPageRef.current = currentPage;
  99. }, [currentPage]);
  100. useEffect(() => {
  101. if (pdf) {
  102. changePdfContainerScale();
  103. }
  104. }, [viewport]);
  105. useEffect(() => {
  106. if (pdf) {
  107. getViewport(pdf, scale);
  108. }
  109. }, [scale]);
  110. return (
  111. viewport.width ? (
  112. <PdfPages scrollToUpdate={scrollToUpdate} />
  113. ) : null
  114. );
  115. };
  116. export default PdfViewer;