Плавная смена картинок — Javascript, SVG и VML
На одном из разрабатываемых сайтов (школа боевых искусств) необходимо было разместить иконки с видами спорта, которые есть в этой школе. В итоге дизайнер предложил такое решение:

Чем порадовал и нас самих, и заказчика. Естественно к этой красоте должны были прилагаться такие эффекты как всплытие наверх картинки при наведении и выделение цветом картинки. Встал вопрос как технически реализовать.
Мысль о Flash'е я отверг весьма быстро, потому что
1. своего человека, хорошо знающего flash в команде нет
2. у меня стоит блокировка flash'а всего по умолчанию, ибо чаще всего там только реклама (привет, хабр)
3. нужен плагин — понятно что он стоит на 95% машин, но все же
4. зачем flash, если так можно и на js + svg/vml?
Писать родными методами с нуля на SVG (для нормальных браузеров) и VML (для IE, там поддержка SVG только через плагин) не хотелось — была найдена отличная либа raphael от нашего русского разработчика Дмитрия Барановского (кстати он есть на хабре, но ник не помню, побликаций по рафаэлю у него на хабре нет).
Достаточно быстро из всех рисунков было собрано то что было на макете — они были размещены и повернуты конструкцией такого вида:
var R = Raphael(«top_sports», 665, 274); //создаем поле для рисования, top_sports — id дива, цифры — размер поля
var img_wushu = R.image(«wushu.png», 0, 75, 178, 137).animate({rotation: 2}, 0); //создаем изображение в координатах 0,75 размером 178x137 и поворачиваем на 2 градуса, 0 после 2 означает что повернуть надо моментально
Как видно — все крайне просто, понятно и красиво.
После этого встал вопрос, как сделать чтоб картинки всплывали наверх при наведении. Для этого необходимо повесить небольшой обработчик, что также делается легко и просто:
$(img_wushu.node).mouseover(function(evt) {img_wushu_back.toFront();});
Теперь картинки при наведении стали моментально отображаться сверху, что было уже лучше чем ничего, но все таки весьма некрасиво. Хотелось чтоб картинка постепенно появлялась на верху, давая пользователю осознать происходящее. Однако метод toFront вгонял в уныние своей безаппеляционностью… И решение конечно же было найдено — наверное сказались попытки гейм-дева и множество прочитанных статей по теме.
Появилась мысль сделать всплытие картинки дополнительным слоем, который будет сперва отправляться toFront, а потом будет менять прозрачность с 0 до 100. Плюс потребуется пара мелких действий, кои я объясню по ходу.
Сперва создаем для каждого спорта две картинки:
var img_wushu = R.image(wushu_src, 0, 75, 178, 137); //создали основную картинку
var img_wushu_back = R.image(wushu_src, 0, 75, 178, 137).hide().animate({rotation: 2}, 0).toBack().show(); //создали, скрыли, повернули, отправили назад и там уже показали картинку, которую будем использовать для плавности
img_wushu.animate({rotation: 2}, 0); //повернули основную картинку
Поворот основной картинки лишь в конце происходит чтоб пользователь гарантированно не имел шансов увидеть создание второй картинки и какое-то мелькание связанное с этим. В принципе все происходит быстро и мне такого эффекта заметить не удавалось, но все же слегка перестраховался.
Теперь новый обработчки onmouseover (используя jquery):
$(img_wushu.node).mouseover(function(evt) {
img_wushu_back.attr({opacity:0}). //картинку используемую для плавности делаем полностью прозрачной
toFront(). //кладем ее на самый верх
animate({opacity:1},500); //и медленно, за пол секунды материализуем ее перед пользователем
setTimeout(function(){img_wushu.insertAfter(img_wushu_back);},501);}); //после того как промежуточная картинка стала непрозрачной, ложим на нее основную картинку, причем ложим уже не toFront, так сверху уже может всплывать другая картинка, а ложим ее поверх промежуточной картинки.
Вот и все решение — получилось весьма оригинально. Кроссбраузерно — IE6+, Opera, FF, Safari, наверное и Chrome, но в нем не проверял. Отдельным плюсом можно отметить что работает даже в Opera Mobile. Может будет работать в последнем мобильном IE, но проверить это не могу.
Тут можно увидеть живой пример получившегося.
P.S. Кросс-пост из blog.itea-lab.ru во избежание Х-эффекта
update Надо конечно как-то автоматизировать это все, чтоб добавление каждой картинки делалось с одной краткой строки — или плагин для raphael оформить, или хотя бы функцию завернуть. Но это уже бытовые мелочи, которые по ходу решим. :)
update 2 Все таки сервер накрыло. Хорошо так — даже по ssh не пускает. Как приотпустит — напишу.
update 3 Хабра-эффект временно отпустил. Можете продолжать. )
Ссылку на сайт школы дам в следующем посте, когда текущий пример доработаем, доделаем сайт в целом и слегка получше подготовимся к х-эффекту.
© Веб-студия iTea Lab — создание сайтов в Мурманске

Чем порадовал и нас самих, и заказчика. Естественно к этой красоте должны были прилагаться такие эффекты как всплытие наверх картинки при наведении и выделение цветом картинки. Встал вопрос как технически реализовать.
Мысль о Flash'е я отверг весьма быстро, потому что
1. своего человека, хорошо знающего flash в команде нет
2. у меня стоит блокировка flash'а всего по умолчанию, ибо чаще всего там только реклама (привет, хабр)
3. нужен плагин — понятно что он стоит на 95% машин, но все же
4. зачем flash, если так можно и на js + svg/vml?
Писать родными методами с нуля на SVG (для нормальных браузеров) и VML (для IE, там поддержка SVG только через плагин) не хотелось — была найдена отличная либа raphael от нашего русского разработчика Дмитрия Барановского (кстати он есть на хабре, но ник не помню, побликаций по рафаэлю у него на хабре нет).
Достаточно быстро из всех рисунков было собрано то что было на макете — они были размещены и повернуты конструкцией такого вида:
var R = Raphael(«top_sports», 665, 274); //создаем поле для рисования, top_sports — id дива, цифры — размер поля
var img_wushu = R.image(«wushu.png», 0, 75, 178, 137).animate({rotation: 2}, 0); //создаем изображение в координатах 0,75 размером 178x137 и поворачиваем на 2 градуса, 0 после 2 означает что повернуть надо моментально
Как видно — все крайне просто, понятно и красиво.
После этого встал вопрос, как сделать чтоб картинки всплывали наверх при наведении. Для этого необходимо повесить небольшой обработчик, что также делается легко и просто:
$(img_wushu.node).mouseover(function(evt) {img_wushu_back.toFront();});
Теперь картинки при наведении стали моментально отображаться сверху, что было уже лучше чем ничего, но все таки весьма некрасиво. Хотелось чтоб картинка постепенно появлялась на верху, давая пользователю осознать происходящее. Однако метод toFront вгонял в уныние своей безаппеляционностью… И решение конечно же было найдено — наверное сказались попытки гейм-дева и множество прочитанных статей по теме.
Появилась мысль сделать всплытие картинки дополнительным слоем, который будет сперва отправляться toFront, а потом будет менять прозрачность с 0 до 100. Плюс потребуется пара мелких действий, кои я объясню по ходу.
Сперва создаем для каждого спорта две картинки:
var img_wushu = R.image(wushu_src, 0, 75, 178, 137); //создали основную картинку
var img_wushu_back = R.image(wushu_src, 0, 75, 178, 137).hide().animate({rotation: 2}, 0).toBack().show(); //создали, скрыли, повернули, отправили назад и там уже показали картинку, которую будем использовать для плавности
img_wushu.animate({rotation: 2}, 0); //повернули основную картинку
Поворот основной картинки лишь в конце происходит чтоб пользователь гарантированно не имел шансов увидеть создание второй картинки и какое-то мелькание связанное с этим. В принципе все происходит быстро и мне такого эффекта заметить не удавалось, но все же слегка перестраховался.
Теперь новый обработчки onmouseover (используя jquery):
$(img_wushu.node).mouseover(function(evt) {
img_wushu_back.attr({opacity:0}). //картинку используемую для плавности делаем полностью прозрачной
toFront(). //кладем ее на самый верх
animate({opacity:1},500); //и медленно, за пол секунды материализуем ее перед пользователем
setTimeout(function(){img_wushu.insertAfter(img_wushu_back);},501);}); //после того как промежуточная картинка стала непрозрачной, ложим на нее основную картинку, причем ложим уже не toFront, так сверху уже может всплывать другая картинка, а ложим ее поверх промежуточной картинки.
Вот и все решение — получилось весьма оригинально. Кроссбраузерно — IE6+, Opera, FF, Safari, наверное и Chrome, но в нем не проверял. Отдельным плюсом можно отметить что работает даже в Opera Mobile. Может будет работать в последнем мобильном IE, но проверить это не могу.
Тут можно увидеть живой пример получившегося.
P.S. Кросс-пост из blog.itea-lab.ru во избежание Х-эффекта
update Надо конечно как-то автоматизировать это все, чтоб добавление каждой картинки делалось с одной краткой строки — или плагин для raphael оформить, или хотя бы функцию завернуть. Но это уже бытовые мелочи, которые по ходу решим. :)
update 2 Все таки сервер накрыло. Хорошо так — даже по ssh не пускает. Как приотпустит — напишу.
update 3 Хабра-эффект временно отпустил. Можете продолжать. )
Ссылку на сайт школы дам в следующем посте, когда текущий пример доработаем, доделаем сайт в целом и слегка получше подготовимся к х-эффекту.
© Веб-студия iTea Lab — создание сайтов в Мурманске



комментарии (84)