推迟图像的延迟加载,直到相关图像开始进入视口

问题描述 投票:0回答:1

我有一小段 Javascript 可以检测浏览器是否已加载图像,然后将

.loaded
类添加到其父级。

img
元素都声明了
loading="lazy"

使用CSS,当添加类时,我会转换/动画出一个占位符图像,该图像位于“主”图像的顶部。占位符图像是一个微小的 16x24 图像,使用

eager
进行拉伸、加载并使用
image-rendering: pixelated;
进行像素化。这提供了相当好的效果 - 由于两个托管图像的加载速度都很慢,因此在示例中可能不会出现这种效果。

问题

据我所知,这一切都有效……但“问题”(在本例中)是所有图像都立即加载。我想知道是否可以推迟在视口之外加载图像,并且仅在图像的 % 进入视口后才加载它们。所以稍后添加该类,您就会看到这种视觉效果。

为什么

原因是,正如你所看到的,我正在使用 JS 轮播。在 iOS 设备上,图像第一次进入视口时会跳转/闪烁到位。但是,如果我删除图像(这样它们就不会加载),像素图像会在您滚动时完美显示。

所以我在想,如果我可以推迟加载主图像/更大的图像,拉伸的像素图像,过渡到主图像看起来会比有一秒钟的空白更好一点。

这个问题很奇怪,因为从技术上讲,图像应该已完全加载,但这对我来说似乎是一个解决方法 - 希望如此。

提前致谢,希望有人能对此给予一些指导!

/* ==========================================================================
   #LAZY LOAD IMAGES
   ========================================================================== */

/**
 * Class to animate/transition an image into view once it has been loaded.
 */

const pixelImage = document.querySelectorAll(".pixel-load")

pixelImage.forEach(div => {
  const img = div.querySelector("img")

  function loaded() {
    div.classList.add("loaded")
  }

  if (img.complete) {
    loaded()
  } else {
    img.addEventListener("load", loaded)
  }
})




/* ==========================================================================
   #KEEN SLIDER
   ========================================================================== */

/**
 * Using Keen-Slider for the infinite looping carousel, which I originally did
 * in pure CSS - but I wanted to make this draggable by the user so made sense
 * to use a 3rd party plug-in to do the heavy lifting.
 */

var animation = {
  duration: 32000,
  easing: (t) => t
}
new KeenSlider("#gallery-slider", {
  dragSpeed: 1,
  loop: true,
  mode: "free",
  slides: {
    perView: 1.5,
    renderMode: "performance",
    spacing: 8
  },
  breakpoints: {
    '(min-width: 768px)': {
      slides: {
        perView: 3,
        spacing: 8
      }
    },
    '(min-width: 1024px)': {
      slides: {
        perView: 4,
        spacing: 8
      }
    }
  },
  created(s) {
    document.querySelector("#gallery-slider").classList.add("loaded");
    s.moveToIdx(5, true, animation);
  },
  updated(s) {
    s.moveToIdx(s.track.details.abs + 5, true, animation);
  },
  animationEnded(s) {
    s.moveToIdx(s.track.details.abs + 5, true, animation);
  }
})
/* ==========================================================================
   #BASE
   ========================================================================== */

html {
  font-size: 62.5%;
  margin: 0;
  padding: 0;
}

body {
  font-size: 12px;
  font-family: "Arial", sans-serif;
  margin: 0;
  padding: 64px 0 0;
  text-transform: uppercase;
}

h2 {
  font-size: 12px;
  font-weight: 400;
  margin: 0 16px 16px;
  padding: 0;
}

figure {
  margin: 0;
  padding: 0;
}

img {
  height: auto;
  width: 100%;
  max-width: 100%;
}


/* ==========================================================================
   #KEEN SLIDER
   ========================================================================== */


/**
 * 1. Removed `overflow: hidden` so I could align the slider with the main grid
 *    but still have it bleed off the edges of the page. To avoid a horizontal
 *    scroll on the site, I've added `overflow: hidden` to a parent div.
 */

.keen-slider:not([data-keen-slider-disabled]) {
  display: flex;
  align-content: flex-start;
  overflow: hidden;
  position: relative;
  touch-action: pan-y;
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  width: 100%;
  -webkit-tap-highlight-color: transparent;
}

.keen-slider:not([data-keen-slider-disabled]) .keen-slider__slide {
  min-height: 100%;
  overflow: hidden;
  position: relative;
  width: 100%;
}

.keen-slider:not([data-keen-slider-disabled])[data-keen-slider-v] {
  flex-wrap: wrap;
}


/* ==========================================================================
   #GALLERY
   ========================================================================== */


/**
 * My overrides for the Keen Slider gallery.
 *
 * 1. Remove `overflow: hidden` from the slider and add it to the parent. This
 *    allows the slider to align with the grid but also bleed off the edges of
 *    the page.
 * 2. Align container with the global grid.
 */

.gallery {
  margin-bottom: 64px;
  overflow: hidden;
  /* [1] */
  padding: 0 16px;
  /* [2] */
}

.gallery .keen-slider {
  overflow: visible;
  /* [1] */
}


/**
 * As the widths for each slide are set in Javascript. We add widths to slides
 * before `.keen-slider` has loaded to keep the layout consistent and help with
 * the Cumulative Layout Shift (CLS) and performance.
 */

.keen-slider:not(.loaded) .keen-slider__slide {
  width: calc((100vw / 1.5) - 24px);
}

@media(min-width: 48em) {
  .keen-slider:not(.loaded) .keen-slider__slide {
    width: calc((100vw - 48px) / 3);
  }
}

@media(min-width: 64rem) {
  .keen-slider:not(.loaded) .keen-slider__slide {
    width: calc((100vw - 56px) / 4);
  }
}


/* ==========================================================================
   #PIXEL LOAD
   ========================================================================== */


/**
 * Add a pixelated effect to images while the load.
 */

.pixel-load {
  overflow: hidden;
  position: relative;
}

.pixel-load__preload img {
  image-rendering: pixelated;
  position: absolute;
  inset: 0;
  opacity: 1;
  pointer-events: none;
}

.loaded .pixel-load__preload img {
  animation: loaded 0.32s 0.32s steps(1, end) both;
}

@keyframes loaded {
  0% {
    scale: 1.1;
  }
  64% {
    scale: 1.04;
  }
  75% {
    opacity: 0.8;
    scale: 1.02;
  }
  100% {
    opacity: 0;
    z-index: 1;
  }
}
<!-- Keen Slider -->
<div class="gallery">
  <div id="gallery-slider" class="keen-slider">
    <div class="keen-slider__slide">
      <figure data-label="Hover Label 1" class="has-label">
        <div class="pixel-load">
          <div class="pixel-load__preload">
            <img src="https://placebeard.it/18/24" width="18" height="24" loading="eager">
          </div>
          <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
        </div>
        <figcaption>Slide 1</figcaption>
      </figure>
    </div>
    <div class="keen-slider__slide">
      <figure data-label="Hover Label 2" class="has-label">
        <div class="pixel-load">
          <div class="pixel-load__preload">
            <img src="https://placebeard.it/18/24" width="18" height="24" loading="eager">
          </div>
          <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
        </div>
        <figcaption>Slide 2</figcaption>
      </figure>
    </div>
    <div class="keen-slider__slide">
      <figure data-label="Hover Label 3" class="has-label">
        <div class="pixel-load">
          <div class="pixel-load__preload">
            <img src="https://placebeard.it/18/24" width="18" height="24" loading="eager">
          </div>
          <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
        </div>
        <figcaption>Slide 3</figcaption>
      </figure>
    </div>
    <div class="keen-slider__slide">
      <figure data-label="Hover Label 4" class="has-label">
        <div class="pixel-load">
          <div class="pixel-load__preload">
            <img src="https://placebeard.it/18/24" width="18" height="24" loading="eager">
          </div>
          <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
        </div>
        <figcaption>Slide 4</figcaption>
      </figure>
    </div>
    <div class="keen-slider__slide">
      <figure data-label="Hover Label 5" class="has-label">
        <div class="pixel-load">
          <div class="pixel-load__preload">
            <img src="https://placebeard.it/18/24" width="18" height="24" loading="eager">
          </div>
          <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
        </div>
        <figcaption>Slide 5</figcaption>
      </figure>
    </div>
    <div class="keen-slider__slide">
      <figure data-label="Hover Label 6" class="has-label">
        <div class="pixel-load">
          <div class="pixel-load__preload">
            <img src="https://placebeard.it/18/24" width="18" height="24" loading="eager">
          </div>
          <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
        </div>
        <figcaption>Slide 6</figcaption>
      </figure>
    </div>
    <div class="keen-slider__slide">
      <figure data-label="Hover Label 7" class="has-label">
        <div class="pixel-load">
          <div class="pixel-load__preload">
            <img src="https://placebeard.it/18/24" width="18" height="24" loading="eager">
          </div>
          <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
        </div>
        <figcaption>Slide 7</figcaption>
      </figure>
    </div>
    <div class="keen-slider__slide">
      <figure data-label="Hover Label 8" class="has-label">
        <div class="pixel-load">
          <div class="pixel-load__preload">
            <img src="https://placebeard.it/18/24" width="18" height="24" loading="eager">
          </div>
          <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
        </div>
        <figcaption>Slide 8</figcaption>
      </figure>
    </div>
  </div>
</div>
<!-- End Keen Slider -->

<script src="https://cdn.jsdelivr.net/npm/[email protected]/keen-slider.min.js"></script>

javascript html css image lazy-loading
1个回答
0
投票

您无需摆弄占位符图像和所有这些复杂性。只需在 HTML 中使用原始大图像,设置

loading="lazy"
,浏览器就会处理剩下的事情。您可以在浏览器检查器的网络选项卡中确认最初仅加载视口中的图像,然后在滚动时加载其他图像。

© www.soinside.com 2019 - 2024. All rights reserved.