Создаем iPhone с эффектом параллакса на JS
Конечно, это не идеальная оболочка всеми любимого смартфона, но главное ведь не она, а те эффекты которые она содержит! Внутренний слайдер будет работать при помощи перетаскивания мыши.
Шаг 1. HTML
Начнем мы с разметки, здесь у нас будет несколько слоев, которые позиционируются относительно друг друга, при этом главное соблюдать порядок. Мы устанавливаем окантовку телефона, фон с эффектом параллакса, иконки в рабочем состоянии и верхний и нижний статус бар.
Вроде ничего сложного, и это правда, разметка не приносит особых трудностей, все достаточно интереснее в следующем шаге.
Шаг 2. CSS
Для начала мы начнем собирать каркас, и указать его позиционирование на странице, мы установим размеры для каркаса:
Далее нам необходимо установить параметры изменения в пространстве для каждой грани:
Далее мы подключаем изображение, и устанавливаем его позиционирование в середине выше указанных граней:
Затем проделываем такие же манипуляции как и для рамки, нам необходимо установить угол наклона:
Последними шагами будет добавление нижнего дока и верхнего статус-бара, мы указываем позиционирование их, относительно рамки:
Первый стиль устанавливает параметры для верхнего статус-бара, а втором, как Вы уже догадались, для полки. И так, мы разобрались с фоном, теперь нам необходимо оформить иконки, так как большую часть у нас будет выполнять JS в работе меню, то стили не особо большие:
Здесь мы устанавливаем размеры навигации, и позиционирование по центру относительно каркаса. Далее нам необходимо установить размеры для иконок и оформить их сетку:
Далее установим индикаторы активного рабочего стола:
Некоторые стили были опущены, так как используются только для оформления демонстрации. Полный код можно просмотреть в исходниках. Перейдем к следующему шагу.
Шаг 3. JS
Практически всю часть работы у нас положена на JS, так мы будем использовать функции для вывода иконок, а также реализовываем возможность их манипуляций, при этом они разбиты на несколько рабочих столов:
Мы используем coffeescript для получения таких возможностей, кроме этого подключены такие скрипты как:
Modernizr — это JavaScript-библиотека, которая узнаёт, что из HTML5 и CSS3 умеет браузер пользователя. Определяя возможности браузера, разработчик может сделать откат некоторых функций для старых версий браузеров.
PrefixFree — плагин разработан так, чтобы не использовать префиксов совсем, даже для свойств @keyframesили transition, которые нигде не поддерживаются без префиксов.
Touchable — скрипт позволяет быть отзывчивым для сенсорных дисплеев, что весьма расширяет возможности использования сайта.
Шаг 1. HTML
Начнем мы с разметки, здесь у нас будет несколько слоев, которые позиционируются относительно друг друга, при этом главное соблюдать порядок. Мы устанавливаем окантовку телефона, фон с эффектом параллакса, иконки в рабочем состоянии и верхний и нижний статус бар.
Код
<div id="page">
<div class="display"><img alt="" src="121.png" />
<div class="icons">
<div class="icon0 center top"></div>
<div id="mask"></div>
<ul id="indicators"></ul>
<div id="dock"></div>
<div class="icon21 center top"></div>
<div class="display"><img alt="" src="121.png" />
<div class="icons">
<div class="icon0 center top"></div>
<div id="mask"></div>
<ul id="indicators"></ul>
<div id="dock"></div>
<div class="icon21 center top"></div>
Вроде ничего сложного, и это правда, разметка не приносит особых трудностей, все достаточно интереснее в следующем шаге.
Шаг 2. CSS
Для начала мы начнем собирать каркас, и указать его позиционирование на странице, мы установим размеры для каркаса:
Код
.display{
width: 320px;
height: 460px;
margin: 20px auto;
overflow: hidden;
position: relative;
border-left: 14px solid #000;
border-right: 14px solid #000;
border-top: 98px solid #000;
border-bottom: 98px solid #000;
border-radius: 25px;
transition: all .5s;
backface-visibility: hidden;
}
width: 320px;
height: 460px;
margin: 20px auto;
overflow: hidden;
position: relative;
border-left: 14px solid #000;
border-right: 14px solid #000;
border-top: 98px solid #000;
border-bottom: 98px solid #000;
border-radius: 25px;
transition: all .5s;
backface-visibility: hidden;
}
Далее нам необходимо установить параметры изменения в пространстве для каждой грани:
Код
.right .display{
transform: rotateY(-12deg);
}
.left .display{
transform: rotateY(12deg);
}
.topper .display{
transform: rotateX(12deg);
}
.topper.right .display{
transform: rotateX(12deg) rotateY(-12deg);
}
.topper.left .display{
transform: rotateX(12deg) rotateY(12deg);
}
.bottomer .display{
transform: rotateX(-12deg);
}
.bottomer.right .display{
transform: rotateX(-12deg) rotateY(-12deg);
}
.bottomer.left .display{
transform: rotateX(-12deg) rotateY(12deg);
}
transform: rotateY(-12deg);
}
.left .display{
transform: rotateY(12deg);
}
.topper .display{
transform: rotateX(12deg);
}
.topper.right .display{
transform: rotateX(12deg) rotateY(-12deg);
}
.topper.left .display{
transform: rotateX(12deg) rotateY(12deg);
}
.bottomer .display{
transform: rotateX(-12deg);
}
.bottomer.right .display{
transform: rotateX(-12deg) rotateY(-12deg);
}
.bottomer.left .display{
transform: rotateX(-12deg) rotateY(12deg);
}
Далее мы подключаем изображение, и устанавливаем его позиционирование в середине выше указанных граней:
Код
.display img{
img: url(1.png);
width: 350px;
height: auto;
position: absolute;
top: -15px;
left: -15px;
z-index: 0;
transition: all .5s;
backface-visibility: hidden;
}
img: url(1.png);
width: 350px;
height: auto;
position: absolute;
top: -15px;
left: -15px;
z-index: 0;
transition: all .5s;
backface-visibility: hidden;
}
Затем проделываем такие же манипуляции как и для рамки, нам необходимо установить угол наклона:
Код
.right .display img{
transform: translate3d(15px, 0, 0);
}
.left .display img{
transform: translate3d(-15px, 0, 0);
}
.topper .display img{
transform: translate3d(0, 15px, 0);
}
.topper.right .display img{
transform: translate3d(15px, 15px, 0);
}
.topper.left .display img{
transform: translate3d(-15px, 15px, 0);
}
.bottomer .display img{
transform: translate3d(0, -15px, 0);
}
.bottomer.right .display img{
transform: translate3d(15px, -15px, 0);
}
.bottomer.left .display img{
transform: translate3d(-15px, -15px, 0);
}
transform: translate3d(15px, 0, 0);
}
.left .display img{
transform: translate3d(-15px, 0, 0);
}
.topper .display img{
transform: translate3d(0, 15px, 0);
}
.topper.right .display img{
transform: translate3d(15px, 15px, 0);
}
.topper.left .display img{
transform: translate3d(-15px, 15px, 0);
}
.bottomer .display img{
transform: translate3d(0, -15px, 0);
}
.bottomer.right .display img{
transform: translate3d(15px, -15px, 0);
}
.bottomer.left .display img{
transform: translate3d(-15px, -15px, 0);
}
Последними шагами будет добавление нижнего дока и верхнего статус-бара, мы указываем позиционирование их, относительно рамки:
Код
.icon0{
position: relative;
margin: 0px -25px;
width: 359px;
height: 30px;
float: center;
background: url(122.png);
border-radius: 13px;
z-index: 2;
}
.icon21{
position: relative;
margin: -100px -30px;
width: 418px;
height: 658px;
float: left;
background: url(12.png);
border-radius: 10px;
}
position: relative;
margin: 0px -25px;
width: 359px;
height: 30px;
float: center;
background: url(122.png);
border-radius: 13px;
z-index: 2;
}
.icon21{
position: relative;
margin: -100px -30px;
width: 418px;
height: 658px;
float: left;
background: url(12.png);
border-radius: 10px;
}
Первый стиль устанавливает параметры для верхнего статус-бара, а втором, как Вы уже догадались, для полки. И так, мы разобрались с фоном, теперь нам необходимо оформить иконки, так как большую часть у нас будет выполнять JS в работе меню, то стили не особо большие:
Код
#homeScreen{
width: 320px;
height: 460px;
padding: 0px;
margin: 0 auto 20px;
background:url('../img/background.png') no-repeat left bottom;
}
#mask{
width: 320px;
height: 460px;
position: relative;
overflow: hidden;
margin: -20px auto -180px;
}
width: 320px;
height: 460px;
padding: 0px;
margin: 0 auto 20px;
background:url('../img/background.png') no-repeat left bottom;
}
#mask{
width: 320px;
height: 460px;
position: relative;
overflow: hidden;
margin: -20px auto -180px;
}
Здесь мы устанавливаем размеры навигации, и позиционирование по центру относительно каркаса. Далее нам необходимо установить размеры для иконок и оформить их сетку:
Код
.screen .icon{
float:left;
width:60px;
height:60px;
background-repeat: no-repeat;
margin: 25px;
position: relative;
}
.screen .icon:after{
bottom: -25px;
color: white;
content: attr(title);
font-size: 12px;
height: 20px;
left: -20px;
overflow: hidden;
position: absolute;
text-align: center;
white-space: nowrap;
width: 100px;
text-shadow: 0 0 3px #222;
}
float:left;
width:60px;
height:60px;
background-repeat: no-repeat;
margin: 25px;
position: relative;
}
.screen .icon:after{
bottom: -25px;
color: white;
content: attr(title);
font-size: 12px;
height: 20px;
left: -20px;
overflow: hidden;
position: absolute;
text-align: center;
white-space: nowrap;
width: 100px;
text-shadow: 0 0 3px #222;
}
Далее установим индикаторы активного рабочего стола:
Код
#indicators{
text-align:center;
list-style: none;
}
#indicators li{
border-radius:70%;
display: inline-block;
margin:3px;
width:6px;
height:6px;
margin-top: 65px;
background-color:white;
opacity:0.6;
}
#indicators li.active{
opacity:0.8;
background-color:#black;
}
text-align:center;
list-style: none;
}
#indicators li{
border-radius:70%;
display: inline-block;
margin:3px;
width:6px;
height:6px;
margin-top: 65px;
background-color:white;
opacity:0.6;
}
#indicators li.active{
opacity:0.8;
background-color:#black;
}
Некоторые стили были опущены, так как используются только для оформления демонстрации. Полный код можно просмотреть в исходниках. Перейдем к следующему шагу.
Шаг 3. JS
Практически всю часть работы у нас положена на JS, так мы будем использовать функции для вывода иконок, а также реализовываем возможность их манипуляций, при этом они разбиты на несколько рабочих столов:
Код
class Icon
constructor: (@id, @title) ->
@markup = "</pre>
<div class="icon" style="background-image: url('assets/img/icons/#{@id}.png');" title="#{@title}"></div>
<pre>
"
class DockIcon extends Icon
constructor: (id, title)->
super(id, title)
@markup = @markup.replace("class='icon'","class='dockicon'")
class Screen
constructor: (icons = [])->
@icons = icons
attachIcons: (icons = [])->
Array.prototype.push.apply(@icons, icons)
generate: ->
markup = []
markup.push(icon.markup) for icon in @icons
"</pre>
<div class="screen">#{markup.join('')}</div>
<pre>
"
class Stage
screenWidth: 332
constructor: (icons)->
@currentScreen = 0
@screens = []
num = Math.ceil(icons.length / 9)
i = 0
while num--
# we pass a slice of the icons array
s = new Screen(icons[i...i+9])
# adding the screen to the local screens array
@screens.push(s)
i+=9
addScreensTo: (element)->
@element = $(element)
@element.width(@screens.length*@screenWidth)
for screen in @screens
@element.append(screen.generate())
addIndicatorsTo: (elem)->
# This method creates the small
# circular indicatiors
@ul = $(elem)
for screen in @screens
@ul.append('</pre>
<ul>
<li>')
@ul.find('li:first').addClass('active');
goTo: (screenNum)->
if @element.is(':animated')
return false
if @currentScreen == screenNum
# Parallel assignment:
[from, to] = ['+=15','-=15']
if @currentScreen != 0
[from, to] = [to, from]
@element.animate( { marginLeft : from }, 150 )
.animate( { marginLeft : to }, 150 )
else
@element.animate( { marginLeft:-screenNum*@screenWidth }, => @currentScreen = screenNum )
@ul.find('li').removeClass('active').eq(screenNum).addClass('active');
next: ->
toShow = @currentScreen+1
# If there is no next screen, show
# the current one
if toShow == @screens.length
toShow = @screens.length - 1
@goTo(toShow)
previous: ->
toShow = @currentScreen-1
# If there is no previous screen,
# show the current one
if toShow == -1
toShow = 0
@goTo(toShow)
# This is equivalent to $('document').ready(function(){}):
$ ->
allIcons = [
new Icon('Photos', 'Фото'), new Icon('Maps', 'Карты Google')
new Icon('Chuzzle', 'Пасьянс'), new Icon('Safari', 'Safari')
new Icon('Weather', 'Погода'), new Icon('nes', 'Эмулятор')
new Icon('Calendar', 'Календарь'), new Icon('Clock', 'Часы')
new Icon('BossPrefs', 'Настройки'), new Icon('Chess', 'Шахматы')
new Icon('Mail', 'Почта'), new Icon('Phone', 'Вызовы')
new Icon('SMS', 'Сообщения'), new Icon('Camera', 'Камера')
new Icon('iPod', 'Видео'), new Icon('Calculator', 'Калькулятор')
new Icon('Music', 'Музыка'), new Icon('Poof', 'Игры')
new Icon('Settings', 'Фонарик'), new Icon('YouTube', 'Youtube')
new Icon('psx4all', 'Приставка'), new Icon('VideoRecorder', 'Запись')
new Icon('Installer', 'Установка'), new Icon('Notes', 'Заметки')
new Icon('RagingThunder', 'Гонки'), new Icon('Stocks', 'Магазин')
new Icon('genesis4iphone', 'Генератор'), new Icon('snes4iphone', 'SNES Эмулятор')
new Icon('Calendar', 'Календарь'), new Icon('Clock', 'Часы')
new Icon('Photos', 'Фото'), new Icon('Maps', 'Карты Google')
]
dockIcons = [
new DockIcon('Camera', 'Камера')
new DockIcon('iPod', 'Видео')
new DockIcon('Calculator', 'Калькулятор')
]
allScreens = $('#allScreens')
allScreens.Touchable();
stage = new Stage(allIcons)
stage.addScreensTo(allScreens)
stage.addIndicatorsTo('#indicators')
allScreens.bind 'touchablemove', (e,touch)->
stage.next() if touch.currentDelta.x < -5 stage.previous() if touch.currentDelta.x > 5
dock = $('#dock')
for icon in dockIcons
dock.append(icon.markup)
constructor: (@id, @title) ->
@markup = "</pre>
<div class="icon" style="background-image: url('assets/img/icons/#{@id}.png');" title="#{@title}"></div>
<pre>
"
class DockIcon extends Icon
constructor: (id, title)->
super(id, title)
@markup = @markup.replace("class='icon'","class='dockicon'")
class Screen
constructor: (icons = [])->
@icons = icons
attachIcons: (icons = [])->
Array.prototype.push.apply(@icons, icons)
generate: ->
markup = []
markup.push(icon.markup) for icon in @icons
"</pre>
<div class="screen">#{markup.join('')}</div>
<pre>
"
class Stage
screenWidth: 332
constructor: (icons)->
@currentScreen = 0
@screens = []
num = Math.ceil(icons.length / 9)
i = 0
while num--
# we pass a slice of the icons array
s = new Screen(icons[i...i+9])
# adding the screen to the local screens array
@screens.push(s)
i+=9
addScreensTo: (element)->
@element = $(element)
@element.width(@screens.length*@screenWidth)
for screen in @screens
@element.append(screen.generate())
addIndicatorsTo: (elem)->
# This method creates the small
# circular indicatiors
@ul = $(elem)
for screen in @screens
@ul.append('</pre>
<ul>
<li>')
@ul.find('li:first').addClass('active');
goTo: (screenNum)->
if @element.is(':animated')
return false
if @currentScreen == screenNum
# Parallel assignment:
[from, to] = ['+=15','-=15']
if @currentScreen != 0
[from, to] = [to, from]
@element.animate( { marginLeft : from }, 150 )
.animate( { marginLeft : to }, 150 )
else
@element.animate( { marginLeft:-screenNum*@screenWidth }, => @currentScreen = screenNum )
@ul.find('li').removeClass('active').eq(screenNum).addClass('active');
next: ->
toShow = @currentScreen+1
# If there is no next screen, show
# the current one
if toShow == @screens.length
toShow = @screens.length - 1
@goTo(toShow)
previous: ->
toShow = @currentScreen-1
# If there is no previous screen,
# show the current one
if toShow == -1
toShow = 0
@goTo(toShow)
# This is equivalent to $('document').ready(function(){}):
$ ->
allIcons = [
new Icon('Photos', 'Фото'), new Icon('Maps', 'Карты Google')
new Icon('Chuzzle', 'Пасьянс'), new Icon('Safari', 'Safari')
new Icon('Weather', 'Погода'), new Icon('nes', 'Эмулятор')
new Icon('Calendar', 'Календарь'), new Icon('Clock', 'Часы')
new Icon('BossPrefs', 'Настройки'), new Icon('Chess', 'Шахматы')
new Icon('Mail', 'Почта'), new Icon('Phone', 'Вызовы')
new Icon('SMS', 'Сообщения'), new Icon('Camera', 'Камера')
new Icon('iPod', 'Видео'), new Icon('Calculator', 'Калькулятор')
new Icon('Music', 'Музыка'), new Icon('Poof', 'Игры')
new Icon('Settings', 'Фонарик'), new Icon('YouTube', 'Youtube')
new Icon('psx4all', 'Приставка'), new Icon('VideoRecorder', 'Запись')
new Icon('Installer', 'Установка'), new Icon('Notes', 'Заметки')
new Icon('RagingThunder', 'Гонки'), new Icon('Stocks', 'Магазин')
new Icon('genesis4iphone', 'Генератор'), new Icon('snes4iphone', 'SNES Эмулятор')
new Icon('Calendar', 'Календарь'), new Icon('Clock', 'Часы')
new Icon('Photos', 'Фото'), new Icon('Maps', 'Карты Google')
]
dockIcons = [
new DockIcon('Camera', 'Камера')
new DockIcon('iPod', 'Видео')
new DockIcon('Calculator', 'Калькулятор')
]
allScreens = $('#allScreens')
allScreens.Touchable();
stage = new Stage(allIcons)
stage.addScreensTo(allScreens)
stage.addIndicatorsTo('#indicators')
allScreens.bind 'touchablemove', (e,touch)->
stage.next() if touch.currentDelta.x < -5 stage.previous() if touch.currentDelta.x > 5
dock = $('#dock')
for icon in dockIcons
dock.append(icon.markup)
Мы используем coffeescript для получения таких возможностей, кроме этого подключены такие скрипты как:
Modernizr — это JavaScript-библиотека, которая узнаёт, что из HTML5 и CSS3 умеет браузер пользователя. Определяя возможности браузера, разработчик может сделать откат некоторых функций для старых версий браузеров.
PrefixFree — плагин разработан так, чтобы не использовать префиксов совсем, даже для свойств @keyframesили transition, которые нигде не поддерживаются без префиксов.
Touchable — скрипт позволяет быть отзывчивым для сенсорных дисплеев, что весьма расширяет возможности использования сайта.
-
FalleN -
950 -
1 -
194
Но только нужно ставить наверное на те модули которые обновляться должны не раньше через пару тройку минут
С Уважением, Андрей...