@@ -127,10 +127,11 @@ export function PdfProvider({ pdfUrl, children }: IPdfProviderProps) {
127127 saveThemeSettingToLocalStorage ( theme ) ;
128128 } , [ theme ] ) ;
129129
130- useScrolling ( {
130+ usePageOffsets ( {
131+ viewer,
132+ services,
131133 pageOffsets,
132134 setVisiblePages,
133- viewer,
134135 } ) ;
135136
136137 const context = useMemo (
@@ -182,49 +183,56 @@ function useScaleUpdater({
182183 } , [ viewer , setScale ] ) ;
183184}
184185
185- function useScrolling ( {
186+ function usePageOffsets ( {
186187 viewer,
188+ services,
187189 setVisiblePages,
188190 pageOffsets,
189191} : {
190192 viewer ?: pdfJsViewer . PDFViewer ;
193+ services : IPdfServices ;
191194 setVisiblePages : Dispatch < SetStateAction < number [ ] > > ;
192195 pageOffsets : MutableRefObject < DOMRect [ ] > ;
193196} ) {
194- const handleViewChanged = useCallback ( ( ) => {
195- // TODO [ToDr] throttle?
196- if ( ! viewer ) return ;
197+ const handleViewChanged = useCallback (
198+ ( forceUpdate : boolean ) => {
199+ // TODO [ToDr] throttle?
200+ if ( ! viewer ) return ;
197201
198- const visiblePagesAfterEvent : number [ ] = [ ] ;
202+ const visiblePagesAfterEvent : number [ ] = [ ] ;
199203
200- for ( let i = 0 ; i < viewer . pagesCount ; i ++ ) {
201- if ( isPartlyInViewport ( viewer . getPageView ( i ) . div . getBoundingClientRect ( ) ) ) {
202- visiblePagesAfterEvent . push ( i + 1 ) ; // using page numbers instead of indices
204+ for ( let i = 0 ; i < viewer . pagesCount ; i ++ ) {
205+ if ( isPartlyInViewport ( viewer . getPageView ( i ) . div . getBoundingClientRect ( ) ) ) {
206+ visiblePagesAfterEvent . push ( i + 1 ) ; // using page numbers instead of indices
207+ }
203208 }
204- }
205209
206- setVisiblePages ( ( visiblePages ) => {
207- if ( visiblePages . join ( ";" ) !== visiblePagesAfterEvent . join ( ";" ) ) {
208- return visiblePagesAfterEvent ;
209- }
210- return visiblePages ;
211- } ) ;
210+ setVisiblePages ( ( visiblePages ) => {
211+ if ( forceUpdate || visiblePages . join ( ";" ) !== visiblePagesAfterEvent . join ( ";" ) ) {
212+ return visiblePagesAfterEvent ;
213+ }
214+ return visiblePages ;
215+ } ) ;
212216
213- for ( let page = 1 ; page <= viewer . pagesCount ; page ++ ) {
214- const pageElement = viewer . getPageView ( page - 1 ) ?. div ;
217+ for ( let page = 1 ; page <= viewer . pagesCount ; page ++ ) {
218+ const pageElement = viewer . getPageView ( page - 1 ) ?. div ;
215219
216- pageOffsets . current [ page ] = subtractBorder (
217- new DOMRect ( pageElement . offsetLeft , pageElement . offsetTop , pageElement . offsetWidth , pageElement . offsetHeight ) ,
218- pageElement ,
219- ) ;
220- }
221- } , [ viewer , setVisiblePages , pageOffsets ] ) ;
220+ pageOffsets . current [ page ] = subtractBorder (
221+ new DOMRect ( pageElement . offsetLeft , pageElement . offsetTop , pageElement . offsetWidth , pageElement . offsetHeight ) ,
222+ pageElement ,
223+ ) ;
224+ }
225+ } ,
226+ [ viewer , setVisiblePages , pageOffsets ] ,
227+ ) ;
222228
223229 // update page offsets on scroll or resize
224230 useEffect ( ( ) => {
225231 if ( ! viewer ?. container ) return ;
226232
227- const handler = handleViewChanged ;
233+ // in case of scroll we don't want to force the update.
234+ // the page offsets do not really changed.
235+ const handler = ( ) => handleViewChanged ( false ) ;
228236 const resizeObserver = new ResizeObserver ( handler ) ;
229237
230238 viewer . container . addEventListener ( "scroll" , handler ) ;
@@ -236,8 +244,23 @@ function useScrolling({
236244 } ;
237245 } , [ viewer , handleViewChanged ] ) ;
238246
247+ // update page offsets when scale is changing
239248 useEffect ( ( ) => {
240- if ( ! viewer ) return ;
241- viewer . container . dispatchEvent ( new CustomEvent ( "scroll" ) ) ;
242- } , [ viewer ] ) ;
249+ if ( ! services . eventBus || ! viewer ) return ;
250+
251+ const { eventBus } = services ;
252+ // in case the scale is changed, we want to force
253+ // new page offsets to be calculated and components
254+ // depending on that re-rendered.
255+ // This happens through `visiblePages` changing, otherwise
256+ // since `pageOffsets` are a ref, we won't see any
257+ // components noticing the change in page offsets, hence
258+ // no rendering would occur.
259+ const handler = ( ) => handleViewChanged ( true ) ;
260+ eventBus . on ( "scalechanging" , handler ) ;
261+
262+ return ( ) => {
263+ eventBus . off ( "scalechanging" , handler ) ;
264+ } ;
265+ } , [ services , viewer , handleViewChanged ] ) ;
243266}
0 commit comments