简体   繁体   中英

ie11 polyfill to load background image based on picture sourceset

I have written the following polyfill for ie so that I can use css object-fit :

 const $images = $('.object-fit'); const replacementClass = 'object-fit-replacement'; if ($images.length) { $images.each(function(index, item) { const $image = $(item); // this code will not run in IE if image is in the cache $image.on('load', function(e) { makeDiv(e.currentTarget); }); // this code will run if image is already in the cache if (item.complete) { makeDiv(item); } }); } function makeDiv(image) { const $image = $(image); const $picture = $image.closest('picture'); let $div; let $parent; let imageSource; if ($picture.length) { $parent = $picture.parent(); imageSource = $image.prop('currentSrc') || image.src; } else { $parent = $image.parent(); imageSource = image.src; } $div = $parent.find('.' + replacementClass); if (!$div.length) { $div = $('<div class="' + replacementClass + '"></div>'); $parent.append($div); } $div.css('background-image', 'url(' + imageSource + ')'); $picture.hide(); $image.hide(); } 
 .object-fit-replacement { /* for test only */ background-size:cover; width:100vw; height:100vh; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <picture> <source srcset="https://via.placeholder.com/300x100" media="(max-width:768px)"> <source srcset="https://via.placeholder.com/600x300" media="(min-width:768px)"> <img src="https://via.placeholder.com/200x200" alt="Test" class="image object-fit"> </picture> 

However, it only seems to load the actual image source from the image tag. Is there a way for it to respect the current source (taken from the correct media query in the picture tag) - I thought $image.prop('currentSrc') was meant to get it but doesn't seem to work in ie11 (if you look at it in chrome, it loads the correct background image)

This is due to ie11 not being able to handle the picture element. In the end, as I knew all the breakpoints on our site for the picture elements (and that they were not going to change as they were made by a server side helper), I just added on a bit of jquery to get the correct source from the the picture tag:

import $ from 'jquery';
import elementHelper from '../helpers/element-helper';
import throttle from 'lodash/throttle';

$(() => {
  const $images = $('.object-fit');
  const replacementClass = 'object-fit-replacement';
  const $window = $(window);

  if ($images.length) {
    $images.each((index, item) => {
      const $image = $(item);
      let imageLoaded = false;

      // this code will not run in IE if image is in the cache
      $image.on('load', e => {
        if (!imageLoaded) {
          makeDiv(e.currentTarget);
          imageLoaded = true;
        }
      });

      // this code will run if image is already in the cache
      if (item.complete && !imageLoaded) {
        makeDiv(item);
        imageLoaded = true;
      }
    });
  }

  $window.on('resize', throttle(() => {
    $(`.${replacementClass}`).each((index, item) => {
      const $picture = $(item).prev('picture');
      console.log('resize', $picture.length)
      if ($picture.length) {
        $div.css('background-image', `url(${getPictureSource($picture)})`);
      }
    });
  }, 100));

  function makeDiv(image) {
    const $image = $(image);
    const $picture = $image.closest('picture');
    let $div;
    let $parent;
    let imageSource;

    if ($picture.length) {
      $parent = $picture.parent();
      imageSource = getImageSource($picture, $image);
    } else {
      $parent = $image.parent();
      imageSource = image.src;
    }

    $div = $parent.find(`.${replacementClass}`);
    if (!$div.length) {
      $div = $(elementHelper.createElement('div', replacementClass));
      $parent.append($div);
    }

    $div.css('background-image', `url(${imageSource})`);

    $picture.hide();
    $image.hide();
  }

  function getImageSource($picture, $image) {
    const imageSource = $image.prop('currentSrc');

    if (imageSource) {
      return imageSource;
    } else {
      return  getPictureSource($picture);
    }
  }

  function getPictureSource($picture) {
    // this assumes that the image helper has created the object fit picture tag and is using the standard 5 media queries
    const $sources = $picture.children('source');
    if ($sources.length === 5) {
      const windowWidth = $window.outerWidth();
      if (windowWidth < 380) {
        return $sources.eq(0).attr('srcset');
      } else if (windowWidth >= 380 && windowWidth < 767) {
        return $sources.eq(1).attr('srcset');
      } else if (windowWidth >= 767 && windowWidth < 1200) {
        return $sources.eq(2).attr('srcset');
      } else if (windowWidth >= 1200 && windowWidth < 1600) {
        return $sources.eq(3).attr('srcset');
      } else {
        return $sources.eq(4).attr('srcset');
      }
    }
    return  $sources.last().attr('srcset'); // this assumes sources are done normally with desktop largest last (default to dektop)
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM