WooCommerce Product Archive Image Slider(2021)

优质
小牛编辑
134浏览
2023-12-01

WooCommerce Product Archive Image Slider是一种在产品分类页面直接展示所有产品图片的方法,特别适合销售服装、玩具等产品的实体商店使用。今天sola为要介绍一种简单的创建产品图片幻灯片的方法,性能友好。

先来看最终效果。主题是storefront,woocommerce版本为5.7.1

WooCommerce Product Archive Image Slider

WooCommerce Product Archive Image Slider的原理

将产品的gallery图片信息以JSON字符串的格式放进HTML,并用Javascript获取该信息,就可以动态替换img标签来实现幻灯片效果。这种方式支持WordPress Responsive Images,但会产生较多的html数据,sola的选择是关闭archive页面 WordPress Responsive Images 功能。

代码文件的结构

storefont-child-theme-master是storefront的child theme,位于wp-content/themes目录下。

WooCommerce Product Archive Image Slider file structure

WooCommerce Product Archive Image Slider代码

分成两部分,php代码用来获取图集数据,js代码控制图片地址切换。当然,你可以添加一些css来美化效果。

PHP部分 – class-product-archive-gallery.php

<?php
// Exit if accessed directly.
defined('WPINC') or exit;

class Sola_Product_Archive_Gallery{

  public function __construct(){
    add_action( 'woocommerce_before_shop_loop_item', [$this,'sola_insert_gallery_data'] );
    add_action( 'wp_footer', [$this,'sola_init_script'] );
  }

  function sola_insert_gallery_data(){

    if( ! $this->is_gallery_enabled() ){
      return;
    }

    global $product;

    if( ! $product instanceof WC_Product ){
      return;
    }
    
    $gallery_ids = $product->get_gallery_image_ids();

    if( !is_array($gallery_ids) || ! sizeof($gallery_ids) ){
      return;
    }

    $gallery_images   = array();
    $gallery_images[] = woocommerce_get_product_thumbnail();

    foreach( $gallery_ids as $attachment_id ){

      $gallery_images[] =  wp_get_attachment_image( $attachment_id, 'woocommerce_thumbnail', false );
    }
    $gallery_images =array_filter($gallery_images);

    if( sizeof($gallery_images) > 1 ){
      echo '<div data-loop-gallery="'.$this->json_encode($gallery_images).'"></div>';
    }
    
  }



  function sola_init_script(){
    if( ! $this->is_gallery_enabled() ){
      return;
    }
    ?>
<script id="product-archive-gallery">
  jQuery(function($){
    $.ajax({
      url: '<?php echo get_stylesheet_directory_uri();?>/plugins/sola-product-archive-gallery/product-archive-gallery.js',
      dataType: "script",
      cache:true
    });
    
  });
    
</script>
    <?php
  }

  function is_gallery_enabled(){
    return is_shop() || is_product_category() || is_product_tag();
  }


  function json_encode( $php_array ){
    return _wp_specialchars( wp_json_encode($php_array), ENT_QUOTES, 'UTF-8', true );
  }
}

new Sola_Product_Archive_Gallery();

Javascript部分 – product-archive-gallery.js

;(function ( $ ) {

  var SolaProductArchiveGallery = {
    settings:{
      'productSelector' : '.products > .product',
      'prevBtn': `<button type="button" aria-label="Previous">
        <svg viewBox="0 0 100 100" width="16" height="16">
        <path d="M 10,50 L 60,100 L 70,90 L 30,50  L 70,10 L 60,0 Z">
        </path></svg></button>`,
      'nextBtn': `<button type="button" aria-label="Next">
        <svg viewBox="0 0 100 100" width="16" height="16">
        <path d="M 10,50 L 60,100 L 70,90 L 30,50  L 70,10 L 60,0 Z" transform="translate(100, 100) rotate(180) ">
        </path></svg></button>`,
    },
    setupGalleries: function(){
      const gallery = $(this.settings.productSelector);
      const self = this;

      if( gallery === null || ! gallery.length  ){
        return;
      }

      gallery.each(function(){
        let product = $(this);
        let galleryData = product.find('.sola-loop-gallery').data('loop-gallery');

        if( ! galleryData || galleryData.length < 1 ){
          return;
        }
        product.addClass('sola-product');
        self.setupGallery(product, galleryData);
        
      });
    },
    setupGallery: function( product, galleryData ){
      // Create navigation buttons
      let prevBtn = this.settings.prevBtn;
      let nextBtn = this.settings.nextBtn;
      let navBar = $('<div>' + prevBtn + nextBtn + '</div>');
      let imgContainer = product.find('img').parent();
      imgContainer.append(navBar);

      // Bind data
      navBar.data('galleryImage', galleryData);
      navBar.data('nextImageIndex', 0 );

      // Add Number Indicator
      let indicator = $('<div>1/'+ galleryData.length +'</div>');
      imgContainer.append(indicator);
    },
    onSlideGallery: function onSlideGallery( event ){

      event.preventDefault();
      let navBtn           = $(this);
      let navBar           = navBtn.parent();
      let product          = navBtn.closest('.sola-product');
      let galleryImages    = navBar.data('galleryImage');
      let lastImageIndex   = galleryImages.length - 1;
      let nextImageIndex   = navBar.data('nextImageIndex');
      let isNextBtnClicked = navBtn.hasClass('next');
      let indicator        = product.find('.sola-archive-gallery-indicator');


      if( isNextBtnClicked ){
        nextImageIndex += 1;
      } else {
        nextImageIndex -= 1;
      }

      // Infinite Loop
      if( nextImageIndex > lastImageIndex ){
        nextImageIndex = 0;
      } 

      if( nextImageIndex < 0 ){
        nextImageIndex = lastImageIndex;
      }

      navBar.parent().find('img').replaceWith(galleryImages[nextImageIndex]);
      indicator.html( (nextImageIndex+1) + '/' + (lastImageIndex+1));
      navBar.data('nextImageIndex', nextImageIndex);
    },
    init:function( userSettings ){
      $.extend( this.settings, userSettings );
      this.setupGalleries();
      $(document).on('click', '.sola-archive-gallery-nav > *', this.onSlideGallery);
    }
  };

  SolaProductArchiveGallery.init();
  
})( jQuery );

CSS部分,根据你的主题决定是否需要

ul.products li.product{
    position:relative;
}
.sola-archive-gallery-btn{
    position:absolute;
    top:30%;
    z-index:100;
    background:rgba(255,255,255,.8);
}
.sola-archive-gallery-btn.previous{
    left:0;
}
.sola-archive-gallery-btn.next{
    right:0;
}
.sola-archive-gallery-indicator{
    position:absolute;
    top:0;
    left:0;
    color:#fff;
    background:rgba(0,0,0,.9);
    padding:.2rem 1rem;
    letter-spacing:3px;
    font-size:14px;
}

WooCommerce Product Archive Image Slider使用方法

按照sola提供的文件结构,将文件夹放到主题的根目录下,并在主题的functions.php中引入php文件。

require get_stylesheet_directory() . '/plugins/sola-product-archive-gallery/class-product-archive-gallery.php';

初始化js时,要根据自己主题的html结构确定productSelector,可以在初始化时更改这个selector。

SolaProductArchiveGallery.init({
  'productSelector' : '.products > .product',
  'prevBtn': `<button type="button" aria-label="Previous">
    <svg viewBox="0 0 100 100" width="16" height="16">
    <path d="M 10,50 L 60,100 L 70,90 L 30,50  L 70,10 L 60,0 Z">
    </path></svg></button>`,
  'nextBtn': `<button type="button" aria-label="Next">
    <svg viewBox="0 0 100 100" width="16" height="16">
    <path d="M 10,50 L 60,100 L 70,90 L 30,50  L 70,10 L 60,0 Z" transform="translate(100, 100) rotate(180) ">
    </path></svg></button>`,
});

考虑到性能,sola创建的 WooCommerce Product Archive Image Slider是在document ready事件发生之后加载,不会触发render-blocking resources提醒。