Плеер картинок

Преамбула

Если Вы занимаетесь веб-программированием, трудно быть специалистом только в одной области. Я занимаюсь разработкой скриптов на php, но фактически это означает, что требуется ещё знать и JS, HTML, CSS, если не в совершенстве, то хоть как-нибудь.

Амбула

Пришёл заказчик с желанием разместить у себя на главной странице плеер картинок. Были прдъявлены следующие требования:

  • плавная смена картинок
  • картинки должны показываться только когда загрузятся

До этого у заказчика уже была сделана галерея на ява-скрипте. Проблема была в том, что в режиме автоматической смены картинок, изображения не успевали загружаться и отображаться, толку от такой галереи было мало.

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

Немного про фильтры

Фильтры устанавливаются через CSS в виде списка. Выглядит это следующим образом:

Старый стиль:

<img style="filter:Фильтр1(параметр=значенме, ...) Фильтр2() ..." />

Новый стиль, используя progid:

<img style="filter:progid:DXImageTransform.Microsoft.Фильтр1(параметр=значенме, ...) Фильтр2() ..." />

Старый стиль поддерживается IE, начиная с версии 4, новый только с 5.5.

 

Новый стиль предоставляет больше фильтров и большее число параметров, которое можно передавать фильтру. Но, если честно, я не нашёл существенных различий, большенство фильтров нового стиля так или иначе доступны и в старом. Единственное - новый стиль позволяет делать более тонкие настройки.

Фильтры, которые накладываются на изображение, можно просто прописать через CSS, но применятся они, только если разрешено выполнение скриптов. Прописать их можно так:

<img src="1.jpg" style="filter: alpha(opacity=50) fliph flipv xray" /> 

 

Source Filtred
  Netscape не поддерживает фильтры
 

 

 

Фильтры, которые делают анимированный переход, нужно сначало прописать в стилях, перед изменением изображения применить, потом изменить картинку, а после этого запустить воспроизведение. Например, так:

 

 

<img src="2.jpg" style="filter: blendtrans(duration=1)" id="i" />

<br />

<input type="button" onclick="i.filters['blendTrans'].apply();i.style.visibility='hidden';i.filters['blendTrans'].play()" value="Hide" /><br />

<input type="button" onclick="i.filters['blendTrans'].apply();i.style.visibility='visible';i.filters['blendTrans'].play()" value="Visible" /><br />

 

Помимо плавного перехода blendTrans для трансформации можно использовать анимированный фильтр revealTrans, у которого есть дополнительный параметр transition, отвечающий за вид трансформации. Параметр transition должен содержать целое положительное число.

 

<img src="3.jpg" style="filter: revealTrans(duration=1, transition=0)" id="i2" />

<br />

<input type="button" onclick="i2.filters['revealTrans'].apply();i2.style.visibility='hidden';i2.filters['revealTrans'].play()" value="Hide" /><br />

<input type="button" onclick="i2.filters['revealTrans'].apply();i2.style.visibility='visible';i2.filters['revealTrans'].play()" value="Visible" /><br />

 

Подробнее о фильтрах можно узнать на http://msdn.microsoft.com/en-us/library/ms532849(VS.85).aspx.

 

Постановка задачи

Нужно разработать ява-скрипт для простой смены картинок с возможностью использовать фильтры. Список картинок заранее известен. Скрипт должен корректно работать в браузерах IE, FF, Opera. Если JavaScript отключён, то должен отрабатывать простой HTML. Картинки должны отображаться циклично.

 

Разработка

Первоначально есть только список слайдов, на основе которого нужно сделать слайд-шоу.

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

 

/**

 * Image gallery viewer

 * Author: zg, 2008-03-10

 */

var ImageList = new Array();

ImageList.addImage = function (ImageSrc) {

   var Img = new Image();

   Img.src = ImageSrc;

   this[ this.length ] = Img;

}


Таким образом, ImageList изначально является объектом "массив", дополнительно расширен функцией, которая может добавлять в него картинки. Для добавления слайда в список воспроизведения достаточно вызвать ImageList.addImage('путь до картинки').

Уже можно формировать список слайдов.

 

// Preload images

ImageList.addImage('1.jpg');

ImageList.addImage('2.jpg');

ImageList.addImage('3.jpg');

ImageList.addImage('4.jpg');

 

В массиве ImageList будет находиться четыре объекта Image. К слову, подгрузка изображений начинётся сразу после добавления нового изображения к списку, поэтому не стоит изначально делать большой список, новые изображения можно добавлять в любой момент времени.

Далее я определил необходимые свойства нового объекта.

 

// Properties

ImageList.playing = false;

ImageList.timer = null;

ImageList.img = null;

ImageList.imgFilter = null;

ImageList.cur = 0;

ImageList.delay = 2000; // 2 sec.

 

ImageList.playing - флаг, который будет отвечать за текущее состояние воспроизведения, true - если проигрыватель листает картинки, false иначе

ImageList.timer - текущий таймер, по которому происходит переход на следующий слайд

ImageList.img - объект <img>, который будет показывать картинки из списка

ImageList.imgFilter - фильтр, который будет накладываться на изображения для игры переходов

ImageList.cur - индекс текущего изображения

ImageList.delay - задержка смены слайдов в миллисекундах

 

Этих свойств вполне хватит, чтобы организовать требуемый функционал.

 

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

 

ImageList.play() - запускает цикличный показ слайдов

ImageList.stop() - останавливает показ

ImageList.next() - делает переход к следующему слайду

 

Запуск показа слайдов

 

ImageList.play = function() {

    if ( !this.playing )

    {

        this.playing = true;

        this.next();

    }

}


Никаких хитростей в этой функции нет - если флаг воспроизведения не установлен, то устанавливаем его и показываем следующее изображение. Все хитрости будут описаны в функции next().

 

Остановка показа


ImageList.stop = function() {

    if ( this.playing )

    {

        clearTimeout(this.timer);

        this.timer = null;

        this.playing = false;

    }

}

 

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

 

Переход к следующему слайду

 

ImageList.next = function() {

    if ( this.playing && this.length && this.img )

    {

        // Check end

        if ( this.cur >= this.length ) this.cur = 0;

        

        // Check complete status

        if ( !this[this.cur].complete )

        {

            setTimeout("ImageList.next()", 50); // wait, while image is loading

            return false;

        }

        

        if ( this.imgFilter )

        {

            // Set random transition

            if ( typeof(this.imgFilter.transition) != 'undefined' )

                this.imgFilter.transition = Math.floor(Math.random() * 99);

            

            this.imgFilter.apply();

        }

        

        // Change image

        this.img.src = this[ this.cur++ ].src;

        

        // Set next timer

        this.timer = setTimeout("ImageList.next()", this.delay);

        

        // Play filter

        if ( this.imgFilter ) this.imgFilter.play();

        

        return true;

    }

}

 

Логика работы этой функции следующая - если флаг воспроизведения установлен, в списке есть изображения и объект, который будет отображать слайды установлен, то выполняем работу по смене изображения. Проверяем, может быть, пора повторить список сначала? Дальше проверяем, загрузилось ли изображение, если нет, то повторим попытку через 50 мс, затем применяем фильтр, если таковой установлен. Потом меняем слайд, увеличивая текущий индекс, после этого устанавливаем таймер для показа следующего изображения. И, наконец, если фильтр был задан, то проигрываем его.

 

Установка объекта <img>

 

ImageList.setImg = function(Img) {

    this.img = Img;

    this.imgFilter = null;

    

    try

    {

        // Try to get filter (IE only)

        for (var i in Img.filters)

        {

            if ( typeof(Img.filters[i]) != 'object' ) continue;

            if ( typeof(Img.filters[i].apply) == 'undefined' ) continue;

            if ( typeof(Img.filters[i].play ) == 'undefined' ) continue;

            

            this.imgFilter = Img.filters[i];

            break;

        }

    }

    catch(e)

    {

        // No filter :'(

    }

}

 

Изначальноэта функция не планировалась, но встал вопорос, каким образом извлекать установленный на объекте <img> фильтр, и я решил сделать специальную функцию. Поскольку фильтры доступны пока только в IE, то нужно поместить код для выбора фильтра в конструкцию try ... catch, чтобы избежать проблем с теми браузерами, которые не поддерживают фильтры.

 

Тестирование

Код - пример использования плеера

 

<html>

<head>

<script language="javascript">

/**

 * Image gallery viewer

 * Author: zg, 2008-03-10

 */

var ImageList = new Array();


ImageList.addImage = function (ImageSrc) {

    var Img = new Image();

    Img.src = ImageSrc;

    this[ this.length ] = Img;

}


// Preload images

ImageList.addImage('1.jpg');

ImageList.addImage('2.jpg');

ImageList.addImage('3.jpg');

ImageList.addImage('4.jpg');


// Properties

ImageList.playing   = false;

ImageList.timer     = null;

ImageList.img       = null;

ImageList.imgFilter = null;

ImageList.cur       = 0;

ImageList.delay     = 2000; // 2 sec.


// Functions

ImageList.play = function() {

    if ( !this.playing )

    {

        this.playing = true;

        this.next();

    }

}


ImageList.stop = function() {

    if ( this.playing )

    {

        clearTimeout(this.timer);

        this.timer = null;

        this.playing = false;

    }

}


ImageList.next = function() {

    if ( this.playing && this.length && this.img )

    {

        // Check end

        if ( this.cur >= this.length ) this.cur = 0;

        

        // Check complete status

        if ( !this[this.cur].complete )

        {

            setTimeout("ImageList.next()", 50); // wait, while image is loading

            return false;

        }

        

        if ( this.imgFilter )

        {

            // Set random transition

            if ( typeof(this.imgFilter.transition) != 'undefined' )

                this.imgFilter.transition = Math.floor(Math.random() * 99);

            

            this.imgFilter.apply();

        }

        

        // Change image

        this.img.src = this[ this.cur++ ].src;

        

        // Set next timer

        this.timer = setTimeout("ImageList.next()", this.delay);

        

        // Play filter

        if ( this.imgFilter ) this.imgFilter.play();

        

        return true;

    }

}


ImageList.setImg = function(Img) {

    this.img = Img;

    this.imgFilter = null;

    

    try

    {

        // Try to get filter (IE only)

        for (var i in Img.filters)

        {

            if ( typeof(Img.filters[i]) != 'object' ) continue;

            if ( typeof(Img.filters[i].apply) == 'undefined' ) continue;

            if ( typeof(Img.filters[i].play ) == 'undefined' ) continue;

            

            this.imgFilter = Img.filters[i];

            break;

        }

    }

    catch(e)

    {

        // No filter :'(

    }

}

</script>

</head>


<body>


<img style="filter:blendtrans(duration=1)" id="imgMain" src="1.jpg" />


<script language="javascript">


ImageList.setImg(imgMain);  // Set image object

ImageList.play();  // Play gallery


// Control buttons

document.writeln('<br />');

document.writeln('<input type="button" onclick="ImageList.play()" value="Play" />');

document.writeln('<input type="button" onclick="ImageList.stop()" value="Stop" />');


</script>


</body>


</html>

 

Если у Вас включён JavaScript, то изображение, которое расположено ниже, будет меняться. Если используется Internet Explorer 4+, то слайды должны плавно сменять друг друга.




Рекомендуем почитать

 

Добавить комментарий


Ваше имя:


Комментарий:


Введите: Картинка