Unformed Building

picplzのAPIを使ってギャラリーを作ってみた

公開:
更新:

パーマリンク

2020年1月7日 追記:
picplzは2012年7月3日に閉鎖されましたので、この記事のデモはもはや動きません。


写真にフィルタをかけてアップロードできる写真SNSのpicplzですが、2月にAPIが公開されていましたので、それを使ってギャラリーを作ってみました。

picplz API

今回はpicplzのinterestingにある画像を一覧表示します。
いやまあ直接見に行けばいいってのは分かってますけどねw
デモとダウンロードは以下からどうぞ。
IE 8以降なら普通に見れると思います。

Interesting Photo Gallery w/ picplz API

デモファイルをダウンロード

まずはHTMLから。
必要な要素をそのまま記述しておきます。

<div id="gallery">
  <!--
    ここにサムネイルのギャラリーが入る
    ul > li > a > img
  -->
  <div id="loader">
    <!-- ローディング画像 -->
    <img src="ajax-loader.gif" alt="loading..." />
  </div>
  <div id="more">
    <!-- 更に画像を読みこむためのボタン -->
    <a href="#">more pic please!</a>
  </div>
</div><!-- // #gallery -->

<!-- 表示領域全体を覆う -->
<div id="view-layer"></div>

<!-- 拡大画像や詳細を入れる -->
<div id="view-container">
  <div id="view-content"><!-- ここにに入る --></div>
  <a href="#" class="close">&#x2716;</a><!-- 閉じるボタン -->
</div>

jQueryで追加してもいいんですけど、めんどくさくなってきたので直接書きました。
次はCSSですが、特に変わったことはしていませんので、デモページのを見るなりダウンロードして確認するなりしてください。
ちなみに、text-shadow0 0 0 transparentはChrome対策です。

ではjQueryを使って書いていきます。
説明はコメントでやります。

jQuery(function ($) {
  // ここにコードを書いていきます。
});

お約束を書いたら、まずは各種変数を。

// 設定
var o = {
  perPage   : 24,     // 1回のロード毎の画像取得数
  thumbSize : '100s', // 56, 64, 75, 100, 200
  picSize   : '400r'  // 150, 320, 400, 640, 1024
}

// セレクタを変数に入れておく
var $gallery       = $('#gallery'),
    $loader        = $('#loader').children('img'),
    $more          = $('#more').children('a');
    $viewLayer     = $('#view-layer'),
    $viewContainer = $('#view-container'),
    $viewContent   = $('#view-content'),
    $closeButton   = $viewContainer.children('a.close');

var lastPicId,      // last_pic_id 用
    clickCount = 0; // ロードした回数の管理
    maxCount   = Math.ceil(240 / o.perPage) - 1; // ロードできる回数の最大値

// サムネイルリスト用
var $imageList = $('<ul/>').prependTo($gallery);

o.thumbSizeとかのsは正方形、rは最長サイズです。
ロードできる回数というのは、このAPIで取れる画像は240枚までなので、呼び出し回数を先に決めておきます。

次はデータを取得する部分。

// 画像を取得する
function loadImages(last) {

  // パラメータ
  var ajaxData = {
    type          : 'interesting',
    pic_page_size : o.perPage,
    pic_formats   : o.thumbSize + ',' + o.picSize
  };

  // last_pic_id を持っていたら(2回目以降)パラメータに追加する
  if (last) {
    ajaxData.last_pic_id = last;
  }

  // API からデータを取得する
  $.ajax({
    url      : 'http://api.picplz.com/api/v2/feed.json',
    dataType : 'jsonp',
    data     : ajaxData,
    success  : function (data) {
                 getPics(data);
               }
  });
}

パラメータなどはAPIドキュメントを見てください。
last_pic_idを指定してAPI叩くと、その画像の続きから取得できます。

次はデータ取得が成功したときの処理です。

// データ取得後
function getPics(d) {

  // ローディング画像を表示
  $loader.show();

  // last_pic_idを変数に格納(上書きしていく)
  lastPicId = d.value.last_pic_id;

  var images = d.value.pics,  // 画像データの配列
      count  = 0,             // 画像の枚数管理
      limit  = images.length; // 画像の配列の要素数

  $.each(images, function (i, p) {

    // 各種データ
    var img = {
      pageUrl  : 'http://picplz.com' + p.url,
      thumbUrl : p.pic_files['100s'].img_url,
      largeUrl : p.pic_files['400r'].img_url,
      caption  : p.caption ? p.caption : '(Untitled)',
      date     : convertTime(p.date),
      count    : {
        pv       : p.view_count,
        like     : p.like_count,
        comment  : p.comment_count
      },
      creator  : {
        userName    : p.creator.username,
        displayName : p.creator.display_name,
        iconUrl     : p.creator.icon.url,
        following   : p.creator.following_count,
        follower    : p.creator.follower_count
      }
    }

    // 画像をロードする
    $('<img/>').load(function () {

      // カウントを1つ増やす
      ++count;

      // 画像のロードが終わったらli要素を作る
      makeList($(this), img);

      // 最後の画像だったら、ロード完了後にリストを全て表示
      if(count === limit) {
        showThumbs();
      }
    }).attr({
      src   : img.thumbUrl,
      alt   : img.caption,
      title : img.caption
    });
  });
}

サムネイル画像は、画像のロードが終わってから表示するようにしています。
ここでは画像のデータをまとめておいて、それを引数として関数に渡しています。

次は画像のロードが終わったときに使う関数を作ります。

// 画像のロードが終わったらli要素を作って$imageListに追加する
function makeList(e, t) {

  // リンクを作る&イベント
  var $anchor = $('<a/>').attr('href', t.largeUrl)
                         .click(function (e) {
                           viewImage(e, t)
                         });

  // 上で作ったimg要素をリンクに追加
  e.appendTo($anchor);

  // ul要素に追加するli要素(フェードイン用に一旦非表示に)
  $('<li/>').hide().append($anchor).appendTo($imageList);

}

// サムネイルを全て表示する
function showThumbs() {

  // ローディング画像を非表示に
  $loader.fadeOut(100);

  // ロード回数が最大値になったらmoreを消す
  if(clickCount === maxCount) {
    $more.parent().fadeOut(function () {
      $(this).remove();
    });
  }

  // リストをフェードイン表示
  $imageList.children().fadeIn();
}

ここまで終わって、サムネイル一覧が表示されるようになりました。
次はサムネイルをクリックしたときの処理です。

// サムネイルをクリックしたときの動作
function viewImage(e, pic) {

  // リンク動作を無効にする
  e.preventDefault();

  // 前に表示したものを消す
  $viewContent.empty();

  // 書き出すHTMLのテンプレート
  var markup = '(長いので省略します)';

  // テンプレートに設定
  $.template("viewDetail", markup);

  // テンプレートとデータを結びつけて、$viewContentに追加する
  $.tmpl("viewDetail", pic).appendTo($viewContent);

  // レイヤーと画像詳細のdivをフェードイン
  $viewLayer.fadeIn(600);
  $viewContainer.fadeIn(600);
}

ここではjQuery Templatesを使って書き出すHTMLを作っています。
使わなくてもできますが、めんどくさかったので……。

// 閉じるボタンやレイヤーのブランク部分をクリックしたときの処理
function closeView(e) {
  e.preventDefault();
  $viewLayer.fadeOut(300);
  $viewContainer.fadeOut(300);
}

// Unix timeを読めるように変換
function convertTime(u) {

  // 数字が1桁の場合にゼロパディングする
  function paddingZero(n) {
    return n > 9 ? n : '0' + n;
  }

  var t = new Date(u * 1000);
  t.setTime(t.getTime() + (60 * 60 * 1000));

  var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

  // 整形
  var year  = t.getFullYear(),
      month = months[t.getMonth()],
      date  = paddingZero(t.getDate()),
      hour  = paddingZero(t.getHours()),
      min   = paddingZero(t.getMinutes()),
      sec   = paddingZero(t.getSeconds());

  var pubdate = month + ' ' + date + ', ' + year + ' ' + hour + ':' + min + ':' + sec;

  return pubdate;
}

拡大画像を閉じるための処理ですね。
あと、picplz APIでは画像の投稿時刻がUNIX timeで書かれているので、それを人間にも読めるように書き換えています。

2011年6月3日 追記:
日付の処理は置換を使っていましたが、変更しました。

// moreをクリックしたときの動作
$more.click(function (e) {
  e.preventDefault();

  // ロード回数を1つ増やす
  clickCount++;

  // last_pic_idを指定して再度取得
  loadImages(lastPicId);
});

// レイヤーと閉じるボタンのクリック動作
$viewLayer.click(function (e) {
  closeView(e);
});
$closeButton.click(function (e){
  e.preventDefault();
  closeView(e);
});

$moreをクリックしたら、また画像を取ってくるようにしています。
残りの2つは画像の詳細を閉じる動作です。

// ページを開いた直後に行う取得処理
loadImages();

ページを開いた直後と書いてますが、ドキュメントの読み込みが完了したときですね。

以上で終わりです。お疲れ様でした。