Предисловие
Несколько недель назад в просторах интернета я увидел очень заинтересовавшую меня вещь — iOS иконки на CSS3 полностью без картинок. Первое что подумал — «Я тоже так могу»! А спустя еще 5 минут для себя четко решил — «challenge accepted». Но чтоб не повторяться я решил немножко усложнить задачу — сделать не только иконки, но и сам девайс.
Постановка задачи
Итак, в тот-же день я решил сделать iPhone4 на CSS3 абсолютно без картинок, base64, canvas или SVG и добавить еще некоторую изюминку — интерактивные возможности:
— включение/выключение;
— блокировка при включении и разблокировка как в реальном iPhone;
— анимация «slide to unlock» текста на экране блокировки;
Используемые технологии
CSS3
Интересные и необходимые технологии CSS3, которые и обрисовали всю картину без графики:
— border-radius для скругления уголков практически всех составляющих элементов устройства.
— box-shadow для создания как внешних так и внутренних теней элементов.
— background: linear-gradient и background: radial-gradient — создание большинства цветных заливок иконок и бликов.
— background-size — для создания полосатого фона у иконок Message и Phone;
— transform: rotate, skew, scale — трансформирование некоторых составляющих иконок, для создания максимально схожих к идеалу картинок;
— before и after псевдоэлементы — для минимизации HTML кода;
— :nth-child(n) — для выборки n-го элемента в динамике и некоторых иконках типа App Store и iTunes, содержащих одинаковые внутренние элементы c небольшим отличием примерно в 1-м или двух свойствах.
jQuery + jQuery UI
Из этой технологии не использовалось практически ничего уникального. Набор animate() функции для анимации «slide to unlock», вылета иконок и убирания панелей блокировки при разблорировке, draggable эффекта для слайдера при разблокировке.
Стиль написания самого скрипта унаследован у Html5BoilerPlate.
HTML
В HTML я не стал использовать кастомные теги, хоть это и позволено, а просто использовал в основном div, hr, b, и списки.
Куски кода
HTML cтруктура iPhone
<div class="iphone">
<div class="iphone_light_gradient"></div> <!-- блик на iPhone -->
<div class="iphone_power_button" id="iphone_power_button"></div> <!-- кнопка вкл./выкл. -->
<div class="iphone_voice_toogle"></div> <!-- переключатель на беззвучный режим -->
<div class="iphone_voice_plus"></div> <!-- кнопка "+" -->
<div class="iphone_voice_minus"></div> <!-- кнопка "-" -->
<div class="iphone_camera"></div> <!-- фронтальная камера -->
<div class="iphone_dynamic"><span></span><!-- куча span для точек на динамике --><span></span></div> <!-- динамик -->
<div class="iphone_black_bg"></div> <!-- черная подложка передней части устройства -->
<div class="iphone_display" > <!-- сам дисплей со всеми внутренностями -->
<div class="iphone_headline" id="iphone_headline"> <!-- верхная черная полоса экрана -->
<div class="iphone_net"></div> <!-- Индикатор сети -->
<div class="iphone_net_title">tjrus</div> <!-- Имя сети -->
<div class="iphone_wi-fi"><div class="hack"></div></div> <!-- Индикатор wi-fi -->
<div class="iphone_clock" id="iphone_headline_clock">00:00</div> <!-- часы -->
<div class="iphone_lock"></div> <!-- замок -->
<div class="iphone_battery"></div> <!-- индикатор батареи -->
</div>
<div class="iphone_header" id="iphone_lock_header"> <!-- верхняя панель заблокированного экрана -->
<div class="iphone_time" id="iphone_lock_time">0<span>:</span>00</div> <!-- часы -->
<div class="iphone_date" id="iphone_lock_date"></div> <!-- дата -->
</div>
<div class="iphone_footer" id="iphone_lock_footer"> <!-- нижняя часть заблокированного экрана -->
<div class="iphone_unlock" id="iphone_unlock"> <!-- область "slide to unlock" -->
<div class="iphone_slider" id="iphone_slider"></div> <!-- слайдер (ползунок) -->
<div class="iphone_slide2unlock" id="iphone_slide2unlock">slide to unlock</div>
</div>
</div>
<div class="iphone_icons_containter" id="iphone_icons_containter"> <!-- контейнер иконок -->
<div class="icon"></div> <!-- пример контейнера иконки ( их таких 16-ть подряд) -->
</div>
<div class="iphone_dock" id="iphone_dock"> <!-- док -->
<div class="icon"></div> <!-- пример контейнера иконки ( их в доке 4 штучки ) -->
</div>
</div>
<div class="iphone_home" id="iphone_home_button"></div> <!-- кнопка "домой" ("home button") -->
</div>
CSS3 интересные части
(Полный CSS код приводить было бы не уместно, так как там всего-то 3395 строчки кода)
Иконки
Все иконки заключаются в контейнеры с классом «icon», дабы их можно было безболезненно переставлять местами в коде по надобности и чтоб задать сразу им обрамительный единый стиль с тенью и названием.
.icon {
width: 56px;
height: 56px;
border-radius: 10px;
box-shadow: rgba(0,0,0,0.5) 0 1px 2px;
margin-bottom: 30px;
position: absolute;
}
.icon span { /* содержит название иконки */
display: block;
text-align: center;
font: bold 11px/15px "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
color: #fff;
text-shadow: rgba(0,0,0,0.3) 1px 2px 1px;
text-transform: capitalize;
position: absolute;
top: 58px;
left: -10px;
width: 76px;
}
так как иконки у нас располагаются по матрице, то их удобно позиционировать таким вот простым способом:
.icon:nth-child(4n + 1) { left:17px; }
.icon:nth-child(4n + 2) { left:92px; }
.icon:nth-child(4n + 3) { left:168px; }
.icon:nth-child(4n + 4) { left:243px; }
.icon:nth-child(-n + 16) { top: 258px; }
.icon:nth-child(-n + 12) { top: 172px; }
.icon:nth-child(-n + 8) { top: 86px; }
.icon:nth-child(-n + 4) { top: 0; }
для дока немного другой случай позиционирования:
.iphone_dock .icon:nth-child(1) { margin-left:7px; margin-right: 19px; }
.iphone_dock .icon:nth-child(2) { margin-right: 20px; }
.iphone_dock .icon:nth-child(3) { margin-right: 19px; }
Тем кому интересен полный код иконок — его лучше смотреть в исходном коде на самой странице, ибо код очень велик.
jQuery интересные части
Как я уже и говорил — взял стиль написания скрипта у html5BoilerPlate. Все настройки, возможности и состояния iPhone описаны в одном объекте. Структура объекта iphone:
iphone = {
slide_started : false, // начался ли слайд разблокировки
letter_animate_time : 50, // время анимации буквы
panels_animate_time : 400, // время анимации исчезновения панелей при разблокировке
status : 'lock', // текущий статус устройства. Возможные статусы: "lock", "unlock", "off"
iconsDefaultPosition : {}, // содержит значения позиции иконок при разблокированном iPhone
iconsOutPosition : {}, // содержит значения позиции иконок при заблокированном iPhone
init : function(){}, // инициализация онкликов, слайдов, перечсета позиции иконок, начала анимации текста
endSlide : function(){}, // функция обработки окончания слайда при разблокировке
turnOn : function(){}, // включение iPhone
turnOff : function(){}, // выключение iPhone
lock : function(){}, // блокирование iPhone
unlock : function(){}, // разблокировка iPhone
showIcons : function(){}, // анимация показа оконок при разблокировке
hideIcons : function(){}, // уход иконок за экран без анимации
animateHideIcons : function(){}, // анимацая ухода иконок за экран
prepareIcons : function(){}, // функция собирает дефолтные значения положения иконок, и устанавливает их за экран в заблокированный режим
timeUpdate : function(){}, // обновление время устройства на заблокированном экране, в верхней линии и иконке
stopTextAnimate : function(){}, // остановка текстовой анимации
startTextAnimate : function(){}, // старт текстовой анимации
prepareTextAnimate : function () {}, // подготовка текста "slide to unlock" к анимации
animateLetters : function() {}, // запуск цикла анимации букв в "slide to unlock"
ua : function() {}, // функция определения типа браузера (user agent)
}
Обработка процесса «Slide to unlock»
$("#iphone_slider").draggable({
containment: 'parent',
axis: 'x',
start: function(event, ui) {
$(document).mousemove(function(){
if(iphone.slide_started){
var left = $("#iphone_slider").css('left').substring(0, $("#iphone_slider").css('left').length - 2);
var width = $('#iphone_unlock').width() - $('#iphone_slider').width();
var opacity_k = (width - left*3) / (width);
$('#iphone_slide2unlock').css({'opacity': opacity_k}, TIME/2); // делаем текст прозрачнее по мере процесса слайда ползунка
}
});
},
stop: function(event, ui){
$(document).unbind('mousemove');
}
});
$("#iphone_slider").mousedown(function(){
iphone.slide_started = true;
});
$(document).mouseup(function(){
if (iphone.slide_started){
iphone.endSlide(); // в этой функции определяем достаточно ли дотянули мы слайдер для того чтоб разблокировать, или же возвращаем слайдер в исходную позицию.
iphone.slide_started = false;
}
});
Что получилось
В результате страница отлично демонстрирует многие, но далеко не все возмoжности CSS3. К большому моему сожалению на веб-сайтах весь такой код использовать нельзя из-за сложного CSS3 (анимация вылета иконок сильно тормозит в браузерах).
Кроссбраузерность
Увы этот пункт наверное самый печальный. iPhone4 на CSS3 отлично работает в WebKit браузерах Safari и Chrome под Mac OS X (в Windows возможно неправильное отображение иконки Phone), так же правильно отображается в последних Firefox и Opera. Для iOS устройств пришлоcь выключить анимацию «slide to unlock», которая очень сильно замедляла страницу в браузере устройства. Что касается Internet Explorer — приношу ему свои извинения.
Демо
сама страница — iPhone4 на CSS3
стили — iphone.css
скрипт — iphone.js