Splideの自動スクロールが動かない?
自動スクロールが動き出さないことがあった
SplideのAuto Scrollエクステンションを使って、横スクロールする自動再生ギャラリーを実装しました。autoScroll: { speed: 1 }とオプションを渡してmountすれば、あとは何もしなくても動き続ける。そのはずでした。
ところが本番環境で確認すると、動いていないことがあります。スライドは最初の位置のまま、1pxも動きません。リロードで直ることもあれば、直らないこともあります。
つまり、再現条件は、はっきりしません。何に依存して動いているのか、ライブラリのソースから追うことにしました。
初回再生が始まる条件
Auto Scrollエクステンションのmount()は、初回再生を次のように制御しています。
function autoStart() {
if (autoScrollOptions.autoStart) {
if (document.readyState === "complete") {
play();
} else {
bind(window, "load", play);
}
}
}
mount時点でdocument.readyStateがcompleteでなければ、windowのloadイベントを待ってからplay()を呼びます。loadはページの読み込み中に一度しか発生しないイベントです。発生しなければ、play()はそのまま呼ばれません。
loadはページ内のすべてのリソース(画像、iframe、スクリプトなど)の読み込み完了を待って発生する、HTML標準で定義された挙動です。ブラウザ判定を挟んでいるわけではないので、特定のブラウザに限った話ではありません。
では、実際にはどれくらい待たされるのでしょうか。サードパーティのスクリプトを多く読み込むページは珍しくありません。そうしたページをPlaywrightでwaitUntil: 'load'を指定して開いたところ、120秒待ってもタイムアウトしました。loadが実質発生しない状態になれば、bind(window, "load", play)で登録したリスナーは呼ばれず、Auto Scrollエクステンションはintervalを作ったところで止まったままになります。
対処は単純です。
splide.mount({ AutoScroll });
splide.Components.AutoScroll.play();
mount直後にComponents.AutoScroll.play()を明示的に呼びます。play()はisPaused()で多重呼び出しをガードしているので、後からloadイベントが発生してリスナーが呼ばれても、二重に動くことはありません。
まとめ
Auto Scrollエクステンションは、初回再生をwindow.loadという一度きりのイベントで制御しています。症状としては「開始しない」という掴みどころのない見え方でしたが、原因はイベントの発生タイミングという単純な話でした。
使う場合は、mount直後にComponents.AutoScroll.play()を明示的に呼んでおくと安全です。