@@ -21,12 +21,18 @@ class BasePDFPageView {
2121
2222 #loadingId = null ;
2323
24+ #minDurationToUpdateCanvas = 0 ;
25+
2426 #renderError = null ;
2527
2628 #renderingState = RenderingStates . INITIAL ;
2729
2830 #showCanvas = null ;
2931
32+ #startTime = 0 ;
33+
34+ #tempCanvas = null ;
35+
3036 canvas = null ;
3137
3238 /** @type {null | HTMLDivElement } */
@@ -51,6 +57,7 @@ class BasePDFPageView {
5157 this . id = options . id ;
5258 this . pageColors = options . pageColors || null ;
5359 this . renderingQueue = options . renderingQueue ;
60+ this . #minDurationToUpdateCanvas = options . minDurationToUpdateCanvas ?? 500 ;
5461 }
5562
5663 get renderingState ( ) {
@@ -71,6 +78,9 @@ class BasePDFPageView {
7178 switch ( state ) {
7279 case RenderingStates . PAUSED :
7380 this . div . classList . remove ( "loading" ) ;
81+ // Display the canvas as it has been drawn.
82+ this . #startTime = 0 ;
83+ this . #showCanvas?. ( false ) ;
7484 break ;
7585 case RenderingStates . RUNNING :
7686 this . div . classList . add ( "loadingIcon" ) ;
@@ -82,10 +92,12 @@ class BasePDFPageView {
8292 this . div . classList . add ( "loading" ) ;
8393 this . #loadingId = null ;
8494 } , 0 ) ;
95+ this . #startTime = Date . now ( ) ;
8596 break ;
8697 case RenderingStates . INITIAL :
8798 case RenderingStates . FINISHED :
8899 this . div . classList . remove ( "loadingIcon" , "loading" ) ;
100+ this . #startTime = 0 ;
89101 break ;
90102 }
91103 }
@@ -100,10 +112,41 @@ class BasePDFPageView {
100112 // have a final flash we just display it once all the drawing is done.
101113 const updateOnFirstShow = ! prevCanvas && ! hasHCM && ! hideUntilComplete ;
102114
103- const canvas = ( this . canvas = document . createElement ( "canvas" ) ) ;
115+ let canvas = ( this . canvas = document . createElement ( "canvas" ) ) ;
104116
105117 this . #showCanvas = isLastShow => {
106118 if ( updateOnFirstShow ) {
119+ let tempCanvas = this . #tempCanvas;
120+ if ( ! isLastShow && this . #minDurationToUpdateCanvas > 0 ) {
121+ // We draw on the canvas at 60fps (in using `requestAnimationFrame`),
122+ // so if the canvas is large, updating it at 60fps can be a way too
123+ // much and can cause some serious performance issues.
124+ // To avoid that we only update the canvas every
125+ // `this.#minDurationToUpdateCanvas` ms.
126+
127+ if ( Date . now ( ) - this . #startTime < this . #minDurationToUpdateCanvas) {
128+ return ;
129+ }
130+ if ( ! tempCanvas ) {
131+ tempCanvas = this . #tempCanvas = canvas ;
132+ canvas = this . canvas = canvas . cloneNode ( false ) ;
133+ onShow ( canvas ) ;
134+ }
135+ }
136+
137+ if ( tempCanvas ) {
138+ const ctx = canvas . getContext ( "2d" , {
139+ alpha : false ,
140+ } ) ;
141+ ctx . drawImage ( tempCanvas , 0 , 0 ) ;
142+ if ( isLastShow ) {
143+ this . #resetTempCanvas( ) ;
144+ } else {
145+ this . #startTime = Date . now ( ) ;
146+ }
147+ return ;
148+ }
149+
107150 // Don't add the canvas until the first draw callback, or until
108151 // drawing is complete when `!this.renderingQueue`, to prevent black
109152 // flickering.
@@ -152,6 +195,14 @@ class BasePDFPageView {
152195 canvas . remove ( ) ;
153196 canvas . width = canvas . height = 0 ;
154197 this . canvas = null ;
198+ this . #resetTempCanvas( ) ;
199+ }
200+
201+ #resetTempCanvas( ) {
202+ if ( this . #tempCanvas) {
203+ this . #tempCanvas. width = this . #tempCanvas. height = 0 ;
204+ this . #tempCanvas = null ;
205+ }
155206 }
156207
157208 async _drawCanvas ( options , onCancel , onFinish ) {
0 commit comments