Прочитав пост о псевдо 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. Работа с камерой возможна, но…
В качестве кода и примера виновно малое время от идеи до реализации. Будет любопытно узнать мнение, подсказки. Если будет интерес, то постараюсь доделать библиотеку.
Автор: igentuman