先日のスライドショーを少し進化させて、Flickrから最新の夕焼けの写真を取り出して順番に表示させる、というものを作ってみた。まずはデモから。
RSSフィードをFlickrに取りに行く部分にはjQueryを使い、スライドショーにはiAnime.jsを使ったのだが、ライブラリの力に大きく頼っているため、このスライドショー自身のコードはごくわずかである。
まずは、フィードを取りに行く部分がinit()。クロスドメインでのアクセスのためにproxyを介してFlickrからフィードを非同期通信で取得し、XMLとしてパースして、各<entry>中の<content type="html">タグの中身を含む<div>を生成して<div id="main">にインサートし、インサートしたdivの数をパラメータとしてstart()を呼ぶ、というかなり複雑な作業が、わずか数行で実現できている。
var tmplt="<div class='slide' id='pic{INDEX}'
onmouseover='HandleMouseOver(this)'
onmouseout='HandleMouseOut(this)'>{HTML}</div>";
function init()
{
jQuery.ajax({
url: 'http://www.uicentric.com/flickr_proxy.php',
data: 'url=http://api.flickr.com/services/feeds/photos_public.gne&tags=sunset',
dataType: 'xml',
success: function(xml) {
var all = "";
var i = 0;
jQuery("entry", xml).each(function() {
var html = jQuery("content[type='html']", this).text();
all += tmplt.replace(/{INDEX}/, i++).replace(/{HTML}/, html);
});
$("#main").html(all);
start(i);
}
});
}
ここまでコンパクトに書けるとすべてが一望できてしまうため作業効率がものすごく上がる。これぞインラインfunctionの威力だ。Cでこんなコードを書いたらいったい何行になるのか考えただけでもぞっとする。ちなみに、HTMLテキストの生成にレギュラー・エクスプレッションを使っているのは読みやすさのため。"<div id='pic'"+id+"'... の方が効率は良いかも知れないが、このケースでは読みやすさを優先すべきと判断。
init()でインサートした画像を含んだ<div>を順番に表示させるのは、start()の役目。iAnime.jsのJSONベースのアニメーション記述言語を使っているのだが、ミソは入れ子のアレイで指示しているいままで表示していたもののfadeoutを指示している部分。新しいdivは2秒でfedeinさせつつ、一つ前のものは0.5秒待ってから0.5秒でfadeoutさせてから完全にdisplay:hiddenにする、という意味である。
var anime = new iAnime();
function start(count)
{
var seq = [];
var prev = count-1;
for (var i=0; i<count; i++) {
seq = seq.concat([
[
{duration:500},
{id:'pic'+prev, effect:'fadeout', duration:500},
{id:'pic'+prev, effect:'hide'}
],
{id:'pic'+i, effect:'show'},
{id:'pic'+i, effect:'fadein', duration:2000},
{duration:4000}
]);
prev = i;
}
seq.push({ onComplete:function() {start(count);} });
anime.addSequence(seq);
}
残りのスクリプトは、マウスがスライドショーの上に来た時に一時的にアニメーションを止めるという処理。
function HandleMouseOver(obj)
{
anime.pause(true);
iBrowse.setOpacity(obj, 1);
obj.style.border = 'solid 2px #6666ff';
}
function HandleMouseOut(obj)
{
anime.pause(false);
obj.style.border = 'solid 2px #eeffff';
}