Lecaw

Учимся создавать Web-сайты

Создание современного лайтбокса на CSS3 и JavaScript

May 28, 2012
CSS
2341hits

Сегодня к нам пришло письмо от нашего гостя  Andy Walpole который делится своим опытом создания Lightbox Ultra расположенный на Mozilla Demo Studio. Несколько лет назад разработчик Lokesh Dhakar создал  сценарий лайтбокса с Prototype и script.aculo.us. Его плавная анимация и гладкая эстетика была хитом в обществе веб-дизайнеров, и он был использован во многих проектах.

ДЕМО

 Исходные файлы

 

Затем было много подражателей - Fancybox и Thickbox,  но лайтбокс по прежнему остается излюбленным способом показа изображения для пользователя. Это, прежде всего, связано с его 3D-анимации и затемнённым фоном, который позволяет пользователю просматривать изображение не отвлекаясь на другие детали.

CSS анимацией я впервые начал пользоваться еще несколько лет назад, многие программисты используют её для воплощения своих идей. Действительно, существует реальное увлечение CSS-анимацией, но это только эксперименты. В ближайшем будущем CSS вытеснит JavaScript на уровне визуализации, поэтому сейчас мы будем использовать для нашей цели именно CSS.

Совсем недавно я соделал проект на CSS, он был выставлен на сайте Mozilla Demo под названием Lightbox Ultra. Его ядро в частности - CSS3 , 3D-анимация - но в процессе создания демо я понял, что нужно добавить JavaScript, для определённых удобств и конструктивных особенностей.

В данном руководстве нет пояснения мелких деталей кода, который я написал для моего Lightbox проекта. Что бы не запутать читателя. Вместо этого, я объясню некоторые из основных концепций создания современного Лайтбокса. Таким образом, вы можете использовать эти идеи в своем собственном проекте.

CSS и Лайтбокс

Начнем с HTML:

html для лайтбокса

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

Полноразмерное изображение должно быть установлено с "display: none", так что начальным состоянием для пользователя будет только эскиз:

display: none

Полноразмерное изображение появляется после взаимодействия пользователя с миниатюрами.

Для этого нужно использовать события JavaScript. Изменим небольшую часть кода CSS, с использованием "display:block" когда пользователь кликает на иконку (Здесь я используюquery Selector (), который имеет только частичную кросс-браузерную поддержку):

var thumbnail = document.querySelector(".first-image img");
var fullSize = document.querySelector(".second-image img");
thumbnail.onclick = function () {
    fullSize.style.display = "block";
}

Сейчас мы должны использовать события JavaScript в CSS для псевдо-класса :target. Я не знаю, чьей идеей было представить :target в спецификацию CSS3, но его включение стало значительным актом изобретательности.

.second-image dl:target {
    display: block;
}

:target работает с использованием фрагмента URL. Ссылка на эскиз имеет следующий фрагмент: "#block-1". Это идентификатор полного размера блока-1. При нажатии на ссылку с фрагментом, запускается HTML с его ID, до тех пор, конечно, пока вы не укажите его в таблице стилей.

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

В будущем :target станет одной из наиболее часто используемых функций CSS3. Правда у него есть один минус, он не поддерживается в  Explorer 8 и ниже. Я расскажу вам как использовать его альтернативу в следующем разделе.

CSS keyframe довольно прост:

/* animation for main image */
.second-image dl:target .animation {
    -moz-animation: image3D 2000ms cubic-bezier(0.950,0.050,0.795,0.035);
    -webkit-animation: image3D 2000ms cubic-bezier(0.950,0.050,0.795,0.035);
    -ms-animation: image3D 2000ms cubic-bezier(0.950,0.050,0.795,0.035);
    -o-animation: image3D 2000ms cubic-bezier(0.950,0.050,0.795,0.035);
    animation: image3D 2000ms cubic-bezier(0.950,0.050,0.795,0.035);
}
/* image3D is used on the main image */
@-moz-keyframes image3D {
    0% {
       -moz-transform: rotateY(90deg);
    }
    100% {
       -moz-transform: rotateY(0deg);
    }
}
@-webkit-keyframes image3D {
    0% {
       -webkit-transform: rotateY(90deg);
    }
    100% {
       -webkit-transform: rotateY(0deg);
    }
}
@-o-keyframes image3D {
    0% {
       -o-transform: rotateY(90deg);
    }
    100% {
       -o-transform: rotateY(0deg)
    }
}
@-ms-keyframes image3D {
    0% {
       -ms-transform: rotateY(90deg);
    }
    100% {
       -ms-transform: rotateY(0deg);
    }
}
@keyframes image3D {
    0% {
       transform: rotateY(90deg);
    }
    100% {
       transform: rotateY(0deg);
    }
}

Я не буду подробно объяснять код, приведенный выше, потому что эта статья не является руководством по CSS3 анимации. Для этого я бы посоветовал Вам прочитать статью написанную Tim Van Damme, Louis Lazaris и Tom Waterhouse.

Обратите внимание, в приведенном выше коде я использовал Webkit, Firefox, Microsoft и Opera prefixes. Пока еще нет поддержки ключевых кадров в Internet Explorer или Opera.

JavaScript и Lightbox

На моей странице в Mozilla Demo у меня было много забавных вещей при создании этого лайтбокса. Я использовал box-shadows, функции Calc () , градиенты и CSS3 преобразования. Если отключить JavaScript в вашем браузере и попробовать запустить демо в современных браузерах, увидите, что оно находится в отличном рабочем состоянии.

Тем не менее, есть это некоторые трудности с CSS3, к которым мы будем применять дополнительные методы.

Во-первых, анимация  CSS3  только срабатывает один раз. Этот вопрос уже хорошо описали Oli Studholme и Chris Coyier.

CSS3 keyframes  будут работать только раз, если не обновлять страницу. Одним из обходных путей заключается использование transitions  вместо keyframes. Другой способ заключается в использовании JavaScript для восстановления узла, каждый раз, когда анимация запускается.

Сейчас нужно удалить старый класс в методе change_animation (), дублировать соответствующую часть DOM,  добавить случайный класс, удалить интернет узел и заменить его дубликатом  DOM:

change_animation: function (htmlElement) {
    var items, random, regEx, result, key, mainBlock, cloneBlock, parentBlock;
    // below finds the unique key which is in the parent div id
    function removeArrayElement(element, index, array) {
       return (!element.search(_private.REMOVE_SEARCH));
    }
    regEx = /.([0-9]+)$/;
    result = regEx.exec(htmlElement.parentNode);
    key = result.filter(removeArrayElement).toString();
    // this unique key is then used to find the large image in the overlay
    // this is an alternative to some bonkers DOM transversal method
    mainBlock = document.querySelector("#block-" + key + " img");
    // remove previous animation class
    mainBlock.removeAttribute("class", "");
    // In order for CSS animation to run more than once on the same element
    // It is necessary to rebuild the node
    // See for further details: http://css-tricks.com/restart-css-animation/
    cloneBlock = mainBlock.cloneNode(true);
    // select a class at random
    items = this.classes;
    random = items[Math.floor(Math.random() * items.length)];
    // rebuild the html adding the new class
    cloneBlock.setAttribute("class", random);
    parentBlock = mainBlock.parentNode;
    parentBlock.removeChild(mainBlock);
    parentBlock.appendChild(cloneBlock);
}

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

Глобальный пользовательский интерфейс:

lightbox.init({
    // declare CSS classes that are used for animation
   classes: ['image3D', 'flipper', 'bulge', 'bouncing', 'side-spin', 'top-spin', 'shadow-play', 'rush']
});

Для того чтобы изменить анимацию нужно просто добавить новый класс в CSS и JavaScript. Упомянутый выше, "top-spin" выглядит следующим образом:

/* TOPSPIN */
.top-spin {
    -moz-animation: topSpin 2000ms cubic-bezier(0.000, -0.600, 0.000, 1.650);
    -webkit-animation: topSpin 2000ms cubic-bezier(0.000, -0.600, 0.000, 1.650);
    -ms-animation: topSpin 2000ms cubic-bezier(0.000, -0.600, 0.000, 1.650);
    -o-animation: topSpin 2000ms cubic-bezier(0.000, -0.600, 0.000, 1.650);
    animation: topSpin 2000ms cubic-bezier(0.000, -0.600, 0.000, 1.650);
}
@-moz-keyframes topSpin {
    0% {
       -moz-transform: rotateX(0deg);
       -moz-transform-origin: 0% 50% 0;
    }
    100% {
       -moz-transform: rotateX(360deg);
       -moz-transform-origin: 0% 50% 0;
    }
}
@-webkit-keyframes topSpin {
    0% {
   opacity: 0.1;
       -webkit-transform: rotateX(0deg);
       -webkit-transform-origin: 0% 50% 0;
    }
    100% {
   opacity: 1;
       -webkit-transform: rotateX(360deg);
       -webkit-transform-origin: 0% 50% 0;
    }
}
@-o-keyframes topSpin {
    0% {
       -o-transform: rotateX(0deg);
       -o-transform-origin: 0% 50% 0;
    }
    100% {
       -o-transform: rotateX(360deg);
       -o-transform-origin: 0% 50% 0;
    }
}
@-ms-keyframes topSpin {
    0% {
       -ms-transform: rotateX(0deg);
       -ms-transform-origin: 0% 50% 0;
    }
    100% {
       -ms-transform: rotateX(360deg);
       -ms-transform-origin: 0% 50% 0;
    }
}
@keyframes topSpin {
    0% {
       transform: rotateX(0deg);
       transform-origin: 0% 50% 0;
    }
    100% {
       transform: rotateX(360deg);
       transform-origin: 0% 50% 0;
    }
}

Вторая проблема, стоящая перед Lightbox CSS3 является отсутствие поддержки в Internet Explorer. К сожалению, версии 8 и ниже не признают псевдо-класс :target.

Один из способов обойти эту проблему, использовать Polyfill такие как Dean Edwards IE7.js или Keith Clarke's Selectivizr (последний имеет поддержку только IE8).

Он имеет полную поддержку CSS3 так же как и Sizzle. Я полагаю также, вы можете использовать JQuery и Dojo.

Тем не менее, моя цель для демо: создать его полностью независимым от любой другой библиотеки JavaScript. 

Если браузер не признает CSS псевдо-классы или псевдо-элементы, тогда необходимо разобрать весь блок кода. Это означает, что  невозможно применить использование CSS стилей объекта, для блока в котором используеться :target.

Мое решение было использовать XMLHttpRequest API для сохранения стилей в памяти, а так же все изменения  :target с классом ieTarget, удалить старые таблицы стилей, а затем добавить новые измененные  к .IeTarget, потом динамически добавлять и удалять его из HTML в зависимости от действий пользователя.

Правда, это довольно радикальный ход и есть возможность оставить много потенциальных ошибок и проблем.

Наконец, если вы собираетесь использовать JavaScript для лайтбокса, то почему бы не использовать новый полноэкранный API. Он был введен в Webkit в 2011 году и сделал свое первое появление в Firefox в начале 2012 года.

API довольно прост в реализации:

full_page: function () {
    var img, x, docElm, l;
    img = document.querySelectorAll(".first-image img");
    for (x = 0, l = img.length; x < l; x += 1) {
       // call full screen when clicking on the thumbnail
       img[x].addEventListener("click", function (evt) {
           docElm = document.documentElement;
           if (docElm.requestFullScreen) {
               docElm.requestFullScreen();
               _private.add_warning();
               _private.request_smallscreen();
           } else if (docElm.mozRequestFullScreen) {
               docElm.mozRequestFullScreen();
               _private.add_warning();
               _private.request_smallscreen();
           } else if (docElm.webkitRequestFullScreen) {
               docElm.webkitRequestFullScreen();
               _private.add_warning();
               _private.request_smallscreen();
           }
       }, false);
    } // end for loop
}

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

lightbox.init({
    // declare whether you want to use the Full-screen API
   fullscreen: false,
    // declare CSS classes that are used for animation
   classes: ['image3D', 'flipper', 'bulge', 'bouncing', 'side-spin', 'top-spin', 'shadow-play', 'rush']
});

ДЕМО

 Исходные файлы

 

Дополнительная информация

Влерий Аликин - веб-разработчик & дизайнер. Соучредитель и член команды Lecaw.

Эл. почта
RATTING:
(0 голосов)

Оставить комментарий