国境を越えた旅を始めよう
お問い合わせ

ウェブサイト制作 カスタマーサービス

カスタマーサービス

デザイナー(Figmaのプロトタイプを作る)

ワードプレス製品スライダー

[custom_product_carousel cat="your-category-slug" count="12"]
这是简码


add_shortcode('custom_product_carousel', function($atts){
    $atts = shortcode_atts([
        'cat' => '',
        'count' => 30,
    ], $atts);

    if(empty($atts['cat'])) return '';

    $args = [
        'post_type' => 'product',
        'posts_per_page' => intval($atts['count']),
        'post_status' => 'publish',
        'ignore_sticky_posts' => 1,
        'tax_query' => [[
            'taxonomy' => 'product_cat',
            'field' => 'slug',
            'terms' => $atts['cat']
        ]]
    ];
    $loop = new WP_Query($args);
    if(!$loop->have_posts()) return '';

    ob_start();
    $list = [];
    while($loop->have_posts()): $loop->the_post();
        global $product;
        $gallery = $product->get_gallery_image_ids();
        $img1 = get_the_post_thumbnail_url(get_the_ID(),'large');
        $img2 = isset($gallery[0]) ? wp_get_attachment_image_url($gallery[0], 'large') : $img1;
        $list[] = [
            'title' => get_the_title(),
            'url'   => get_permalink(),
            'price' => $product->get_price_html(),
            'img1'  => $img1,
            'img2'  => $img2,
        ];
    endwhile; wp_reset_postdata();
    $count = count($list);
    ?>
    <div class="cpc3-wrap">
        <div class="cpc3-carousel-wrap">
            <div class="cpc3-carousel">
                <?php foreach($list as $i=>$item): ?>
                <div class="cpc3-item" data-idx="<?php echo $i; ?>">
                    <a href="<?php echo esc_url($item['url']); ?>" class="cpc3-img-wrap">
                        <img src="<?php echo esc_url($item['img1']); ?>" class="cpc3-img img-1" alt="">
                        <img src="<?php echo esc_url($item['img2']); ?>" class="cpc3-img img-2" alt="">
                    </a>
                    <div class="cpc3-bottom-line"></div>
                    <div class="cpc3-meta">
                        <span class="cpc3-title"><?php echo esc_html($item['title']); ?></span>
                        <span class="cpc3-price"><?php echo wp_kses_post($item['price']); ?></span>
                    </div>
                </div>
                <?php endforeach; ?>
            </div>
        </div>
        <button class="cpc3-arrow left cpc3-arrow-pc" aria-label="prev">
            <svg fill="#000000" viewBox="0 0 24 24" id="left-circle-1" data-name="Flat Line" xmlns="http://www.w3.org/2000/svg" class="icon flat-line" width="44" height="44">
                <circle cx="12" cy="12" r="9" style="fill: #F05B2D; stroke-width: 2;"></circle>
                <polyline points="13 9 10 12 13 15" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"></polyline>
                <circle cx="12" cy="12" r="9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"></circle>
            </svg>
        </button>
        <button class="cpc3-arrow right cpc3-arrow-pc" aria-label="next">
            <svg fill="#000000" viewBox="0 0 24 24" id="right-circle" data-name="Flat Line" xmlns="http://www.w3.org/2000/svg" class="icon flat-line" width="44" height="44">
                <circle cx="12" cy="12" r="9" style="fill: #F05B2D; stroke-width: 2;"></circle>
                <polyline points="11 15 14 12 11 9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"></polyline>
                <circle cx="12" cy="12" r="9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"></circle>
            </svg>
        </button>
        <div class="cpc3-mobile-struct" style="display:none;">
            <div class="cpc3-m-nav">
                <button class="cpc3-m-arrow m-left" aria-label="prev">
                    <svg viewBox="0 0 1024 1024" class="icon" width="30" height="30" fill="#b5b5b5"><path d="M768 903.232l-50.432 56.768L256 512l461.568-448 50.432 56.768L364.928 512z"></path></svg>
                </button>
                <div class="cpc3-m-title"></div>
                <button class="cpc3-m-arrow m-right" aria-label="next">
                    <svg viewBox="0 0 1024 1024" class="icon" width="30" height="30" fill="#b5b5b5"><path d="M256 120.768L306.432 64 768 512l-461.568 448L256 903.232 659.072 512z"></path></svg>
                </button>
            </div>
            <div class="cpc3-m-price"></div>
            <div class="cpc3-m-img-touch">
                <div class="cpc3-m-img-wrap"></div>
            </div>
            <div class="cpc3-m-progress"></div>
        </div>
    </div>
    <style>
    @import url('https://fonts.googleapis.com/css2?family=Marcellus:wght@400&display=swap');
    .cpc3-wrap { width:100%; position:relative; padding:0 0 24px 0;}
    .cpc3-carousel-wrap { width:100%; overflow:hidden; position:relative; }
    .cpc3-carousel {
        display: flex;
        flex-wrap: nowrap;
        transition: transform .55s cubic-bezier(.5,.1,.1,1);
        gap: 40px;
        will-change:transform;
    }
    .cpc3-item {
        flex: 0 0 calc((100% - 80px) / 3.5);
        max-width: calc((100% - 80px) / 3.5);
        box-sizing: border-box;
        background: none;
        position: relative;
        min-width: 0;
        display: flex;
        flex-direction: column;
        align-items: stretch;
    }
    .cpc3-img-wrap {
        display: block;
        width: 100%;
        aspect-ratio: 1/1;
        position: relative;
        overflow: hidden;
        background: #fff;
    }
    .cpc3-img {
        width: 100%;
        height: 100%;
        aspect-ratio: 1/1;
        object-fit: cover;
        transition: opacity .42s;
        position: absolute;
        left: 0; top: 0;
    }
    .cpc3-img.img-1 { z-index:1; opacity:1; }
    .cpc3-img.img-2 { z-index:2; opacity:0; }
    .cpc3-img-wrap:hover .img-2 { opacity:1; }
    .cpc3-img-wrap:hover .img-1 { opacity:0; }
    .cpc3-bottom-line {
        height: 1.5px;
        width: 100%;
        background: #e5decf;
    }
    .cpc3-meta {
        display: flex;
        justify-content: space-between;
        align-items: flex-end;
        font-family: 'Marcellus', serif;
        font-size: 18px;
        margin-top: 20px;
        margin-bottom: 0;
        width: 100%;
        min-height: 24px;
    }
    .cpc3-title {
        font-size: 18px;
        color: #222;
        font-family: 'Marcellus', serif;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 65%;
    }
    .cpc3-price {
        font-size: 18px;
        color: #222;
        font-family: 'Marcellus', serif;
        white-space: nowrap;
    }
    .cpc3-arrow,
    .cpc3-arrow:focus,
    .cpc3-arrow:active,
    .cpc3-arrow:hover {
        background: transparent !important;
        border: none !important;
        box-shadow: none !important;
        outline: none !important;
    }
    .cpc3-arrow svg {
        background: transparent !important;
        box-shadow: none !important;
        border: none !important;
        outline: none !important;
    }
    .cpc3-arrow {
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        cursor: pointer;
        padding: 0;
        z-index: 8;
        opacity: 0;
        transition: .22s;
    }
    .cpc3-wrap:hover .cpc3-arrow { opacity:1;}
    .cpc3-arrow.left, .cpc3-arrow.cpc3-arrow-pc.left { left: 0;}
    .cpc3-arrow.right, .cpc3-arrow.cpc3-arrow-pc.right { right: 0;}
    .cpc3-mobile-struct {display:none;}
    @media (max-width:900px) {
        .cpc3-item { flex: 0 0 100%; max-width:100%; }
        .cpc3-carousel { gap:14px;}
    }
    @media (max-width:700px) {
        .cpc3-carousel-wrap,
        .cpc3-carousel,
        .cpc3-meta,
        .cpc3-bottom-line,
        .cpc3-item,
        .cpc3-img-wrap,
        .cpc3-arrow.cpc3-arrow-pc { display: none !important; }
        .cpc3-mobile-struct { display: block !important; }
        .cpc3-m-nav {
            display:flex;
            justify-content:space-between;
            align-items:center;
            gap:8px;
            margin-bottom:10px;
        }
        .cpc3-m-title {
            flex:1;
            font-size:17px;
            color:#222;
            font-family:'Marcellus',serif;
            font-weight:400;
            line-height:1.3;
            display:-webkit-box;
            -webkit-line-clamp:2;
            -webkit-box-orient:vertical;
            overflow:hidden;
            text-overflow:ellipsis;
            white-space:normal;
            text-align:center;
        }
        .cpc3-m-arrow {
            background:transparent !important;
            border:none !important;
            box-shadow:none !important;
            outline:none !important;
            padding:0 6px !important;
            min-width:28px;
            min-height:28px;
            display:flex;
            align-items:center;
            justify-content:center;
            transition:.2s;
            user-select:none;
        }
        .cpc3-m-arrow:active,
        .cpc3-m-arrow:focus { background:transparent !important; }
        .cpc3-m-price {
            text-align:center;
            font-size:16px;
            color:#222;
            font-family:'Marcellus',serif;
            margin-bottom:10px;
            margin-top:2px;
        }
        .cpc3-m-img-touch {
            width:100%;
            overflow:hidden;
            margin-bottom:18px;
            position:relative;
        }
        .cpc3-m-img-wrap {
            width:100%;
            aspect-ratio:1/1;
            background:#fff;
            position:relative;
            overflow:hidden;
        }
        .cpc3-m-img {
            width:100%;
            height:100%;
            object-fit:cover;
            aspect-ratio:1/1;
            display:block;
        }
        .cpc3-m-progress {
            margin:14px auto 0 auto;
            display:flex;
            justify-content:center;
            align-items:center;
            gap:7px;
        }
        .cpc3-m-progress-bar {
            width:28px;
            height:3.5px;
            border-radius:2px;
            background:#e5decf;
            transition:.22s;
            cursor:pointer;
        }
        .cpc3-m-progress-bar.active {
            background:#F05B2D;
        }
    }
    </style>
    <script>
    (function(){
        var wrap = document.currentScript.parentElement,
            carousel = wrap.querySelector('.cpc3-carousel'),
            items = wrap ? wrap.querySelectorAll('.cpc3-item') : [],
            btnL = wrap ? wrap.querySelector('.cpc3-arrow.left') : null,
            btnR = wrap ? wrap.querySelector('.cpc3-arrow.right') : null;
        var pcShow = 3.5, gap = 40, idx = 0, max = items.length, isMobile = false;

        function setTransform() {
            isMobile = window.innerWidth<=900;
            var gapPx = isMobile ? 14 : gap;
            var showNum = isMobile ? 1 : pcShow;
            var offset = idx * (100 / showNum + gapPx * 100 / (showNum * wrap.offsetWidth));
            if(carousel) carousel.style.transform = 'translateX(-' + offset + '%)';
            if(btnL) btnL.style.display = (idx===0?'none':'');
            if(btnR) btnR.style.display = (idx >= (max-showNum) ? 'none' : '');
        }
        function go(dir){
            var showNum = window.innerWidth<=900 ? 1 : pcShow;
            idx += dir;
            if(idx<0) idx=0;
            if(idx>max-showNum) idx=max-showNum;
            setTransform();
        }
        if(btnL) btnL.onclick = function(){ go(-1);}
        if(btnR) btnR.onclick = function(){ go(1);}
        var sx, dx;
        if(carousel){
            carousel.addEventListener('touchstart',function(e){ sx = e.touches[0].clientX; dx=0; },{passive:true});
            carousel.addEventListener('touchmove',function(e){ dx = e.touches[0].clientX-sx; },{passive:true});
            carousel.addEventListener('touchend',function(){
                if(Math.abs(dx)>40){
                    if(dx<0) go(1);
                    else go(-1);
                }
            });
        }
        window.addEventListener('resize',function(){ setTimeout(setTransform,120); });
        setTimeout(setTransform,120);

        // Mobile
        var mStruct = wrap.querySelector('.cpc3-mobile-struct');
        if(mStruct){
            var list = <?php echo json_encode($list); ?>, midx = 0;
            var titleBox = mStruct.querySelector('.cpc3-m-title'),
                priceBox = mStruct.querySelector('.cpc3-m-price'),
                imgBox = mStruct.querySelector('.cpc3-m-img-wrap'),
                progressBox = mStruct.querySelector('.cpc3-m-progress'),
                imgTouchBox = mStruct.querySelector('.cpc3-m-img-touch'),
                leftBtn = mStruct.querySelector('.cpc3-m-arrow.m-left'),
                rightBtn = mStruct.querySelector('.cpc3-m-arrow.m-right');

            function renderMobile(){
                var cur = list[midx];
                titleBox.textContent = cur.title;
                priceBox.innerHTML = cur.price;
                imgBox.innerHTML = '<a href="'+cur.url+'"><img class="cpc3-m-img" src="'+cur.img1+'" alt=""></a>';
                var p = '';
                for(var i=0;i<list.length;i++){
                    p += '<div class="cpc3-m-progress-bar'+(i==midx?' active':'')+'" data-idx="'+i+'"></div>';
                }
                progressBox.innerHTML = p;
                leftBtn.style.visibility = midx === 0 ? 'hidden' : 'visible';
                rightBtn.style.visibility = midx === list.length-1 ? 'hidden' : 'visible';
            }

            // 进度条点击
            mStruct.addEventListener('click', function(e){
                var t = e.target;
                if(t.classList.contains('cpc3-m-progress-bar')){
                    var i = parseInt(t.getAttribute('data-idx'));
                    if(!isNaN(i)) {
                        midx = i; renderMobile();
                    }
                }
            });

            // 左右按钮
            leftBtn.onclick = function(){ if(midx>0){midx--;renderMobile();} }
            rightBtn.onclick = function(){ if(midx<list.length-1){midx++;renderMobile();} }

            // 图片区域左右滑动
            var touchX = 0, moveX = 0, dragging = false;
            if(imgTouchBox){
                imgTouchBox.addEventListener('touchstart',function(e){ 
                    if(e.touches.length===1){ touchX = e.touches[0].clientX; moveX=0; dragging=true; }
                },{passive:true});
                imgTouchBox.addEventListener('touchmove',function(e){
                    if(dragging){ moveX = e.touches[0].clientX - touchX; }
                },{passive:true});
                imgTouchBox.addEventListener('touchend',function(){
                    if(dragging && Math.abs(moveX)>40){
                        if(moveX<0 && midx<list.length-1){ midx++;renderMobile(); }
                        else if(moveX>0 && midx>0){ midx--;renderMobile(); }
                    }
                    dragging = false;
                },{passive:true});
            }
            renderMobile();
        }
    })();
    </script>
    <?php
    return ob_get_clean();
});