Псевдо 3D или параллакс средствами javascript

Прочитав пост о псевдо 3D эффекте, стало интересно реализовать некий аналог для использования в веб приложениях. За результатом прошу под кат

Основы


Посмотрев видео и покрутив пару приложений из апп стора, пришел к выводу: спрайты (слои) находятся как бы в кубе. Поэтому когда мы поворачиваем девайс, ближние слои движутся в одну сторону а самые дальние слои в другую. Где-то в середине находится главный слой, к которому приковано наше внимание.

Разобравшись с теорией приступаем к разработке.

Размещаем слои


Далеко не будем ходить и используем DIV'ы, и CSS свойство z-index нам тоже пригодится.
<div id="background_scene" class="flow" style="background-image:url(res/images/moun.jpg);z-index:2;top:-20px;left:-150px;width:200%;height:200%"></div>
<div id="clouds" class="flow" style="background-image:url(res/images/clouds.png);opacity: 0.5;z-index:3;top:120px;left:400px;"></div>
<div id="dragon" class="flow" style="background-image:url(res/images/dragon.png);z-index:5;top:120px;left:500px;"></div>

Выше я привел 3 спрайта с классом .flow, начальными координатами и картинками. Теперь пора заставить их двигаться.

Вращение девайса


Все наши потребности в получении положения в пространстве удовлетворит событие: window.ondevicemotion.
window.ondevicemotion = function(event) {  
     X = event.accelerationIncludingGravity.x;  
     Y = event.accelerationIncludingGravity.y;  
     Z = event.accelerationIncludingGravity.z;
}

Не буду расписывать событие, любопытных отправляю в список литературы.
Нам же из этого события необходимо 2 значения: Х и У.
Высчитываем дельту смещения:
    deltaX = lastX - X;
    deltaY = lastY - Y;
    lastY = Y;
    lastX = X;

Находим все спрайты по имени класса .flow
Т.к. спрайты с малым z-index'ом 'самые «удаленные» и должны двигаться в обратном направлении, движения для каждой группы высчитываем отдельно:
elements = $('div.flow');
 elements.each(function (key, layer) {
        zIndex = layer.style.zIndex;
        sprite = $('#' + layer.id);
                if (zIndex > 9) { //Я решил что дальние спрайты это спрайты с z-index < 10
                    anim = {"left":"-=" + deltaX * zIndex * 2, "top":"+=" + deltaY * zIndex * 0.5}; //0.5  это случайный коэффициент пришедший в голову, использую эти коэффициенты для отладки скоростей движения слоев
                } else {
                    anim = {"left":"+=" + deltaX * zIndex * 2, "top":"-=" + deltaY * zIndex * 2};
                }
sprite.animate(anim, 100); //Используем анимацию из jQuery
}

Помимо своей обычной задачи z-index выполняет еще роль коэффициента для ускорения движения спрайтов.
Ну вот в принципе и все.

Улучшения


1. Для уменьшения числа срабатывания метода движения слоев, была добавлена активация по таймеру. Это дало прироста, но увеличение интервала влечет за собой дерганность анимации.
2. Для уменьшения тряски дельта высчитывается иначе: дельта = Х — Хсредн; Хсредн — высчитывается в моментах интервала таймера. Даже если в последний момент вы тряхнете рукой, все будет гладко.
3. Добавлена поддержка ориентаций экрана

Проблемы


1. Тряска все еще заметна, не знаю, надо калибровать или совершенно другой алгоритм писать надо
2. Не могу толком настроить скорости спрайтов

Можно было бы сделать


1. Простенький дизайнер Drag&Drop спрайтов, с регулированием уровня
2. Работа не только с акселерометром, но и с мышкой, скролл баром (в зависимости от доступности или настроек)
3. Работа с камерой возможна, но…

Рекомендую ознакомиться

демка (если на устройстве не поддерживается devicemotion, то включится рандомный генератор наклонов)

В качестве кода и примера виновно малое время от идеи до реализации. Будет любопытно узнать мнение, подсказки. Если будет интерес, то постараюсь доделать библиотеку.

UPD: Не было и нет возможности протестировать на Andriod девайсах. И, к сожалению, код на них не работает. Попробую поискать решение.
Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 10

    +8
    Chrome Версия 25.0.1354.0 dev-m
    Ничего не происходит в демке.
    Или это только для айфона?
      +10
      Нужно монитор наклонять!
        +1
        Не ну я попробовал еще в Хроме и Опера Мини на Андроиде 4.1.1 (Samsung Galaxy Star III) — тоже не работает…
        0
        К сожалению, пока только для iOS
          0
          Посмотрите в сторону PhoneGap. Думаю поможет сделать вашу демку немного более кроссбраузерной и кроссплатформенной:)
        0
        Safari, iPad 1, iOS 5.0.1 — тормозит страшно, эффект не впечатляет.
          +2
          На iPad 2, iOS 6 — тоже тормозит, но юзабельно. Для демки накачал спрайтов каких нашел. Надо оптимизировать.
          0
          WinPhone 7.5 — Не работает тоже.
            0
            даже на пятом айфоне все тормозит, дергается и медленно скачет вверх…
              0
              Найду время, скачаю адекватные и легковесные спрайты, оптимизмрую анимации. пока это только пробный вариант.

            Only users with full accounts can post comments. Log in, please.