Skip to content

Commit bba0327

Browse files
committed
fix scrolling fit to height zoom issue
1 parent aad46fe commit bba0327

File tree

7 files changed

+50
-40
lines changed

7 files changed

+50
-40
lines changed

example/index.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,14 @@ const PdfReaders = () => {
136136
instead of taking over the full page. It is fixed height, which
137137
means it will not grow to fit content in scrolling mode.
138138
</Text>
139-
<WebReader
140-
webpubManifestUrl={`${origin}/samples/pdf/single-resource-long.json`}
141-
proxyUrl={pdfProxyUrl}
142-
pdfWorkerSrc={`${origin}/pdf-worker/pdf.worker.min.mjs`}
143-
growWhenScrolling={false}
144-
/>
139+
<Box margin="0 auto" width="50%">
140+
<WebReader
141+
webpubManifestUrl={`${origin}/samples/pdf/single-resource-short.json`}
142+
proxyUrl={pdfProxyUrl}
143+
pdfWorkerSrc={`${origin}/pdf-worker/pdf.worker.min.mjs`}
144+
growWhenScrolling={false}
145+
/>
146+
</Box>
145147
<Heading>The page continues...</Heading>
146148
<Text as="p">Here is some more content below the reader</Text>
147149
</Box>

src/PdfReader/ChakraPage.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { chakra, shouldForwardProp } from '@chakra-ui/react';
22
import React from 'react';
33
import { Page, PageProps } from 'react-pdf';
4-
5-
type FitMode = 'width' | 'height';
4+
import { FitMode } from '../types';
65

76
interface ChakraPageProps extends Omit<PageProps, 'width' | 'height'> {
87
width?: number;

src/PdfReader/index.tsx

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
DEFAULT_HEIGHT,
1313
DEFAULT_SHOULD_GROW_WHEN_SCROLLING,
1414
MAIN_CONTENT_ID,
15+
READER_MARGIN,
1516
} from '../constants';
1617
import LoadingSkeleton from '../ui/LoadingSkeleton';
1718
import { fetchAsUint8Array, getResourceUrl, SCALE_STEP } from './lib';
@@ -128,48 +129,49 @@ export default function usePdfReader(args: PdfReaderArguments): ReaderReturn {
128129
}, [state.resourceIndex, manifest, proxyUrl, getContent]);
129130

130131
/**
131-
* calculate the height or width of the pdf page in paginated mode.
132+
* calculate the height or width of the pdf page to fit to dimensions.
132133
* - if the page's aspect ratio is taller than the container's, we will constrain
133134
* the page to the height of the container.
134135
* - if the page's aspect ratio is wider than the container's, we will constrain
135136
* the page to the width of the container
136137
*/
137138
const resizePage = React.useCallback(
138-
(containerSize: { width: number; height: number }, fitMode: FitMode) => {
139+
(
140+
containerSize: { width: number; height: number },
141+
fitMode: FitMode,
142+
scale: number
143+
) => {
139144
let width, height;
140145
if (fitMode === 'width') {
141-
width = Math.round(containerSize.width);
146+
width = Math.round((containerSize.width - READER_MARGIN) * scale);
142147
height = undefined;
148+
} else if (fitMode === 'height' && state.pdfWidth && state.pdfHeight) {
149+
const aspectRatio = state.pdfHeight / state.pdfWidth;
150+
width = Math.round(
151+
((containerSize.height - READER_MARGIN) / aspectRatio) * scale
152+
);
153+
height = Math.round((containerSize.height - READER_MARGIN) * scale);
143154
} else {
144155
width = undefined;
145-
height = Math.round(containerSize.height);
156+
height = undefined;
146157
}
147158
dispatch({ type: 'RESIZE_PAGE', width, height });
148159
},
149-
[]
160+
[state.pdfWidth, state.pdfHeight]
150161
);
151162

152163
React.useEffect(() => {
153-
resizePage(containerSize, state.fitMode);
154-
}, [containerSize, resizePage, state.fitMode]);
164+
resizePage(containerSize, state.fitMode, state.scale);
165+
}, [containerSize, resizePage, state.fitMode, state.scale]);
155166

156-
const setInitialPageHeight = React.useCallback(() => {
157-
if (
158-
pageHeight === 0 &&
159-
state.pdfWidth &&
160-
state.pdfHeight &&
161-
containerSize.width
162-
) {
163-
const margin = 16;
167+
React.useEffect(() => {
168+
if (state.pdfWidth && state.pdfHeight && pageHeight === 0) {
164169
const aspectRatio = state.pdfHeight / state.pdfWidth;
165-
const initialPageHeight = (containerSize.width - margin) * aspectRatio;
166-
setPageHeight(initialPageHeight);
170+
const initialPageHeight =
171+
(containerSize.width - READER_MARGIN) * aspectRatio;
172+
setPageHeight(Math.round(initialPageHeight));
167173
}
168-
}, [pageHeight, state.pdfWidth, state.pdfHeight, containerSize.width]);
169-
170-
React.useEffect(() => {
171-
setInitialPageHeight();
172-
}, [setInitialPageHeight]);
174+
}, [state.pdfWidth, state.pdfHeight, containerSize.width, pageHeight]);
173175

174176
/**
175177
* Update the atStart/atEnd state to tell the UI whether to show the prev/next buttons
@@ -376,7 +378,7 @@ export default function usePdfReader(args: PdfReaderArguments): ReaderReturn {
376378
width: Math.round(page.width),
377379
});
378380

379-
resizePage(containerSize, state.fitMode);
381+
resizePage(containerSize, state.fitMode, state.scale);
380382
}
381383
}
382384

@@ -401,6 +403,11 @@ export default function usePdfReader(args: PdfReaderArguments): ReaderReturn {
401403
overflowX: 'hidden',
402404
overflowY: 'auto',
403405
},
406+
'.react-pdf__Page': {
407+
width: `${
408+
containerSize.width ? containerSize.width - READER_MARGIN : 0
409+
}px`,
410+
},
404411
}}
405412
>
406413
<Document
@@ -414,7 +421,7 @@ export default function usePdfReader(args: PdfReaderArguments): ReaderReturn {
414421
Array.from(new Array(state.numPages), (_, index) => (
415422
<ScrollPage
416423
key={`page_${index + 1}`}
417-
width={containerSize.width - 16}
424+
width={state.pageWidth}
418425
height={state.pageHeight}
419426
placeholderHeight={state.pdfHeight}
420427
placeholderWidth={state.pdfWidth}

src/PdfReader/pdfReader.css

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@
1111
}
1212

1313
.react-pdf__Page {
14-
display: flex;
15-
flex-direction: column;
16-
align-items: center;
17-
width: 100%;
14+
display: block;
1815
background: #252525 !important;
1916
}
2017

21-
.react-pdf__Page__canvas {
22-
background: #fff !important;
18+
.react-pdf__Page canvas,
19+
.react-pdf__Page .textLayer {
20+
display: block;
21+
margin: 0 auto;
2322
}

src/PdfReader/reducer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ export function makePdfReducer(
193193
return {
194194
...state,
195195
scale: action.scale,
196+
fitMode: undefined,
196197
};
197198

198199
case 'RESET_SETTINGS':
@@ -224,7 +225,7 @@ export function makePdfReducer(
224225
};
225226

226227
case 'SET_FIT_MODE':
227-
return { ...state, fitMode: action.fitMode };
228+
return { ...state, fitMode: action.fitMode, scale: 1 };
228229

229230
case 'BOOK_BOUNDARY_CHANGED':
230231
return {

src/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export const CHROME_HEIGHT = HEADER_HEIGHT;
1111
export const DEFAULT_HEIGHT = `calc(100vh - ${CHROME_HEIGHT}px)`;
1212
export const DEFAULT_SHOULD_GROW_WHEN_SCROLLING = true;
1313

14+
export const READER_MARGIN = 16;
15+
1416
export const DEFAULT_SETTINGS: ReaderSettings = {
1517
colorMode: 'day',
1618
isScrolling: true,

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export type ColorMode = 'night' | 'sepia' | 'day';
1313

1414
export type FontFamily = 'publisher' | 'serif' | 'sans-serif' | 'open-dyslexic';
1515

16-
export type FitMode = 'width' | 'height';
16+
export type FitMode = 'width' | 'height' | undefined;
1717

1818
export type Navigator = {
1919
goForward: () => void;

0 commit comments

Comments
 (0)