有料プラグイン Slider Revolution のカルーセルを、無料の自作プラグインに置き換えた記録

WordPress で管理しているサイトのトップページで、長年 Slider Revolution の「中央フォーカス型カルーセル」を使ってきた。チラシ画像を中央に大きく、両脇に前後のスライドをちら見せする、よくあるタイプのものだ。

このカルーセルを、無料の Swiper.js を使った自作プラグインに置き換えた。その過程で踏んだ問題と解決策を、未来の自分のために記録しておく。

目次

なぜ置き換えたか

Slider Revolution は高機能だが、自分の用途では完全にオーバースペックだった。実際に管理画面の設定を確認したところ、やっていたのは次の一点だけだった。

  • 投稿(post)と The Events Calendar のイベント(tribe_events)から、「スライド画面」という1つのカテゴリーが付いたものを最大30件取得し、Post ID の降順で回す

これだけのために、年額ライセンス・頻繁な更新通知・管理画面内の宣伝表示を抱え続けるのは割に合わない。設定を確認して「これなら自分で書ける」と判断した。

設計:投稿とイベントを1つのカルーセルにまとめる

最初の山場がここだった。通常の投稿とイベントでは、カテゴリーの仕組み(タクソノミー)が別物になっている。

  • 通常投稿:category(標準カテゴリー)
  • The Events Calendar のイベント:tribe_events_cat(イベント専用カテゴリー)

同じ「スライド画面」という名前でも、チェックボックスが置かれている場所が違う。これを1つのクエリでまとめて取得するには、WP_Query の tax_query で relation => 'OR' を使い、2つのタクソノミーを横断する。

$query = new WP_Query( array(
    'post_type'      => array( 'post', 'tribe_events' ),
    'post_status'    => 'publish',
    'posts_per_page' => 30,
    'orderby'        => 'ID',
    'order'          => 'DESC',
    // The Events Calendar がイベントクエリに割り込むのを防ぐ
    'tribe_suppress_query_filters' => true,
    'tax_query'      => array(
        'relation' => 'OR',
        array(
            'taxonomy' => 'category',
            'field'    => 'name',
            'terms'    => 'スライド画面',
        ),
        array(
            'taxonomy' => 'tribe_events_cat',
            'field'    => 'name',
            'terms'    => 'スライド画面',
        ),
    ),
) );

tribe_suppress_query_filters => true は重要で、これを入れないと The Events Calendar がイベントクエリに独自の並び替えや絞り込みを差し込んでくる。

表示は Swiper の slidesPerView: 'auto' + centeredSlides: true で、中央1枚を大きく、両脇をちら見せする構成にした。

つまずき1:背景グラデーションの扱い

元のデザインは、カルーセル全体に1枚のグラデーション背景が敷かれていて、スライドが流れても背景は動かない。最初これを「各スライドに背景を持たせる」実装にしてしまい、チラシ1枚+背景がセットで丸ごと入れ替わる紙芝居のような動きになった。

正解は、カルーセルを囲む外側のラッパーにだけ背景を敷くこと。スライド側には背景を一切持たせない。

.roon-carousel-bg {
    background: linear-gradient(
        to right,
        #8023a8 0%,    /* 紫 */
        #0b0b2b 50%,   /* 濃いネイビー */
        #00424E 100%   /* 深いティール */
    );
}

つまずき2:全幅にならない

一番手こずったのがこれ。カルーセルの枠を画面の左端から右端まで広げたいのに、左右に白い帯が残る。

最初に試したのは CSS だけで突破する方法だった。

  • width: 100vw; margin-left: -50vw; → テーマのコンテナ構造によって右側が切れる
  • left: calc(50% - 50vw); → 親要素に padding があると内側にずれる
  • WordPress の「全幅」ブロック設定 → このテーマの固定ページでは、そもそも全幅ブロック自体が画面端まで広がらなかった(旧 Slider Revolution まで左右に白帯が出た)

切り分けの決め手は「旧 Slider Revolution も全幅になっていない」と気づいたこと。つまり問題は自分のコードではなく、このテーマの固定ページでは標準の全幅機能が当てにならない、ということだった。

最終的な解決は、JavaScript で実際のビューポート幅と位置を測ってラッパーに反映する方法。100vw(スクロールバー幅を含むため右が切れる)は使わず、要素の現在位置から画面左端までの距離を実測して、その分だけずらす。

function roonFullBleed() {
    bg.style.marginLeft = '0px';
    bg.style.width = '100%';
    var rect = bg.getBoundingClientRect();
    var viewportWidth = document.documentElement.clientWidth;
    var offsetLeft = rect.left;
    bg.style.marginLeft = (-offsetLeft) + 'px';
    bg.style.width = viewportWidth + 'px';
}

これに加えて、ショートコードのブロックを WordPress の「全幅」設定と併用しないこと(二重指定でずれる)。グループブロックから出して、単独のショートコードブロックとして配置し、ブロックの配置は「なし」にしたら安定した。

つまずき3:古い iPad mini だけ自動再生が始まらない

機能としては完成し、Android・iPhone では問題なく動いた。ところが古い iPad mini(Chrome / Safari 両方)だけ、自動再生が始まるまでに5分以上かかった。表示・画像読み込み自体は正常で、Swiper の autoplay のタイマー起動だけが極端に遅れていた。

検証で分かったのは、Slider Revolution は最初に1〜2秒のローディングを見せてから動かしている、ということ。最初これを真似てプリローダーを実装したが、根本解決にはならなかった。

本当の原因は、Swiper 内蔵の autoplay が、古い Safari の省電力なタイマー制御と相性が悪いことだった。新しい端末は処理が速いので問題が表面化しないが、古い iPad mini では autoplay の内部タイマーが後回しにされ続ける。

解決策は、Swiper の autoplay を使わず、自前の setInterval で slideNext() を定期実行すること。

var DELAY = 3000;
function roonStart() {
    roonStop();
    timer = setInterval(function () {
        if (swiper) { swiper.slideNext(); }
    }, DELAY);
}
function roonStop() {
    if (timer) { clearInterval(timer); timer = null; }
}

Swiper には表示・スライド・ループ・矢印だけを任せ、「いつ次に進むか」は自分で制御する。これで端末性能や省電力設定に左右されず、全端末で安定して動くようになった。あわせて、矢印操作中やマウスホバー中は一時停止、タブ非表示中は停止して復帰時に再開、という制御も入れた。

結果

  • 年額ライセンス・広告・更新通知・ライセンス縛りから解放された
  • 投稿とイベントを横断する1つのカルーセルを、無料の Swiper.js だけで実現できた
  • 旧プラグインより読み込みが軽くなった
  • 全端末(Android / iPhone / iPad mini、Chrome / Safari)で安定動作する

学んだこと

  • 多機能プラグインの設定を一度きちんと確認すると、自分の用途では何をしているか意外と単純なことがある。それが分かれば自作の判断ができる
  • 全幅問題は、自分のコードを疑う前に「他の要素(今回は旧プラグイン)も同じ症状か」を見ると原因の切り分けが速い
  • ライブラリ任せの自動再生は、古い端末や Safari でタイミング問題を起こすことがある。重要な動作は自前のタイマーで握ったほうが安定する
  • 本番に入れる前にテストサイト(サブドメイン+コピー)で検証する手順は、今回のように何度も差し替える作業では特に効いた

同じように Slider Revolution の特定用途だけを置き換えたい人の参考になれば嬉しいです。

目次