/ Scripts & jquery / Lazyload + srcset

Lazyload + srcset

HIT

11.04.2019

3232

Недавно начал использовать библиотеку Lazyload от Daniel ‘Eisbehr’ Kern. Работает лучше чем вторая версия от Mika Tuupola.

Особенности Lazyload

Многие параметры схожи с версией Mika Tuupola (MT), инициализируется так:

$(function() {
	$(".lazy").Lazy({
		effect : "fadeIn",
		threshold : 200
	});
});

Корректно работает с атрибутом srcset, нужно прописывать data-srcset.

Одной из главных особенностей этого решения является наличие поддержки событий, т.е. подгрузка изображений при совершении какого-либо действия. Всю дорогу у меня была в этом плане проблема с галереей slick. Штатные средства по отложенной загрузке slick работают некорректно (по крайней мере у меня), а lazyload MT тоже не подгружал изображения при автоматической перемотке, а только при прокрутке страницы.

Скрипт для slick (определенного слайдера #index-slider) подгружающий слайды при перемотке:

$(document).ready(function() {  
	$("button.slick-arrow").click(function() {
		$("#index-slider img.lazy").Lazy({
			bind: "event"
		});
	});
	
	$('#index-slider').on('afterChange', function(event, slick, currentSlide, nextSlide){
		$("#index-slider img.lazy").Lazy({
			bind: "event"
		});
	});
});

Скрипт для owlCarousel

Вписываем параметр в функцию инициализации карусели (вешаем на событие перемотки слайда функцию):

onTranslated: callback,

Добавляем функцию callback

function callback(event) {
	$(".carousel-vertical img").Lazy({
		bind: "event"
	});
}

функция прописана для конкретной карусели (.carousel-vertical), но это не обязательно.

Функция замены у миниатюр параметра srcset

function lazy_load_responsive_images_modify_post_thumbnail_attr( $attr, $attachment, $size ) {
   if ( isset( $attr['sizes'] ) ) {
      $data_sizes = $attr['sizes'];
      unset( $attr['sizes'] );
      $attr['data-sizes'] = $data_sizes;
   }

   if ( isset( $attr['srcset'] ) ) {
      $data_srcset = $attr['srcset'];
      unset( $attr['srcset'] );
      $attr['data-srcset']   = $data_srcset;
      $attr['data-noscript'] = $attr['src'];
      unset( $attr['src'] );
   }

   $attr['class'] .= ' lazy';

   return $attr;
}
add_filter( 'wp_get_attachment_image_attributes', 'lazy_load_responsive_images_modify_post_thumbnail_attr', 20, 3);

Дополнение. У миниатюр, размер которых мы прописываем (rectangle), может не выводиться атрибут src-set, если пропорция прописанного размера отличается от базовых. В этом случае дорабатываем функцию, чтобы src заменялся на data-src:

// Lazyload для миниатюр
function lazy_load_responsive_images_modify_post_thumbnail_attr( $attr, $attachment, $size ) {
	if ( isset( $attr['sizes'] ) ) {
		$data_sizes = $attr['sizes'];
		unset( $attr['sizes'] );
		$attr['data-sizes'] = $data_sizes;
	}

	if ( isset( $attr['srcset'] ) ) {
		$data_srcset = $attr['srcset'];
		unset( $attr['srcset'] );
		$attr['data-srcset']   = $data_srcset;
		$attr['data-noscript'] = $attr['src'];
		unset( $attr['src'] );
	} else { 
		$attr['data-src'] = $attr['src'];
		unset( $attr['src'] );
	}

	$attr['class'] .= ' lazy';

	return $attr;
}
add_filter( 'wp_get_attachment_image_attributes', 'lazy_load_responsive_images_modify_post_thumbnail_attr', 20, 3);

Также, нашел функцию замены атрибутов в контенте страниц и записей:

function lazy_load_responsive_images ( $content ) {
   if ( empty( $content ) ) {
      return $content;
   }
   $dom = new DOMDocument();
   libxml_use_internal_errors( true );
   $dom->loadHTML( $content );
   libxml_clear_errors();
   foreach ( $dom->getElementsByTagName( 'img' ) as $img ) {
      if ( $img->hasAttribute( 'sizes' ) && $img->hasAttribute( 'srcset' ) ) {
         $sizes_attr = $img->getAttribute( 'sizes' );
         $srcset     = $img->getAttribute( 'srcset' );
         $img->setAttribute( 'data-sizes', $sizes_attr );
         $img->setAttribute( 'data-srcset', $srcset );
         $img->removeAttribute( 'sizes' );
         $img->removeAttribute( 'srcset' );
         $src = $img->getAttribute( 'src' );
         if ( ! $src ) {
            $src = $img->getAttribute( 'data-noscript' );
         }
      } else {
         $src = $img->getAttribute( 'src' );
         if ( ! $src ) {
            $src = $img->getAttribute( 'data-noscript' );
         }
         $img->setAttribute( 'data-src', $src );
      }
      $classes = $img->getAttribute( 'class' );
      $classes .= " lazy";
      $img->setAttribute( 'class', $classes );
      $img->removeAttribute( 'src' );
      $noscript      = $dom->createElement( 'noscript' );
      $noscript_node = $img->parentNode->insertBefore( $noscript, $img );
      $noscript_img  = $dom->createElement( 'IMG' );
      $noscript_img->setAttribute( 'class', $classes );
      $new_img = $noscript_node->appendChild( $noscript_img );
      $new_img->setAttribute( 'src', $src );
      $content = $dom->saveHTML();
   }

   return $content;
}
add_filter( 'the_content', 'lazy_load_responsive_images', 20 );
Но второй код (про страницы и записи) почему-то ломает кодировку шрифта.

Альтернативный и рабочий вариант функции по подгрузке изображений из записей:

// Lazyload Converter
function add_lazyload($content) {

    $content = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
    $dom = new DOMDocument();
    @$dom->loadHTML($content);

    // Convert Images
    $images = [];

    foreach ($dom->getElementsByTagName('img') as $node) {  
        $images[] = $node;
    }

    foreach ($images as $node) {
        $fallback = $node->cloneNode(true);

        $oldsrc = $node->getAttribute('src');
        $node->setAttribute('data-src', $oldsrc );
        $newsrc = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
        $node->setAttribute('src', $newsrc);

        $oldsrcset = $node->getAttribute('srcset');
        $node->setAttribute('data-srcset', $oldsrcset );
        $newsrcset = '';
        $node->setAttribute('srcset', $newsrcset);

        $classes = $node->getAttribute('class');
        $newclasses = $classes . ' lazy';
        $node->setAttribute('class', $newclasses);

        $noscript = $dom->createElement('noscript', '');
        $node->parentNode->insertBefore($noscript, $node); 
        $noscript->appendChild($fallback); 
    }


    // Convert Videos
    $videos = [];

    foreach ($dom->getElementsByTagName('iframe') as $node) {
        $videos[] = $node;
    }

    foreach ($videos as $node) {  
        $fallback = $node->cloneNode(true);

        $oldsrc = $node->getAttribute('src');
        $node->setAttribute('data-src', $oldsrc );
        $newsrc = '';
        $node->setAttribute('src', $newsrc);

        $classes = $node->getAttribute('class');
        $newclasses = $classes . ' lazy';
        $node->setAttribute('class', $newclasses);

        $noscript = $dom->createElement('noscript', '');
        $node->parentNode->insertBefore($noscript, $node); 
        $noscript->appendChild($fallback); 
    }

    $newHtml = preg_replace('/^<!DOCTYPE.+?>/', '', str_replace( array('<html>', '</html>', '<body>', '</body>'), array('', '', '', ''), $dom->saveHTML()));
    return $newHtml;
}
add_filter('the_content', 'add_lazyload');
add_filter('post_thumbnail_html', 'add_lazyload');

Если основная миниатюра итак работает с lazy, то последний фильтр нужно убрать.

Функция Lazyload для товаров WC

Функции взяты из плагина Lazy Load for WooCommerce (500+)

// Lazyload для изображений Woocommerce
if (!function_exists('woocommerce_template_loop_product_thumbnail')) {

    remove_action('woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10);
    add_action('woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10);

    function woocommerce_template_loop_product_thumbnail() {
        $llwoo_image_src = wp_get_attachment_image_src(get_post_thumbnail_id(), 'shop_catalog');
        $llwoo_placeholder = get_option('lazyload-woo_placeholder');
        $llwoo_placeholder_fallback = wc_placeholder_img_src();
        $alt = get_post_meta(get_post_thumbnail_id(), '_wp_attachment_image_alt', true);
        $size = wc_get_image_size('shop_catalog');
        $llwoo_width = $size['width'];
        $llwoo_height = $size['height'];
        if (!empty($llwoo_placeholder)) {
            echo '<img src="' . $llwoo_placeholder . '" data-src="' . $llwoo_image_src[0] . '" width="' . $llwoo_width . '" height="' . $llwoo_height . '" class="attachment-shop_catalog wp-post-image lazy" alt="' . $alt . '"><noscript><img src="' . $llwoo_image_src[0] . '" width="' . $llwoo_width . '" height="' . $llwoo_height . '" class="attachment-shop_catalog wp-post-image lazy" alt="' . $alt . '"></noscript>';
        } else {
            echo '<img src="' . $llwoo_placeholder_fallback . '" data-src="' . $llwoo_image_src[0] . '" width="' . $llwoo_width . '" height="' . $llwoo_height . '" class="attachment-shop_catalog wp-post-image lazy" alt="' . $alt . '"><noscript><img src="' . $llwoo_image_src[0] . '" width="' . $llwoo_width . '" height="' . $llwoo_height . '" class="attachment-shop_catalog wp-post-image lazy"  alt="' . $alt . '"></noscript>';
        }
    }

}
if (!function_exists('woocommerce_subcategory_thumbnail')) {
    //For WooCommerce Category
    remove_action('woocommerce_before_subcategory_title', 'woocommerce_subcategory_thumbnail', 10);
    add_action('woocommerce_before_subcategory_title', 'woocommerce_subcategory_thumbnail', 10);

    function woocommerce_subcategory_thumbnail($category) {
        $small_thumbnail_size = apply_filters('single_product_small_thumbnail_size', 'shop_catalog');
        $dimensions = wc_get_image_size($small_thumbnail_size);
        $thumbnail_id = get_term_meta($category->term_id, 'thumbnail_id', true);
        $llwoo_image_src_cat = wp_get_attachment_image_src($thumbnail_id, $small_thumbnail_size);
        $llwoo_placeholdercat = get_option('lazyload-woo_placeholdercat');
        $llwoo_placeholdercat_fallback = wc_placeholder_img_src();
        $sizecat = wc_get_image_size('shop_catalog');
        $llwoo_widthcat = $sizecat['width'];
        $llwoo_heightcat = $sizecat['height'];
        if (!empty($llwoo_placeholdercat)) {
            echo '<img src="' . $llwoo_placeholdercat . '" data-src="' . $llwoo_image_src_cat[0] . '" width="' . $llwoo_widthcat . '" height="' . $llwoo_heightcat . '" class="attachment-shop_catalog wp-post-image lazy"><noscript><img src="' . $llwoo_image_src_cat[0] . '" width="' . $llwoo_widthcat . '" height="' . $llwoo_heightcat . '" class="attachment-shop_catalog wp-post-image lazy"></noscript>';
        } else {
            echo '<img src="' . $llwoo_placeholdercat_fallback . '" data-src="' . $llwoo_image_src_cat[0] . '" width="' . $llwoo_widthcat . '" height="' . $llwoo_heightcat . '" class="attachment-shop_catalog wp-post-image lazy"><noscript><img src="' . $llwoo_image_src_cat[0] . '" width="' . $llwoo_widthcat . '" height="' . $llwoo_heightcat . '" class="attachment-shop_catalog wp-post-image lazy"></noscript>';
        }
    }
}

Отложенная загрузка для background-image

Чтобы подгрузить background-image нужно в целевом объекте прописать атрибут:

data-src="/wp-content/plugins/site-feedback-form/img/neon-ring.jpg"

И добавить класс .lazy

Чтобы в админке изображения загружались обычным образом нужно Lazyload выводить только для фронтенда if( !is_admin() ) { }

Поделиться в соц. сетях:

  • Комментарии
  • Вложения

Добавить комментарий

Пока нет комментариев. Будь первым!

Lazyload + srcset
Парсинг контента с различных сайтов
Рекомендации для васПарсинг контента с различных сайтовOpttour.ru
Спасибо! Наш менеджер свяжется с Вами в течении 5 минут.