🎞️

複数のコンテンツ項目を自動的にスライド表示する

たとえば、Twitterのタイムラインを自分のブログなどに表示するとき、Twitterから公式に提供されているウィジェットを使えばほぼ問題無いのだけど、表示する発言に何らかのフィルタをかける等、TwitterのAPIを使って処理した結果を、動きを付けてスライド表示させたい、という場合。

こちらのサイト(8works-web.com、現在は閉鎖)で紹介されているように、「Simple jQuery Spy Effect」というJSがあるので、基本的にはこれを使うとよいです。

ただ、このスクリプトにはちょっと難点があって、1つの項目を表示する欄の高さが一定になっています。基準となるのは、先頭の項目の表示高さです。 Twitterのつぶやきの長さは一定ではないので、表示に必要な高さも一定ではないのですが、スクリプトをそのまま使うと、2つめ以降の表示が途中で切れたり、余白ができたりしてちょっとカッコ悪いです。

ということで、ちょっと修正して、欄の高さを可変にしてみました。

(当時は scripts.songs-inside.com に表示サンプルを置いていましたが、現在は公開していません)

JavaScriptサンプル

$(function () {
    $('ul.twitter').simpleSpy();
});
(function ($) {
$.fn.simpleSpy = function (limit, interval) {
    limit = limit || 5;
    interval = interval || 5000;
    return this.each(function () {
        // 1. setup
            // capture a cache of all the list items
            // chomp the list down to limit li elements
        var $list = $(this),
            $list2 = $('ul.twitter-dummy'),
            items = [], // uninitialised
            currentItem = limit,
            total = 0, // initialise later on
            height = '300px';
        // capture the cache
        $list.find('> li').each(function () {
            items.push("<li class='update clear clearfix'>" + $(this).html() + "</li>");
        });
        total = items.length;
        $list.find('> li').filter(':gt(' + (limit - 1) + ')').remove();
        // 2. effect
        function spy() {
            // insert a new item with opacity and height of zero
            var $insert = $(items[currentItem]).css({
                height : 0,
                opacity : 0,
                display : 'none'
            }).prependTo($list);

        // get real height
        var $insert2 = $(items[currentItem]).css({
            opacity : 0,
            display : 'none'
        }).prependTo($list2);
        height = $list2.find('> li:first').height();

        // fade the LAST item out
        $list.find('> li:last').animate({ opacity : 0}, 1000, function () {
            // increase the height of the NEW first item
            $insert.animate({ height : height }, 1000).animate({ opacity : 1 }, 1000);
            // AND at the same time - decrease the height of the LAST item
            // $(this).animate({ height : 0 }, 1000, function () {
                // finally fade the first item in (and we can remove the last)
                $(this).remove();
            // });
        });
        currentItem++;
        if (currentItem >= total) {
            return;
        }
        setTimeout(spy, interval)
    }
    spy();
});

};
})(jQuery);

HTMLサンプル

<ul class="twitter">
<li class='update clear clearfix'>つぶやきつぶやき</li>
<li class='update clear clearfix'>つぶやきつぶやき</li>
<li class='update clear clearfix'>つぶやきつぶやき</li>
<li class='update clear clearfix'>つぶやきつぶやき</li>
<li class='update clear clearfix'>つぶやきつぶやき</li>
</ul>
<ul class='twitter-dummy'></ul>

概要としては以下の通り。

  1. 表示に必要な高さを得るために、表示場所と同じスタイルが適用されるulオブジェクトをもう1つ作ります(サンプルでは「twitter-dummy」というのを作ってます)[HTMLサンプル8行目]
  2. そのオブジェクトに対してアイテムを追加します[JavaScriptサンプル34行目~]
  3. ダミーのオブジェクトはheightを指定しないようにして、表示に必要な高さを取得します[JavaScriptサンプル38行目]
  4. その高さを、本来の表示場所の表示高さに指定します[JavaScriptサンプル43行目]

そうするとキレイにできますよ、と。