diff --git a/src/components/core/defaults.js b/src/components/core/defaults.js index c9d4664ef..521649047 100644 --- a/src/components/core/defaults.js +++ b/src/components/core/defaults.js @@ -6,6 +6,7 @@ export default { speed: 300, cssMode: false, updateOnWindowResize: true, + resizeObserver: false, nested: false, // Overrides diff --git a/src/modules/resize/resize.js b/src/modules/resize/resize.js index 90c4d1056..27e9e0c25 100644 --- a/src/modules/resize/resize.js +++ b/src/modules/resize/resize.js @@ -1,12 +1,45 @@ import { getWindow } from 'ssr-window'; import { extend } from '../../utils/utils'; +const supportsResizeObserver = () => { + const window = getWindow(); + return typeof window.ResizeObserver !== 'undefined'; +}; + export default { name: 'resize', create() { const swiper = this; extend(swiper, { resize: { + observer: null, + createObserver() { + if (!swiper || swiper.destroyed || !swiper.initialized) return; + swiper.resize.observer = new ResizeObserver((entries) => { + const { width, height } = swiper; + let newWidth = width; + let newHeight = height; + entries.forEach(({ contentBoxSize, contentRect, target }) => { + if (target && target !== swiper.el) return; + newWidth = contentRect + ? contentRect.width + : (contentBoxSize[0] || contentBoxSize).inlineSize; + newHeight = contentRect + ? contentRect.height + : (contentBoxSize[0] || contentBoxSize).blockSize; + }); + if (newWidth !== width || newHeight !== height) { + swiper.resize.resizeHandler(); + } + }); + swiper.resize.observer.observe(swiper.el); + }, + removeObserver() { + if (swiper.resize.observer && swiper.resize.observer.unobserve && swiper.el) { + swiper.resize.observer.unobserve(swiper.el); + swiper.resize.observer = null; + } + }, resizeHandler() { if (!swiper || swiper.destroyed || !swiper.initialized) return; swiper.emit('beforeResize'); @@ -22,6 +55,10 @@ export default { on: { init(swiper) { const window = getWindow(); + if (swiper.params.resizeObserver && supportsResizeObserver()) { + swiper.resize.createObserver(); + return; + } // Emit resize window.addEventListener('resize', swiper.resize.resizeHandler); @@ -30,6 +67,7 @@ export default { }, destroy(swiper) { const window = getWindow(); + swiper.resize.removeObserver(); window.removeEventListener('resize', swiper.resize.resizeHandler); window.removeEventListener('orientationchange', swiper.resize.orientationChangeHandler); }, diff --git a/src/types/swiper-options.d.ts b/src/types/swiper-options.d.ts index 2cf46b7ff..a743e216d 100644 --- a/src/types/swiper-options.d.ts +++ b/src/types/swiper-options.d.ts @@ -36,6 +36,13 @@ export interface SwiperOptions { */ updateOnWindowResize?: boolean; + /** + * When enabled it will use ResizeObserver (if supported by browser) on swiper container to detect container resize (instead of watching for window resize) + * + * @default false + */ + resizeObserver?: boolean; + /** * Index number of initial slide. *