ユーザーインターフェースアニメーション
アニメーション付きログインフォームの実装
ログインフォームは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>