こんにちは、かつコーチです。
前回はモーダルウィンドウをjQueryで実装しました。
今回は、トップページなどでよく見るスライダー(カルーセル)をjQueryで実装していきます。
素のJavaScript版ではCSSの transform: translateX() を使いましたが、jQueryでは animate() メソッドを使うと、CSSのtransitionを書かなくてもアニメーションを実現できます。
「保守案件でjQueryの animate() が出てきたけど、CSSのtransitionと何が違うのか分からない」という方は、ぜひこの記事で違いを整理してください。
jQueryのanimate()メソッドとは
CSSのtransitionとの違い
animate()とは、CSSの数値プロパティ(left、top、widthなど)を指定した時間をかけて変化させるjQueryのメソッドです。
素のJavaScript版では、CSSに transition: transform 0.4s ease; を書いておき、JavaScript側は style.transform の値を変更するだけでした。
jQueryの animate() はこれとは逆に、アニメーション自体をJavaScript側で計算しながら実行するという違いがあります。
| 方法 | アニメーションの制御場所 | 対応できるプロパティ |
|---|---|---|
| CSSのtransition + JSでスタイル変更 | CSS側 | transformを含む多くのプロパティ |
jQueryのanimate() | JavaScript側 | left・top・width・opacityなど数値プロパティのみ |
animate() は transform を直接アニメーションさせることができないため、スライダーの横移動には left プロパティを使うのが定番です。
実装方針を先に整理する
素のJS版と同じく、状態として管理するのは次の3つです。
- 現在のスライド番号(
currentIndex) - スライドの総数(
slideCount) - 自動再生のタイマーID(止めるときに必要)
考え方自体は素のJavaScript版と共通なので、「変わるのは状態を画面に反映する部分の書き方だけ」と捉えると理解しやすくなります。
基本の実装手順
手順1:HTMLとCSSを用意する
<div class="slider">
<div class="slider__track" id="sliderTrack">
<div class="slider__slide"><img src="slide1.jpg" alt="スライド1"></div>
<div class="slider__slide"><img src="slide2.jpg" alt="スライド2"></div>
<div class="slider__slide"><img src="slide3.jpg" alt="スライド3"></div>
</div>
<button class="slider__btn slider__btn--prev" id="prevBtn" aria-label="前へ">‹</button>
<button class="slider__btn slider__btn--next" id="nextBtn" aria-label="次へ">›</button>
<div class="slider__dots" id="sliderDots"></div>
</div>
.slider {
position: relative;
overflow: hidden;
max-width: 600px;
}
.slider__track {
display: flex;
position: relative; /* leftプロパティで動かすためrelativeにしておく */
}
.slider__slide {
min-width: 100%;
}
animate() で left を動かすため、CSS側の transition の指定は不要になります。
手順2:jQueryで切り替えロジックを実装する
$(function () {
const $track = $('#sliderTrack');
const $slides = $track.children();
const slideCount = $slides.length;
const $dotsContainer = $('#sliderDots');
let currentIndex = 0;
// インジケーターをスライド枚数分だけ動的に生成する
for (let i = 0; i < slideCount; i++) {
const $dot = $('<button>').addClass('slider__dot');
if (i === 0) $dot.addClass('is-active');
$dot.on('click', function () {
goToSlide(i);
});
$dotsContainer.append($dot);
}
const $dots = $dotsContainer.children();
function goToSlide(index) {
currentIndex = index;
$track.animate(
{ left: `-${currentIndex * 100}%` },
400 // 400ミリ秒かけて移動する
);
$dots.removeClass('is-active').eq(currentIndex).addClass('is-active');
}
function nextSlide() {
const nextIndex = (currentIndex + 1) % slideCount;
goToSlide(nextIndex);
}
function prevSlide() {
const prevIndex = (currentIndex - 1 + slideCount) % slideCount;
goToSlide(prevIndex);
}
$('#nextBtn').on('click', nextSlide);
$('#prevBtn').on('click', prevSlide);
});
$('<button>') のように、タグ文字列を $() に渡すと新しい要素を生成できます。
素のJS版の document.createElement() に対応する書き方です。
.eq(currentIndex) は「何番目の要素か」をインデックスで指定するjQuery特有のメソッドで、removeClass().eq(index).addClass() とメソッドチェーンでつなげられるのが便利なポイントです。
剰余演算子(%)を使った循環の考え方は、素のJS版とまったく同じです。
よくあるつまずきポイント・エラー対処
Before/After:animateを連打すると動きがガクガクになる
私が最初にjQueryで自動再生スライダーを作ったとき、ボタンを連打すると、スライドがガクガクと不自然に前後に動く現象に遭遇しました。
❌ Before:連打対策をしていない
$('#nextBtn').on('click', function () {
nextSlide();
});
// animateが完了する前に次のanimateが呼ばれると、アニメーションのキューが積み重なる
animate() は呼び出すたびに「アニメーションのキュー(順番待ちの列)」に処理を追加します。
ボタンを連打すると、前のアニメーションが終わっていないのに次のアニメーションが予約され、後から「溜まった分のアニメーションが順番に再生される」という状態になり、見た目がガクガクした動きになります。
✅ After:stop()でキューをクリアしてから動かす
function goToSlide(index) {
currentIndex = index;
$track.stop(true, true).animate(
{ left: `-${currentIndex * 100}%` },
400
);
$dots.removeClass('is-active').eq(currentIndex).addClass('is-active');
}
stop(true, true) は「今実行中のアニメーションを止め、溜まっているキューもすべて破棄したうえで、現在のアニメーションを最終状態まで一気に進める」という指定です。
animate() を使うUIでは、この stop() によるキュー対策がほぼ必須のテクニックだと覚えておいてください。
Before/After:自動再生タイマーの多重起動
素のJS版でも紹介されていた「タイマーが多重に動いてしまう」問題は、jQueryでも同じように起こります。
❌ Before:タイマーを止めずに何度も再生成してしまう
let timerId;
function startAutoPlay() {
timerId = setInterval(nextSlide, 3000);
}
$('.slider').on('mouseleave', function () {
startAutoPlay(); // 呼ばれるたびに新しいタイマーが増えていく
});
✅ After:開始前に必ず既存のタイマーを止める
let timerId = null;
function startAutoPlay() {
stopAutoPlay();
timerId = setInterval(nextSlide, 3000);
}
function stopAutoPlay() {
clearInterval(timerId);
timerId = null;
}
$('.slider').on('mouseenter', stopAutoPlay);
$('.slider').on('mouseleave', startAutoPlay);
startAutoPlay();
setInterval / clearInterval はDOM標準のAPIなので、jQueryを使っていても書き方は素のJavaScript版と変わりません。
jQuery特有の animate() の話と混同しないよう、「アニメーションのキュー管理はstop()」「タイマーの多重起動対策はclearInterval()」と分けて覚えておくと整理しやすくなります。
応用:easing(イージング)を変える
jQuery標準のeasingオプション
animate() の第3引数(または設定オブジェクトの easing プロパティ)で、動きの緩急を変更できます。
$track.stop(true, true).animate(
{ left: `-${currentIndex * 100}%` },
{
duration: 400,
easing: 'swing', // jQuery標準では linear か swing のみ
}
);
jQuery本体が標準で持っているイージングは linear(一定速度)と swing(滑らかな緩急)の2種類だけです。
「もっとバリエーションが欲しい」という場合は、jQuery UIライブラリを追加で読み込むことで easeInOutQuad のような多彩なイージングが使えるようになりますが、レガシー案件の保守であれば、まずは標準の2種類で十分なケースがほとんどです。
まとめ
この記事のポイント
- jQueryの
animate()は、leftなどの数値プロパティをJavaScript側でアニメーションさせるメソッド $('<button>')のようにタグ文字列を$()に渡すと新しい要素を生成できるanimate()を連打すると、アニメーションのキューが溜まってガクガクした動きになるためstop(true, true)で対策するsetIntervalによるタイマーの多重起動対策は、素のJavaScript版と同じ考え方で解決できるanimate()標準のeasingはlinearとswingの2種類のみ
次に読むべき記事
次回は、フォームのバリデーションをjQueryで実装します。
submitイベントを使ったチェックと、エラーメッセージ表示の実装方法を解説します。
→ 次の記事:フォームのバリデーションをjQueryで実装する
タグ:jQuery, 中級者向け, UI実装