jQuery UI アニメーションとプラグイン開発の実践ガイド

ユーザーインターフェースアニメーション

アニメーション付きログインフォームの実装

ログインフォームはWebアプリケーションの第一印象を左右する重要な要素です。jQueryのアニメーション機能を活用することで、フォーム表示・非表示時のスムーズなトランジションやエラーフィードバックを視覚的に強化できます。

以下のHTML構造を準備します:

<button class="open-login">ログインフォームを開く</button>
<div class="login-frame">
  <div class="login-box">
    <div class="login-msg">下記よりログインしてください</div>
    <div class="form-group">
      <label class="form-label">ユーザー名:</label>
      <input type="text" class="form-control" id="username" />
    </div>
    <div class="form-group">
      <label class="form-label">パスワード:</label>
      <input type="password" class="form-control" id="password" />
    </div>
    <div class="login-actions">
      <button class="btn login-btn">ログイン</button>
      <button class="btn close-login">キャンセル</button>
    </div>
  </div>
</div>

CSSで初期状態を非表示に設定し、位置を画面外に配置します:

.login-frame {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: none;
  background: rgba(0,0,0,0.5);
}
.login-box {
  width: 400px;
  height: 165px;
  position: absolute;
  top: -200px;
  left: 50%;
  margin-left: -200px;
  background: white;
  border-radius: 8px;
  padding: 20px;
}

jQueryでアニメーションを実装します:

$(function(){
  $('.open-login').on('click', function(){
    $('.login-frame').fadeIn(500);
    $('.login-box').animate({'top': '50%'}, 500);
  });
  
  $('.close-login').on('click', function(){
    $('.login-box').animate({'top': '-200px'}, 500);
    $('.login-frame').fadeOut(500);
  });
  
  $('.login-btn').on('click', function(){
    const username = $('#username').val();
    const password = $('#password').val();
    
    $.post('/auth.php', {username, password})
      .done(function(response) {
        const msgEl = $('.login-msg');
        if (response.success) {
          msgEl.removeClass('error').addClass('success')
              .text('ログイン成功!');
        } else {
          msgEl.removeClass('success').addClass('error')
              .text(response.error);
          // エラー時のシェイクアニメーション
          $('.login-box').animate({left: -15}, 30)
                        .animate({left: 15}, 30)
                        .animate({left: 0}, 30);
        }
      });
  });
});

画像ズーム効果の実装

サムネイル画像にホバーした際に拡大表示するインタラクティブな効果を実装します。

<div class="gallery">
  <div class="thumb"><img src="image1.jpg" alt=""></div>
  <div class="thumb"><img src="image2.jpg" alt=""></div>
</div>

CSSでコンテナを設定:

.gallery {
  display: flex;
  gap: 10px;
}
.thumb {
  width: 200px;
  height: 150px;
  overflow: hidden;
  cursor: pointer;
}
.thumb img {
  width: 100%;
  height: auto;
  transition: transform 0.3s ease;
}
.thumb:hover img {
  transform: scale(1.2);
}

jQueryによる高度な制御(必要に応じて):

$('.thumb img').each(function() {
  const $img = $(this);
  const originalWidth = $img.width();
  const originalHeight = $img.height();
  
  $img.data('original', {width: originalWidth, height: originalHeight});
});

$('.thumb').hover(
  function() {
    const $img = $(this).find('img');
    const orig = $img.data('original');
    $img.animate({
      width: orig.width * 1.2,
      height: orig.height * 1.2
    }, 200);
  },
  function() {
    const $img = $(this).find('img');
    const orig = $img.data('original');
    $img.animate({
      width: orig.width,
      height: orig.height
    }, 200);
  }
);

コンテンツスライダーの作成

複数のコンテンツを横スクロールで切り替えるスライダーを実装します。

<div class="slider-container">
  <div class="slides">
    <div class="slide">コンテンツ1</div>
    <div class="slide">コンテンツ2</div>
    <div class="slide">コンテンツ3</div>
  </div>
  <div class="slider-nav">
    <button data-slide="0">1</button>
    <button data-slide="1">2</button>
    <button data-slide="2">3</button>
  </div>
</div>

jQuery実装:

class ContentSlider {
  constructor(container) {
    this.$container = $(container);
    this.$slides = this.$container.find('.slides');
    this.$slideItems = this.$container.find('.slide');
    this.currentSlide = 0;
    this.slideCount = this.$slideItems.length;
    
    this.init();
  }
  
  init() {
    // スライドを横並びに
    this.$slides.css('width', `${this.slideCount * 100}%`);
    this.$slideItems.css('width', `${100 / this.slideCount}%`);
    
    // ナビゲーションイベント
    this.$container.find('[data-slide]').on('click', (e) => {
      const index = parseInt($(e.currentTarget).data('slide'));
      this.goToSlide(index);
    });
    
    // 自動再生(オプション)
    setInterval(() => {
      this.nextSlide();
    }, 4000);
  }
  
  goToSlide(index) {
    if (index < 0 || index >= this.slideCount) return;
    
    this.currentSlide = index;
    const translateX = -index * 100;
    this.$slides.css('transform', `translateX(${translateX}%)`);
    
    // アクティブクラスの更新
    this.$container.find('[data-slide]').removeClass('active');
    this.$container.find(`[data-slide="${index}"]`).addClass('active');
  }
  
  nextSlide() {
    const next = (this.currentSlide + 1) % this.slideCount;
    this.goToSlide(next);
  }
}

// 初期化
$(document).ready(() => {
  new ContentSlider('.slider-container');
});

jQueryプラグイン開発

プラグインテンプレートの作成

再利用可能なjQueryプラグインの基本テンプレート:

(function($) {
  'use strict';
  
  const PluginName = 'customPlugin';
  
  class Plugin {
    constructor(element, options) {
      this.$element = $(element);
      this.options = $.extend({}, this.defaults, options);
      this.init();
    }
    
    get defaults() {
      return {
        duration: 300,
        easing: 'swing'
      };
    }
    
    init() {
      // プラグインの初期化ロジック
      this.bindEvents();
    }
    
    bindEvents() {
      // イベントバインディング
    }
    
    destroy() {
      // クリーンアップ処理
      this.$element.removeData(PluginName);
    }
  }
  
  $.fn[PluginName] = function(options) {
    return this.each(function() {
      if (!$.data(this, PluginName)) {
        $.data(this, PluginName, new Plugin(this, options));
      }
    });
  };
  
})(jQuery);

ツールチッププラグインの実装

要素にホバーツールチップを追加するプラグイン:

(function($) {
  'use strict';
  
  const Tooltip = 'tooltip';
  
  class TooltipPlugin {
    constructor(element, options) {
      this.$element = $(element);
      this.options = $.extend({}, this.defaults, options);
      this.$tooltip = null;
      this.init();
    }
    
    get defaults() {
      return {
        position: 'top',
        delay: 200,
        className: 'custom-tooltip'
      };
    }
    
    init() {
      const title = this.$element.attr('title') || 
                   this.$element.data('tooltip') || '';
      
      if (!title) return;
      
      // オリジナルのtitle属性を削除
      this.$element.removeAttr('title');
      this.$element.data('tooltip-text', title);
      
      this.bindEvents();
    }
    
    bindEvents() {
      this.$element.hover(
        () => this.show(),
        () => this.hide()
      );
    }
    
    show() {
      if (this.$tooltip) return;
      
      const text = this.$element.data('tooltip-text');
      this.$tooltip = $(`<div class="${this.options.className}">${text}</div>`);
      
      $('body').append(this.$tooltip);
      this.positionTooltip();
      
      this.$tooltip.fadeIn(this.options.delay);
    }
    
    hide() {
      if (!this.$tooltip) return;
      
      this.$tooltip.fadeOut(this.options.delay, () => {
        this.$tooltip.remove();
        this.$tooltip = null;
      });
    }
    
    positionTooltip() {
      const elementOffset = this.$element.offset();
      const elementHeight = this.$element.outerHeight();
      const tooltipHeight = this.$tooltip.outerHeight();
      const tooltipWidth = this.$tooltip.outerWidth();
      
      let top, left;
      
      switch(this.options.position) {
        case 'top':
          top = elementOffset.top - tooltipHeight - 10;
          left = elementOffset.left + (this.$element.outerWidth() / 2) - (tooltipWidth / 2);
          break;
        case 'bottom':
          top = elementOffset.top + elementHeight + 10;
          left = elementOffset.left + (this.$element.outerWidth() / 2) - (tooltipWidth / 2);
          break;
        default:
          top = elementOffset.top - (tooltipHeight / 2);
          left = elementOffset.left + this.$element.outerWidth() + 10;
      }
      
      this.$tooltip.css({ top, left });
    }
  }
  
  $.fn[Tooltip] = function(options) {
    return this.each(function() {
      if (!$.data(this, Tooltip)) {
        $.data(this, Tooltip, new TooltipPlugin(this, options));
      }
    });
  };
  
})(jQuery);

使用例

<button data-tooltip="これはツールチップです">ホバーしてみてください</button>

<script>
$(document).ready(function() {
  $('[data-tooltip]').tooltip({
    position: 'top',
    delay: 150
  });
});
</script>

タグ: jQuery javascript CSS UIアニメーション プラグイン開発

7月2日 18:49 投稿