@@ -165,15 +165,34 @@ function _doPlot(gd, data, layout, config) {
165165 gd . calcdata [ i ] [ 0 ] . trace = gd . _fullData [ i ] ;
166166 }
167167
168- // make the figure responsive
168+ // Make the figure responsive. We need to save the callback that clears the
169+ // listener for proper teardown.
169170 if ( gd . _context . responsive ) {
170- if ( ! gd . _responsiveChartObserver ) {
171- // Keep a reference to the resize observer to purge it down the road
172- gd . _responsiveChartObserver = new ResizeObserver ( function ( ) {
171+ if ( ! gd . _clearResponsive ) {
172+ const resizeIfShown = ( ) => {
173173 if ( ! Lib . isHidden ( gd ) ) Plots . resize ( gd ) ;
174- } ) ;
175-
176- gd . _responsiveChartObserver . observe ( gd ) ;
174+ } ;
175+ // We still need the window resize listener for `fillFrame` and an
176+ // escape hatch for browser-like users that don't support `ResizeObserver` (like jsdom)
177+ if ( gd . _context . fillFrame || typeof ResizeObserver === 'undefined' ) {
178+ window . addEventListener ( 'resize' , resizeIfShown ) ;
179+ gd . _clearResponsive = ( ) => window . removeEventListener ( 'resize' , resizeIfShown ) ;
180+ } else {
181+ let previousWidth = gd . offsetWidth ;
182+ let previousHeight = gd . offsetHeight ;
183+ const observer = new ResizeObserver ( ( ) => {
184+ const width = gd . offsetWidth ;
185+ const height = gd . offsetHeight ;
186+ // Ignore size changes of one pixel or less (the same as plotAutoSize)
187+ const changed = Math . abs ( width - previousWidth ) > 1 || Math . abs ( height - previousHeight ) > 1 ;
188+ previousWidth = width ;
189+ previousHeight = height ;
190+ // Only resize plot if it changed and is visible (width and height > 0)
191+ if ( changed && width && height ) resizeIfShown ( ) ;
192+ } ) ;
193+ observer . observe ( gd ) ;
194+ gd . _clearResponsive = ( ) => observer . disconnect ( ) ;
195+ }
177196 }
178197 } else {
179198 Lib . clearResponsive ( gd ) ;
0 commit comments