patrickkunka / mixitup

A high-performance, dependency-free library for animated filtering, sorting, insertion, removal and more
https://www.kunkalabs.com/mixitup/
4.52k stars 734 forks source link

Lazy Loading Images #453

Open dejardine opened 6 years ago

dejardine commented 6 years ago

This is not really an issue, more of a question.

I have a grid of images that loads filtered. What is the recommended way of preventing mixitup from loading all images (even those hidden), which it seems to do? I see there was at one time a lazy load, is that still part of MixitUp3?

Thank you

ghost commented 6 years ago

Hi,

MixItUp doesn't know anything about your DOM or images - only how to show/hide/sort the target elements. However, MixItUp will give you data about which elements are shown and when.

The best way to deal with lady loading images therefore is to use the onMixEnd callback function to iterate through all "shown" targets in the state object (which is passed as a parameter to the callback), and lazy load the images for those targets only. You'll also want a way of making sure that an images isn't lazy loaded multiple times for the same target.

A common approach is to omit the src attribute of your images, or set it to a 1px gif dataurl, by default, and keep the real image url stored in a data-src attribute which will not be parsed by the browser. Then, for each shown target element (using the callback described above), find the image element within in it, and move the image url from the data-src attribute to the src attribute, which will load the image. You can then remove the data-src attribute to clean up so that on subsequent operations, you can then check if the image has a data-src attribute, and if it doesn't it, ignore it.

Hope that makes sense.

patrickkunka commented 5 years ago

Should add a demo for this.

Andrew-APUS commented 5 years ago

Instead of lazy loading all the "shown" objects I use the Intersection Observer API to just load images as they are about to come into the viewport (note: IE and older Safari browsers need a polyfill).

    function lazyload() {
        //lazy load using IntersectionObserver API
        var images = document.querySelectorAll('[data-src]'); //look at images with data-src
        var config = {
          rootMargin: '0px 0px 50px 0px',
          threshold: 0
        };
        var loaded = 0;

        var observer = new IntersectionObserver(function (entries, self) {
          entries.forEach(function (entry) {
            if (entry.isIntersecting) {
                //console.log("Image" .concat(entry.target.src, "is in the viewport!"));
              preloadImage(entry.target);
              // Stop watching and load the image
              self.unobserve(entry.target);
            }
          });
        }, config);

        images.forEach(function(image) {
          observer.observe(image);
        });
        //set each observed image src to its data-src value
        function preloadImage(img) {
          var src = img.getAttribute('data-src');
          if (!src) { return; }
          img.src = src;
        }
    }