Если Вы занимаетесь веб-программированием, трудно быть специалистом только в одной области. Я занимаюсь разработкой скриптов на 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 | Filtered |
---|---|
Фильтры, которые делают анимированный переход, нужно сначало прописать в стилях, перед изменением изображения применить, потом изменить картинку, а после этого запустить воспроизведение. Например, так:
<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 мс, затем применяем фильтр, если таковой установлен. Потом меняем слайд, увеличивая текущий индекс, после этого устанавливаем таймер для показа следующего изображения. И, наконец, если фильтр был задан, то проигрываем его.
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, чтобы избежать проблем с теми браузерами, которые не поддерживают фильтры.
Код - пример использования плеера |
|
1 |
<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+, то слайды должны плавно сменять друг друга.
Testing | Control |
---|---|