Презентация картинок в виде слайдшоу

Как сделать красивое оформление для презентации я писал в заметке о Lightbox. А теперь расскажу, как собственно можно сделать саму презентацию.

Поставщиком картинок у нас будет сервис Flickr.

/**
 * Flickr photos provider
 */
(function () {

    var FLICKR_KEY = '4e1a2666b38001e7cb295852430274fe';
    var FLICKR_PREFIX = 'flickr-photo-';

Создаем замыкание, ограничивающее область видимости переменных и объявляем некоторые константы.

Замечу, что FLICKR_KEY содержит уникальный ключ Flickr API, который каждый разработчик должен бесплатно получить для своего приложения.

    APP.Flickr = function () {
        var me = Observable(this);
        me.init();
    };

Конструктор нашего поставщика. Он так же заботится об инициализации сервиса в целом. Для связи сервиса с приложением используется система событий.

    APP.Flickr.prototype = {
        init: function () {
            this.imageCache = document.createElement('div');
            $(this.imageCache)
                .attr('id', FLICKR_PREFIX + 'holder')
                .css({
                    'position': 'absolute',
                    'width': 0,
                    'height': 0,
                    'overflow': 'hidden'
                })
                .appendTo('body');
        },

Все изображения кэшируются для дальнейшего использования в невидимом блоке. Этот прием оказывается очень эффективным с небольшим количеством картинок в галерее.

        load: function (tags) {
            var me = this;
            $.getJSON('http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=' + FLICKR_KEY + '&format=json&tags=' + tags + '&content_type=1&jsoncallback=?',
                function(data) {
                    me.photos = data.photos;
                    me.notify('photosDidLoad', me.photos);
                }
            );
        },

Загружаем список картинок с заданными критериями поиска. Для взаимодействия с Flickr используется команда flickr.photos.search и протокол обмена информацией JSON.

Метод генерирует событие photosDidLoad, после удачного получения списка.

        showPhoto: function (index) {
            var me = this;
            var photo = me.photos.photo[index], img;
            var cached = $('#' + FLICKR_PREFIX + photo.id);
            if (cached.length === 0) {
                img = $('<img id="' + FLICKR_PREFIX + photo.id + '" title="' + photo.title + '" class="photo" />')
                        .appendTo(this.imageCache)
                        .load(function () {
                            me.notify('imageReady', img);
                        })
                        .attr('src', 'http://farm' + photo.farm + '.static.flickr.com/' + photo.server + '/' + photo.id + '_' + photo.secret + '.jpg');
            } else {
                me.notify('imageReady', cached);
            }
        }
    };
})();

Загружаем изображение из списка или берем его из кеша, если оно было уже загружено ранее.

Метод генерирует событие imageReady и передает подписчикам изображение, когда оно будет готово к использованию.

Теперь перейдем к коду нашего приложения, использующее только что созданный сервис и эффектно сменяющее картинки. Создаем объект поставщика картинок и подписываемся на его события.

$(function () {
    var provider = new APP.Flickr(),
        wait = false;
    provider.attachObserver('photosDidLoad', function (data) {
        var i = 0;
        (function () {
            i = (i >= data.length) ? 0 : i;
            if (!wait) {
                wait = true;
                provider.showPhoto(i++);
            }
            setTimeout(arguments.callee, 2000);
        })();
    });

Когда поставщик сообщит о том, что список загружен, мы запускаем циклический просмотр изображений с интервалом в 2 секунды.

Так как в JavaScript нет паузы как таковой, то применяется такой отложенный асинхронный вызов анонимной функции. Это стало возможным благодаря тому, что внутри любой функции поле callee объекта arguments всегда ссылается на выполняющуюся функцию.

    provider.attachObserver('imageReady', function (img) {
        $('#showroom img.photo')
                .animate({
                    'opacity': 0
                }, function () {
                    $(provider.imageCache).append(this);
                });
        $(img).appendTo('#showroom')
                .css({
                    'opacity': 0
                })
                .centering()
                .animate({
                    'opacity': 1
                }, function () {
                    wait = false;
                });
    });

Как только очередная картинка будет загружена, она центрируется на странице и ее прозрачность плавно меняется с 0 до 1. Тем временем, у текущей картинки меняется прозрачность до 0 и затем она отправляется в кеш.

    provider.load('apple,mac');
});

Загружаем список картинок с тегами «apple» и «mac».

Слайдшоу начнется сразу после загрузки страницы и будет продолжаться до тех пор, пока страница не будет закрыта.