「つくるぶ特集 Flash|Ajax ベストサイトセレクション20」:スライダー(Slider)ライブラリと、写真の中に写真レイヤーを表示するテクニック

SEの竹村です。

今回も「つくるぶ特集 Flash|Ajax ベストサイトセレクション20」のJavaScriptの技術面をフォローしていきます。

▼Flash | Ajax ベストサイトセレクション20
http://www.tkrb.jp/modules/feature0/index.php?id=12

フォローを弊社のブログで行う理由は、Ajax ベストサイトセレクション20ではプログラム的な話はしていないためです。


さて、第4回は

「お題6>検索が楽しくなるサイト」で紹介した「Amazon.com Diamond Search」より、
Script.aculo.usとYUIの両方のSliderについて、

「お題7>写真/動画で魅せるサイト」の「Zooomr」より、
写真の中に写真レイヤーを重ねてスクロールさせる方法について、

を説明していきます。

まずは「Amazon.com Diamond Search」です。

▼Amazon.com Diamond Search

http://www.amazon.com/gp/gsl/search/finder/102-4988296-2955357

こちらはネタとしては新しいものではなく、弊社の八木が2005年6月にブログとして書いています。

▼Ajaxの活用事例:Amazon.com - Diamond Searchの快適な宝石検索体験
https://www.ark-web.jp/blog/archives/2005/06/ajaxamazoncom_d.html

どういうことができるかについてはこの記事を読んでいただくとして、肝心の技術的な内容に入っていきましょう。
Amazonの例では、特に最近のフレームワーク系ライブラリは利用していませんが、同じようなUIを実装するにはまずスライダーのライブラリが使えるようになる必要がありますね。

フレームワーク系のスライダーを利用するとすれば、下記が候補になると思います。

▼Script.aculo.usのSlider
http://wiki.script.aculo.us/scriptaculous/show/Slider

▼Yahoo! UIのSlider
http://developer.yahoo.com/yui/slider/

ただ、これらのフレームワークには単方向のスライダーしかありません。双方向のスライダーというのは、通常のUIでなかなか見かけることもないとは思います。
それでも実装したい場合は↓このサイトの「評価」「予算」部分のように 2つ組み合わせることで実現できます。

▼eatspot

http://eatspot.jp/

このサイトでは、script.aculo.usのSliderライブラリを利用しています。


では、上記 2つのライブラリで同じ仕様のSliderを作ってみます。
※他の要素を入れないように極力HTMLタグとCSSを削っているので見た目はショボイですが、コードを見てください^^;

▼script.aculo.us スライダーサンプル
http://staff.ark-web.jp/~takemura/public/js/slider/scriptaculous/

▼yuiスライダーサンプル
http://staff.ark-web.jp/~takemura/public/js/slider/yui/

リンク先のコードを見てわかる通り、違いはほとんどありません。
インスタンス作成の際に引数が異なりますが、指定の仕方が違うだけでやろうとしていることは同じです。

▼script.aculo.us

	slider = new Control.Slider("handle1", "track1", {
	  onSlide:function(v){displayNewValue(v);},
	  onChange:function(v){displaySelectedSlide(v);},
	  range:$R(0,SLIDER_WIDTH -1)
	});

▼yui

	slider = YAHOO.widget.Slider.getHorizSlider("sliderbg", "sliderthumb", 
	  0, SLIDER_WIDTH - SLIDER_POINTER_WIDTH);
	slider.subscribe("change",   displayNewValue);
	slider.subscribe("slideEnd", displaySelectedSlide);

その他、動作が異なる部分は、イベントハンドラとして登録したdisplaySelectedSlide関数が異なります。
script.aculo.usは引数で直接現在のスライダーの位置が取れますが、YUIでは明示的にスライダーの位置を取得します。

▼script.aculo.us

// onSlideEndイベントが呼ばれたら実行するイベントハンドラ
function displaySelectedSlide(sliderValue) {
	var selectedSlideNo = Math.floor(sliderValue / oneBarLength);
	document.getElementById('slidermsg').innerHTML = '現在選択中のステータスは「'+
	  slideStatusList[selectedSlideNo] +'」です';
}

▼yui

// onSlideEndイベントが呼ばれたら実行するイベントハンドラ
function displaySelectedSlide() {
	var selectedSlideNo = Math.floor(slider.getValue() / oneBarLength);
	document.getElementById('slidermsg').innerHTML = '現在選択中のステータスは「'+
	  slideStatusList[selectedSlideNo] +'」です';
}

動作的に異なるのは、YUIがドラッグ移動中以外は change, slideEnd 両方のハンドラが呼ばれるのに対して、script.aculo.usはonMouseUpのタイミングで onChange が呼ばれ、onMouseMoveの状態では onChange が呼ばれます。

リンク先にも書きましたが、YUIではYUI内のアニメーションライブラリと組み合わせて、バーがスッと動くようなアニメーションが付与されています。

2007/10/22 11:15 追記━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
実は、スライダーライブラリはjQueryのUIという選択肢もあります。

▼jQuery UI
http://ui.jquery.com/

ただ、最新のjQueryでinterface.jsのスライダーを利用しようとしたところ、
IEで動作しなかったため、今回は取り上げていません。今後のライブラリのバージョンアップに期待です。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

では、次に「Zooomr」の説明をしていきます。

▼Zooomrフォト共有

http://www.zooomr.com/photos/17626@Z01/151669/

フォト共有サービスのZooomrの機能で面白いのは、写真の上に別の写真のレイヤーが配置できることです。
お粗末ながら、ちょっと同じものを作ってみました。

▼crossLayer サンプル

http://staff.ark-web.jp/~takemura/public/js/crosslayer/

まずは背景画像の上に乗るレイヤーの作成と、その中にリンク先の写真(以下、拡大画像)を用意して、display:none で配置します。

	var layer = document.createElement('div');
	$('back-image').appendChild(layer);
	layer.className = "layer";
	layer.id        = "my-layer";
	var oBackImagePosition = getPosition($('back-image'));
	layer.style.left   = (oBackImagePosition.x + giOffsetX) + "px";
	layer.style.top    = (oBackImagePosition.y + giOffsetY) + "px";
	layer.innerHTML    = '<div id="inner-image"><a href="image/img02.jpg">'+
	    '<img src="image/img02.jpg" width="500" height="375" border="0" /></a></div>';
	$('inner-image').style.display= 'none';
	
	Event.observe($('back-image'), "mouseover", startMousemove, false);
	Event.observe($('back-image'), "mouseout",  endMousemove, false);

その際に、レイヤー上にマウスが乗ったら(mouseover)拡大画像を表示するように実装し、この間はマウスの座標から拡大画像の位置を変更するイベントハンドラを設定しておきます。

また、レイヤーからマウスが離れたら(mouseout)拡大画像を隠すように実装し、イベントハンドラを解除しています。

function startMousemove() {
	Element.show('inner-image');
	Event.observe($('my-layer'), "mousemove", function(event){mouseMove(event);}, false);
}
function endMousemove() {
	Element.hide('inner-image');
	Event.stopObserving($('my-layer'), "mousemove", function(event){mouseMove(event);}, false);
}


そして、拡大画像の表示位置をマウスの座標に応じて移動させることでスクロールしているような実装になっています。マウスの座標は prototype.js の Event.pointerX, Event.pointerY で取ってこれます。

次回は、下記の3つのお題について説明する予定です。

「お題8>投稿するのが楽しくなるサイト」
「お題9>地図をフル活用したサイト」
「お題10>一歩先行くショッピングサイト」

次回で最終回です。よろしくお願いします。