WEBOPIXEL

jQueryでTwitterのトップページのように一定のタイミングでコンテンツをスライドさせる

Posted: 2011.02.25 / Category: javascript / Tag: ,

Twitterのトップページは人気のツイートが次々とスライドして表示されてますね。
この記事ではjQueryを使用して見た目のスライドするだけの部分を再現してみたいと思います。

Sponsored Link

demo

ベースとなるhtml+css

Twitterの場合は裏でajax的なことを色々やっているのだと思いますが、見た目しか再現しないのでプレーンなhtmlを使用します。

html

	<div id="slide">
		<ul>
			<li>
				<strong>2011.02.01</strong>
				最初です。最初だけどむしろ最後です。
			</li>
			<li>
				<strong>2011.02.12</strong>
				Twitterのトップページのようにコンテンツを一定の時間でスライドさせてみます。<br />
				jQueryを使用しています。
			</li>
			<li>
				<strong>2011.02.28</strong>
				そろそろ3月ですね。<br />
				暖かいですね。今日はとても暖かいですね。
			</li>
			<li>
				<strong>2011.04.18</strong>
				このスライドは最後の子要素まで進むと止まります。<br />
				たぶん止まります。<br />
				止まってください。
			</li>
		</ul>
		<div id="fade"></div>
	</div>
	

「slide」というidのdivの中にリストでマークアップしています。
最後のfadeはだんだん消えていく透明度の画像を配置してフェードアウトを表現します。
配置する「fade.png」はこちら(真っ白ですが透明のグラデーションになっています)。

css

	#slide {
		font-size: 84%;
		width:450px;
		height: 200px;
		overflow: hidden;
		position: relative;
	}
	#slide ul {
		list-style: none;
		position:absolute;
		width:450px;
	}
	#slide ul li {
		margin-bottom: 1em;
		padding-bottom: 1em;
		border-bottom: 1px solid #CCCCCC;
	}
	#slide ul li strong {
		display: block;
	}
	#slide #fade {
		position:absolute;
		bottom:0;
		width:450px;
		height:60px;
		z-index:1;
		background:url(fade.png) repeat-x bottom;
		_visibility:hidden;
	}
	

「overflow: hidden」で「#slide」枠の外は非表示になります。
「position: relative」は「#fade」を配置するためのものなのでフェードアウトの処理が必要なければとってください。
ie6では透明度画像が使用できないので「_visibility:hidden」しています。

jQueryでやること。

最初にulの高さ分だけ上に配置します。
その後一定のタイミングごとに、リストの高さ分を下をスライドさせまればなんとなくできそうなきがします。

説明図

最終的なコード

javascript

	$(function() {
		var time = 1000;	//切り替えのタイミング
		var speed = 500;	//スライドスピード
		var slideUl = $('#slide > ul');
		var slideList = $('li', slideUl);
		//ulの高さ分を上にずらす
		slideUl.css('margin-top', '-'+slideUl.attr('offsetHeight')+'px');
		//リストのmargin
		var mBottom = parseInt(slideList.css('margin-bottom'));
		var count = slideList.length-1;
		var timer = setInterval(loop, time);
		
		//ループ処理
		function loop() {
			//最後のリストまで繰り返す
			if(0 <= count) {
				slideUl.animate({
					marginTop :  parseInt(slideUl.css('margin-top'))+slideList.eq(count).attr('offsetHeight')+mBottom+'px'
				},speed);
			} else {
				//最後まできたらループ終了
				clearInterval(timer);	
			}
			count--;
		}
		//マウスオーバーでストップ
		slideUl.hover(
			function(){
				if(0 <= count) clearInterval(timer);
			},
			function () {
				if(0 <= count) timer = setInterval(loop, time);
			}
		);
	});
	
7行目
slideUl.attr('offsetHeight')
これでulのHeight(高さ)を取得してcssで上に配置しています。
今回だったら「slideUl.height()」でも良いのですが、「offsetHeight」はpaddingを含めた値を取得できます。
9行目
parseInt(slideList.css('margin-bottom'))
リストの高さ分だけスライドさせるのですが、実際は「height+margin」ですね。
「attr('offsetHeight')」にはmarginが含まれていませんので、別に取得しています。
またそのままのcssの値では「px(単位)」も含まれてしまうため、parseIntで数値のみ取得する必要があります。
9行目
parseInt(slideList.css('margin-bottom'))
リストの高さ分だけスライドさせるのですが、実際は「height+margin」ですね。
「attr('offsetHeight')」にはmarginが含まれていませんので、別に取得しています。
またそのままのcssの値では「px(単位)」も含まれてしまうため、parseIntで数値のみ取得する必要があります。
11行目
var timer = setInterval(loop, time)
一定時間ごとに処理を実行するには「setInterval」を使用します。
これで「loop」というメソッドを「time」間隔で実行できます。
16~24行目
ここでスライドの処理をしています。
アニメーションは「animate」の「marginTop」に移動後の位置を指定します。
移動後の位置は「ul」の位置+次の「li」の高さ+「li」の「margin-bottom」ですね。
1回実行されるごとに「count」をマイナスして、0になったら「clearInterval(timer)」でタイマー処理を終了します。
27~34行目
マウスオーバーすると「clearInterval(timer)」でスライドが停止。
マウスアウトすると「timer = setInterval(loop, time)」で再スタートです。

COMMENTS

mof 2012-07-04 10:09 

最後のlist要素の次に最初のlist要素を持ってきてループさせることは出来ますか?

ゆーた 2012-07-18 23:39 

そのままコピーしてやりましたができないです。。。
どこか追加とかありますか?

webOpixel 2012-07-19 10:16 

jQUeryは読み込まれていますか?
デモのソースも確認してみてください。

ゆーた 2012-07-20 01:23 

できました!すいませんでした。
jQUeryが読まれてなかったようです!
もうひとつだけご質問ですがこのループが止まらずにずっと動いてるようにするのは可能ですか? もしですが最後までいけばまた最初から動くって感じにしたいのですが・・・
よろしくお願いします!

webOpixel 2012-07-23 15:04 

animateのコールバックで最初のリストを最後の持ってくるような処理をすればいいのではないでしょうか。
そこそこのカスタマイズが必要かもしれませんが、、、
すぐにはできませんが、そのうち対応します。

LEAVE A REPLY

コードを書く場合は<pre>で囲んでください。