Создаем iPhone с эффектом параллакса на JS

Конечно, это не идеальная оболочка всеми любимого смартфона, но главное ведь не она, а те эффекты которые она содержит! Внутренний слайдер будет работать при помощи перетаскивания мыши.

Шаг 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>

Вроде ничего сложного, и это правда, разметка не приносит особых трудностей, все достаточно интереснее в следующем шаге.

Шаг 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;
}

Далее нам необходимо установить параметры изменения в пространстве для каждой грани:

Код
.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);
}

Далее мы подключаем изображение, и устанавливаем его позиционирование в середине выше указанных граней:

Код
.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;
}

Затем проделываем такие же манипуляции как и для рамки, нам необходимо установить угол наклона:

Код
.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);
}

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

Код
.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;
}

Первый стиль устанавливает параметры для верхнего статус-бара, а втором, как Вы уже догадались, для полки. И так, мы разобрались с фоном, теперь нам необходимо оформить иконки, так как большую часть у нас будет выполнять 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;
  }

Здесь мы устанавливаем размеры навигации, и позиционирование по центру относительно каркаса. Далее нам необходимо установить размеры для иконок и оформить их сетку:

Код
.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;
}

Далее установим индикаторы активного рабочего стола:

Код
#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;
}

Некоторые стили были опущены, так как используются только для оформления демонстрации. Полный код можно просмотреть в исходниках. Перейдем к следующему шагу.

Шаг 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)

Мы используем coffeescript для получения таких возможностей, кроме этого подключены такие скрипты как:

Modernizr — это JavaScript-библиотека, которая узнаёт, что из HTML5 и CSS3 умеет браузер пользователя. Определяя возможности браузера, разработчик может сделать откат некоторых функций для старых версий браузеров.

PrefixFree — плагин разработан так, чтобы не использовать префиксов совсем, даже для свойств @keyframesили transition, которые нигде не поддерживаются без префиксов.

Touchable — скрипт позволяет быть отзывчивым для сенсорных дисплеев, что весьма расширяет возможности использования сайта.

  • FalleN

  • 921

  • 1

  • 179
Теги:

Ссылки на статью:

Похожие статьи: