jQueryプラグインを使わずに自前カルーセルパネルを導入してみる

カルーセルパネル系のjQueryプラグインはかなり数が多いのですが、今回はjQuery本体のみ利用しプラグインを利用せず自作してみます。CSSとJavascriptを数行書き換えるだけで横型、縦型の2つが作れます。

プラグインを使わずにカルーセルパネル 横型
プラグインを使わずにカルーセルパネル 縦型

ではでは横型のカルーセルパネルを作っていきます。まずはHTML、CSSでカルーセルパネルの表示部分をつくります。内容を表示させるボックスを指定して、その中にリスト横並びに並べることにしましょう。両端にはリストを動かすボタン(「id=prev」「id=next」)を置き、これはCSSで配置を制御します。で、できたものは下記↓。

プラグインを使わずにカルーセルパネル HTML、CSSのみ

■HTML

<div id="carouselwrap">
<div id="prev" class="hide"></div><div id="next" class="show"></div>
<div id="carousel">
<ul>
	<li><a href="#"><img src="img/1.gif"></a></li>
	<li><a href="#"><img src="img/2.gif"></a></li>
	<li><a href="#"><img src="img/3.gif"></a></li>
	.......
</ul>
</div>
</div>

■CSS

<style>
* {
	margin: 0;
	padding: 0;
}
#carouselwrap {
	position:relative;
	margin:40px auto;
	width:900px;
	height:155px;
	background: #efefef;
}
#carouselwrap #carousel {
	position:relative;
	width:100%;
	height:100%;
	overflow: hidden; //はみでた部分を隠す
}
#carouselwrap ul{
	list-style-type:none;
}
#carouselwrap ul li {
	float:left; // liを横並びにする
	width: 270px;
	height:100%;
	padding-left: 23px;
	display:inline;
}
#carouselwrap ul li img {
	border:none;
}
#carouselwrap #prev,
#carouselwrap #next {
	position: absolute;
	top: 0;
	width: 20px;
	height:100%;
}
#carouselwrap #prev {
	left: -20px; //戻るボタンを左端に配置
	background-image: url(./img/prev.png);
	background-repeat: no-repeat;
	background-position: 50% 50%;
}
#carouselwrap #next {
	right: -20px; //進むボタンを右端に配置
	background-image: url(./img/next.png);
	background-repeat: no-repeat;
	background-position: 50% 50%;
}
// ボタンがアクティブなときは「show」、使えないときは「hide」
#carouselwrap .show {
	cursor: pointer;
	background: #FF3399;
}
#carouselwrap .hide {
	background: #ccc;
}
</style>

戻る、進むボタンを「carouselwrap(幅900px)」の左右-20pxに配置したので幅940pxのパネルができたことになります。これでHTML、CSSの準備はOKです。

では次にJavascriptでパネルを動くようにしましょう。動作の基本は「戻る、進むボタンでulタグの位置(position leftの値)を変更する」ということです。

Javascript側でやることを簡単にまとめると
・liタグが全部横に並んだときの幅を取得し、ulタグにスタイルを書き込む
・戻る、進むボタンがクリックされたらulのposition leftの値を変更する
の2点です。

あとは動作条件として「ulの右端、左端が表示されたときは各戻る、進むボタンを動作させない」「戻る、進むボタンはスライド中は動作させない」といったものを含めて下記のようなものができあがりました。あとJavascriptが切られている場合はボタンを表示させたくないので、HTML側でボタンの記述は削除し、Javascript側で追加するようにしています。

■Javascript

<script>
$(function(){
	// prev,nextをクリックしたときに動かすliの数
	var li_move = 3;
	// prev,nextを追加
	$("#carouselwrap").append('<div id="prev" class="hide"></div><div id="next" class="show"></div>');
	// カルーセルパネルの幅を取得
	var carousel_wid = $("#carouselwrap").width();
	// liのpaddingを含む幅を取得
	var li_wid = $("#carousel li").outerWidth();
	// liの数を取得
	var li_num = $("#carousel li").size();
	// ulの幅を計算(liを全部横に並べた幅)
	var ul_wid = li_wid*li_num;
	// ulにスタイルを追加
	$('#carousel ul').css({
		position: 'absolute',
		top: '0',
		left: '0',
		width: ul_wid+'px'
	});
	$('#prev').click(function(){
		// prevをクリックしたときにclass=hideが指定されていなければ、以下を実行
		if($(this).attr("class") != "hide") {
			// ulのpositionを左に動かすアニメーション(:not(:animated)は動いている最中のクリック防止用)
			$('#carousel ul:not(:animated)').animate(
				{left:'+='+li_wid*li_move},
				600,
				function(){
					// アニメーションが完了したらulのposition-leftの位置を取得
					var ul_pos = boxPosition("#carousel ul","left");
					// nextのclassを「show」に書き換え
					$('#next').attr("class","show");
					// ulのposition-leftが0の場合、prevのclassを「hide」に書き換え
					if(ul_pos === 0) {
						$('#prev').attr("class","hide");
					}
				}
			);
		}
	});
	$('#next').click(function(){
		// nextをクリックしたときにclass=hideが指定されていなければ、以下を実行(以下略)
		if($(this).attr("class") != "hide") {
			$('#carousel ul:not(:animated)').animate(
				{left:'-='+li_wid*li_move},
				600,
				function(){
					var ul_pos = boxPosition("#carousel ul","left");
					$('#prev').attr("class","show");
					if(carousel_wid > (ul_wid+ul_pos)) {
						$('#next').attr("class","hide");
					}
				}
			);
		}
	});
	function boxPosition(ele,pos) {
	 	// 指定されたエレメントのpositionの各値を取得
		var position = $(ele).position();
		// 指定された位置の値をリターン
		return position[pos];
	}
});
</script>

少し説明を加えると「var li_move = 3」という指定でliタグ何個分の幅をスライドさせるか、という指定をしています。CSSで表示サイズやリストの幅を変更したときに、「var li_move = 1」で1個ずつスライドさせる、「var li_move = 5」で5個スライドさせる、といったことが簡単にできるようになっています。

あとはCSSで表示サイズやデザインを自分のサイトにあうように調整すれば、導入完了です。

縦型のカルーセルパネルについても少し説明すると、横型のカルーセルパネルは各幅を取得していましたが、縦型の場合は高さを取得します。で、その数値を元にulタグのtopの値を変更します。

プラグインを使わずにカルーセルパネル 縦型

CSSを縦用のものにし、Javacriptを下記のように書き換えるだけです。

■縦型 CSS
変更した要素のみ抜粋しています。

#carouselwrap {
	position:relative;
	margin:40px auto;
	width:270px;
	height:340px;
	background: #efefef;
}
#carouselwrap ul li {
	width:100%;
	height: 155px;
	padding-top: 10px;
}
#carouselwrap #prev,
#carouselwrap #next {
	position: absolute;
	left: 0;
	width: 100%;
	height:20px;
}
#carouselwrap #prev {
	top: -20px;
	background-image: url(./img/top.png);
	background-repeat: no-repeat;
	background-position: 50% 50%;
}
#carouselwrap #next {
	bottom: -20px;
	background-image: url(./img/bottom.png);
	background-repeat: no-repeat;
	background-position: 50% 50%;
}

■縦型 Javascript
横型のjavascriptから変更した箇所は「//*****書き換え******//」と書かれた数行です。

<script>
$(function(){
	// prev,nextをクリックしたときに動かすliの数
	var li_move = 2;
	// prev,nextを追加
	$("#carouselwrap").append('<div id="prev" class="hide"></div><div id="next" class="show"></div>');
	// カルーセルパネルの高さを取得
	var carousel_wid = $("#carouselwrap").height(); //*****書き換え******//
	// liのpaddingを含む高さを取得
	var li_wid = $("#carousel li").outerHeight(); //*****書き換え******//
	// liの数を取得
	var li_num = $("#carousel li").size();
	// ulの高さを計算(liを全部縦に並べた高さ)
	var ul_wid = li_wid*li_num;
	// ulにスタイルを追加
	$('#carousel ul').css({
		position: 'absolute',
		top: '0',
		left: '0',
		height: ul_wid+'px' //*****書き換え******//
	});
	$('#prev').click(function(){
		// prevをクリックしたときにclass=hideが指定されていなければ、以下を実行
		if($(this).attr("class") != "hide") {
			// ulのpositionを左に動かすアニメーション(:not(:animated)は動いている最中のクリック防止用)
			$('#carousel ul:not(:animated)').animate(
				{top:'+='+li_wid*li_move},
				600,
				function(){
					// アニメーションが完了したらulのposition-topの位置を取得
					var ul_pos = boxPosition("#carousel ul","top"); //*****書き換え******//
					// nextのclassを「show」に書き換え
					$('#next').attr("class","show");
					// ulのposition-topが0の場合、prevのclassを「hide」に書き換え
					if(ul_pos === 0) {
						$('#prev').attr("class","hide");
					}
				}
			);
		}
	});
	$('#next').click(function(){
		// nextをクリックしたときにclass=hideが指定されていなければ、以下を実行(以下略)
		if($(this).attr("class") != "hide") {
			$('#carousel ul:not(:animated)').animate(
				{top:'-='+li_wid*li_move},
				600,
				function(){
					var ul_pos = boxPosition("#carousel ul","top"); //*****書き換え******//
					$('#prev').attr("class","show");
					if(carousel_wid > (ul_wid+ul_pos)) {
						$('#next').attr("class","hide");
					}
				}
			);
		}
	});
	function boxPosition(ele,pos) {
	 	// 指定されたエレメントのpositionの各値を取得
		var position = $(ele).position();
		// 指定された位置の値をリターン
		return position[pos];
	}
});
</script>

これでトップページのメインビジュアルのスライドとして使う、サイドバーに縦長に置きたい場合も、CSSでサイズ調整すれば、どこでもカルーセルパネルを導入できます。利用する際にはjQuery本体を読み込むのをお忘れなく。

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>

長くなりましたが、少しJavascriptができれば、横型、縦型のJavascriptを1つにまとめて関数化して使い回しやすくするのも簡単です。Javascript練習中の方は、ぜひ関数化して利用することにもチャレンジして見て下さい。

jQuery API
jQuery API 1.4.4 日本語リファレンス – StackTrace

jQueryで簡単タブメニューを自作する

WordPress 3.2.1がリリースされてますね。3.2からIE6非対応とのことなのでまだインストールすらしてませんが、そのうち試そう。

今日はスマホで活躍の場がありそうなタブメニューをjQueryで作成してみます。

スマホ対応ページを作成する場合、PCページをそのまま移植しようとするとやたらにページが長くなってしまう場合があります。そんなときはタブメニューを使って、ちょちょいとコンテンツをまとめてみましょう。

jQueryで簡単タブメニュー サンプル

まずは簡単にHTMLから説明。HTML側にはjQueryで処理しやすいように、タブとコンテンツにidを割り当てます。idは処理しやすくするため「tab_1」「content_1」と文字と数字のセパレータに「_」を入れ、数字が同じものが対になるように割り当てています。

<div class="tabarea">  
<ul class="tabs">  
<li id="tab_1" class="selected">メニュー1</li>  
<li id="tab_2">メニュー2</li>  
<li id="tab_3">メニュー3</li>  
</ul>  
<div id="content_1" class="content">『メニュー1』のコンテンツです。</div>  
<div id="content_2" class="content">『メニュー2』のコンテンツです。</div>  
<div id="content_3" class="content">『メニュー3』のコンテンツです。</div>  
</div>

つぎにCSS。リストを簡単に横並びにできるように「display: box;」を使っています。box非対応ブラウザの表示くずれを避けたい場合は「float: left;」等を使って調整を。

.tabarea {
	background: #000;
}
ul.tabs {  
	display: box;
	display: -webkit-box;
	display: -moz-box;
	margin:0px;
	padding:0px;
	background: #000;
}
ul.tabs li {  
	list-style:none;
	padding: 20px;
	border: 1px solid #000;  
	border-bottom: 0;
	color: #fff;
}
div.content {
	padding: 20px;
	border: 1px solid #000;  
	border-top: 0;
	background: #fff;
}
.tabarea .selected {
	background: #fff;
	color: #000;
}
#content_2, #content_3 {
	display: none;
} 

最後にjQuery。HTML側で割り当てたタブのidの数字部分取得して、数字の一致するコンテンツのみ表示させる、という処理をしています。

$(function(){
	$(".tabarea .tabs li").click(function(){
		var tab = $(this).attr("id"); //クリックされたタブのidを取得
		var num = tab.split("_"); //セパレータで分割
		var con = "#content_" + num[1]; //表示させるコンテンツのid名を生成
		$(this).addClass("selected"); //クリックされたタブのclassにselectedを割り当て
		$(".tabarea li:not(#"+tab+")").removeClass("selected"); //その他のタブのclassにあるselectedを削除
		$(".tabarea div[id^=content]").hide(); //コンテンツをすべて非表示に
		$(".tabarea " + con).show(); //クリックされたタブ対応のコンテンツのみ表示
	});
});

今回のサンプルではHTML側で視覚的にどれが対になっているかわかりやすいようidを割り当てましたが、jQuery側で「.index()」使って要素の順番を取得し、HTML側はいちいちidを記述しなくても動作するようにもできます。

と、こんな感じに、わざわざjQueryプラグインを導入しなくても、ちょこっとjQueryの記述さえわかれば、簡単にタブメニューを導入できます。

jQueryさわったことがないという方も、この機会にぜひお試しあれ。

ページ遷移、読み込み時にふわっと表示するjQueryプラグインを再び修正 [ 2012-02-06 ]

fadeMoverプラグインの解説ページを別途作成しましたので、下記ページをご覧ください。

jquery.fadeMover – Fadein and Fadeout for jQuery

——- 以下 [ 2012-02-06 ] 以前の内容です —-

[ 2012-02-06 追記 ] 最近このページのアクセスがかなり増えているので、記事を見直していたら、制作途中のものを記事にしてしまっていました。もしご利用をお考えになられていても「動かない…wtf…」となっていた方がおられたと思います。。。申し訳ありません。

作成途中で「ページ内リンクの動作禁止にしないと使えないよね、これ。。。」と気がつき、機能を付け足していたんですが、公開していたものが動作確認中の途中のスクリプトでした。それが原因でアンカーにclassを指定していたらまったく動作しないようになっていました。もし古いものをご利用されている方がいらっしゃいましたら修正していただければと思います。

//jquery.fademover.jsの23行目
if(!$(this).attr("class")){
//jquery.fademover.jsの23行目
if(!$(this).hasClass(setting.nofadeOut) && moveUrl.charAt(0) != "#"){

——- 以下 [ 2012-02-06 ] 内容修正済みです —-

以前作成していたページ遷移、読み込み時にふわっと表示するjQueryプラグインを修正しました。

ブラウザのバックボタンで戻った時にフェードアウトしたページが表示されない状態で保持されてしまっていたのですが、下記1行追加してきちんと表示されるようになりました。

window.onunload = function () {}

プラグインの動作は、
・ページ読み込み時にフェードインする。
・アンカーをクリックし次のページに移る前に現在のページをフェードアウトするというものです。

jquery.fademover.js サンプル

$(function(){
	$('フェード処理する要素').fadeMover({'outSpeed':現在のページをフェードアウトするスピード,'inSpeed':ページ読み込み時のフェードインスピード,'effectType':どのエフェクトを利用するか指定,'nofadeOut','クリックしてもフェードアウトさせないアンカーに記述するclass名'});
	$('body').fadeMover();
});

なにも指定しない場合はフェードイン、フェードアウト両方利用し、処理速度は1000ミリ秒(1秒)になっています。

effectTypeの指定は、指定なし(もしくは「1」)は両方、フェードインのみは「2」、フェードアウトのみは「3」となります。

effectTypeは分ける必要もないかなと思いつつ、もしかしたら使うかもってことで分けてあります。

nofadeOutはクリックしてもフェードアウト処理をさせないアンカータグに対して記述するclass名になります。初期値は「nonmover」になっています。これはページ内リンクに対応するために追加したものです。アンカーにclassを記述してください。もしアンカーのclass名に「nonmover」という文字を含む名前を使っている場合(nonmover1等)は、nofadeOutを別のものに指定してください。

[ 2012-02-06 追記 ] 「<a href=”#pagetop”>」等、#から始まるページ内リンクの記述の場合はclassを付ける必要がないように修正しました。

//下記のリンクは動作しません。
<a href="#pagetop">ページの先頭へ戻る</a>
<a href="/img/big.jpg" class="nonmover">画像を開く</a>

[ 2012-02-06 追記 ] javascriptの読み込みの関係で、フェードインする前に全部表示されてから動作する場合があります。この場合フェード処理する要素のスタイル自体に「opacity:0」の記述をしておけば一番いいのですが、Javascriptを切っている場合、表示されなくなります。このあたりは少し悩ましいところですが、javascriptでhead要素にスタイルを追加する方法があります。
※ この記述はフェードアウトのみ利用の場合は必要ありません。

/*
jQueryのappendでhead内に対象要素のスタイルに「opacity:0」を追記
IE6〜8対応用に-ms-filter:"alpha( opacity=0 )";filter: alpha( opacity=0 );
$(function(){〜});の外に記述
*/
$('head').append('<style>#content { opacity: 0;-ms-filter:"alpha( opacity=0 )";filter: alpha( opacity=0 ); }</style>');
$(function(){
	$('#content').fadeMover();
});

必ず「$(function(){〜});の外に記述」するようにして下さい。これで全部表示されることがなく、スームーズにフェードインするようになるはず。お試しください。

jquery.fademover.jsの中身は下記。

/* Copyright (c) 2011 detelu (http://www.detelu.com)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * jquery.fademover.js
 * Version: 2012-02-06
*/
(function($){
	$.fn.fadeMover = function(options) {
        var defaults = {
            'outSpeed': 1000,
            'inSpeed': 1000,
			'effectType': 1, // fadeIn only 2, fadeOut only 3
			'nofadeOut' : 'nonmover' //fadeOut no thx (class name)
        };
        var setting = $.extend(defaults, options);
        this.each(function() {
			var pel = this;
			if(setting.effectType == 1 || setting.effectType == 2) {
				$(pel).css("opacity", 0).animate({opacity: 1}, setting.inSpeed);
			}
			if(setting.effectType == 1 || setting.effectType == 3) {
				$('a').click(function(event) {
					var moveUrl = $(this).attr("href");
					if(!$(this).hasClass(setting.nofadeOut) && moveUrl.charAt(0) != "#"){
						event.preventDefault();
						$(pel).animate({"opacity": 0}, setting.outSpeed, function(){
							location.href = moveUrl;
						});
					}
				});
			}
		});
		return this;
	}
	window.onunload = function () {};
})(jQuery);

プラグインを作ってみようと、ぱぱっと作ったものなので不具合はあるかもしれません。とりあへずZIPファイルを置いておきますので、ご利用の方はどーぞ。

fademover.zip (サンプルファイル等一式 107KB)

アマゾンのサーバでエラーが起こっているかもしれません。一度ページを再読み込みしてみてください。