From 7c88b2034e47e676c79be6090cb0217d1c3ed8ef Mon Sep 17 00:00:00 2001 From: Yurii Zusik Date: Mon, 22 Mar 2021 09:41:31 +0200 Subject: [PATCH] feat(storefront): BCTHEME-446 Improve performance of analyzing homepage carousel image --- .../carousel/utils/getActiveSlideInfo.js | 10 ++---- .../carousel/utils/handleImageAspectRatio.js | 28 +++++++++------- .../common/carousel/utils/handleImageLoad.js | 33 ++++++++++++++++--- .../stencil/heroCarousel/_heroCarousel.scss | 9 +++++ 4 files changed, 57 insertions(+), 23 deletions(-) diff --git a/assets/js/theme/common/carousel/utils/getActiveSlideInfo.js b/assets/js/theme/common/carousel/utils/getActiveSlideInfo.js index c5b67c770e..3cdf46b7df 100644 --- a/assets/js/theme/common/carousel/utils/getActiveSlideInfo.js +++ b/assets/js/theme/common/carousel/utils/getActiveSlideInfo.js @@ -5,16 +5,12 @@ export default ({ $slider }, isAnalyzedDataAttr) => { if (isAnalyzedSlide) return { isAnalyzedSlide }; const $activeSlideImg = $activeSlide.find('.heroCarousel-image'); - - const attrsObj = { - src: $activeSlideImg.attr('src'), - srcset: $activeSlideImg.attr('srcset'), - sizes: $activeSlideImg.attr('sizes'), - }; + const activeSlideImgNode = $activeSlideImg[0]; return { - attrsObj, $slider, $activeSlide, + $activeSlideImg, + activeSlideImgNode, }; }; diff --git a/assets/js/theme/common/carousel/utils/handleImageAspectRatio.js b/assets/js/theme/common/carousel/utils/handleImageAspectRatio.js index ef163e433e..daa28603e4 100644 --- a/assets/js/theme/common/carousel/utils/handleImageAspectRatio.js +++ b/assets/js/theme/common/carousel/utils/handleImageAspectRatio.js @@ -17,12 +17,20 @@ const defineClass = (imageAspectRatio) => { } }; +const installClass = (imageNode, $slides) => { + if (imageNode.naturalHeight <= 1) return; + + const imageAspectRatio = imageNode.naturalHeight / imageNode.naturalWidth; + $slides.each((idx, slide) => $(slide).addClass(defineClass(imageAspectRatio))); +}; + export default ({ delegateTarget }, carousel) => { const { isAnalyzedSlide, - attrsObj, $slider, $activeSlide, + $activeSlideImg, + activeSlideImgNode, } = getActiveSlideInfo(carousel || delegateTarget.slick, IS_ANALYZED_DATA_ATTR); if (isAnalyzedSlide) return; @@ -32,15 +40,11 @@ export default ({ delegateTarget }, carousel) => { if ($activeSlide.find('.heroCarousel-content').length) return; - $('') - .on('load', function getImageSizes() { - const imageHeight = this.height; - const imageWidth = this.width; - - if (imageHeight < 2 || imageWidth < 2) return; - - const imageAspectRatio = imageHeight / imageWidth; - $activeSlideAndClones.each((idx, slide) => $(slide).addClass(defineClass(imageAspectRatio))); - }) - .attr(attrsObj); + if (activeSlideImgNode.complete) { + if (activeSlideImgNode.naturalHeight === 1) { + $activeSlideAndClones.each((idx, slide) => $(slide).data(IS_ANALYZED_DATA_ATTR, false)); + } else if (activeSlideImgNode.naturalHeight > 1) { + installClass(activeSlideImgNode, $activeSlideAndClones); + } + } else $activeSlideImg.on('load', () => installClass(activeSlideImgNode, $activeSlideAndClones)); }; diff --git a/assets/js/theme/common/carousel/utils/handleImageLoad.js b/assets/js/theme/common/carousel/utils/handleImageLoad.js index 66572db108..9c6f6b0b3c 100644 --- a/assets/js/theme/common/carousel/utils/handleImageLoad.js +++ b/assets/js/theme/common/carousel/utils/handleImageLoad.js @@ -3,18 +3,43 @@ import getActiveSlideInfo from './getActiveSlideInfo'; const IMAGE_ERROR_CLASS = 'is-image-error'; const IS_ANALYZED_DATA_ATTR = 'image-load-analyzed'; +const generateImage = ($slide, $image) => { + $('') + .on('error', () => $slide.addClass(IMAGE_ERROR_CLASS)) + .attr({ + src: $image.attr('src'), + srcset: $image.attr('srcset'), + sizes: $image.attr('sizes'), + }); +}; + export default (e, carousel) => { const { isAnalyzedSlide, - attrsObj, $activeSlide, + $activeSlideImg, + activeSlideImgNode, } = getActiveSlideInfo(carousel, IS_ANALYZED_DATA_ATTR); if (isAnalyzedSlide) return; $activeSlide.data(IS_ANALYZED_DATA_ATTR, true); - $('') - .on('error', () => $activeSlide.addClass(IMAGE_ERROR_CLASS)) - .attr(attrsObj); + if (activeSlideImgNode.complete) { + if (activeSlideImgNode.naturalHeight === 0) { + $activeSlide.addClass(IMAGE_ERROR_CLASS); + } else if (activeSlideImgNode.naturalHeight === 1) { + generateImage($activeSlide, $activeSlideImg); + } + + return; + } + + // if IE + if (document.documentMode) { + generateImage($activeSlide, $activeSlideImg); + return; + } + + $activeSlideImg.on('error', () => $activeSlide.addClass(IMAGE_ERROR_CLASS)); }; diff --git a/assets/scss/components/stencil/heroCarousel/_heroCarousel.scss b/assets/scss/components/stencil/heroCarousel/_heroCarousel.scss index c109d870eb..10cff12547 100644 --- a/assets/scss/components/stencil/heroCarousel/_heroCarousel.scss +++ b/assets/scss/components/stencil/heroCarousel/_heroCarousel.scss @@ -33,6 +33,15 @@ } } + // for IE + @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { + opacity: 0; + + &.slick-initialized { + opacity: 1; + } + } + &:not(.slick-initialized) :not(.heroCarousel-slide--first).heroCarousel-slide { display: none; }