WooCommerce Product Archive Image Slider(2021)
WooCommerce Product Archive Image Slider是一种在产品分类页面直接展示所有产品图片的方法,特别适合销售服装、玩具等产品的实体商店使用。今天sola为要介绍一种简单的创建产品图片幻灯片的方法,性能友好。
先来看最终效果。主题是storefront,woocommerce版本为5.7.1
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代码
分成两部分,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提醒。