В рамках создания нашей браузерной космической игры, перед нами стояла задача разработать простую и наименее ресурсозатратную анимацию вращения планет в звездной системе.
После непродолжительного подбора различных способов реализации, сразу были исключены варианты:
Итак, остановились мы на использовании Canvas и JavaScript, посчитав этот вариант оптимальным для реализации нашей задачи.
Любым доступным способом находим, рисуем или генерируем карту нашей будущей планеты. Предположим, у нас это будет экзопланета, где есть вода и растительность. Выглядеть карта нашей планеты будет примерно так:
Нам необходимо половину изображения скопировать и добавить с правой стороны, т.к. наша карта будет двигаться по поверхности canvas-блока, и при крайнем положении начинать движение заново. Результат получается таким:
В качестве космического пространства у нас выступит блок div с любым подходящим для этого бэкграундом, а внутри разместим элемент с id=«planet»:
Далее заставляем нашу карту двигаться внутри созданного элемента canvas, который скоро превратится в планету:
В результате произведенных действий, получаем примерно такую картину:
Квадратных планет еще не открыли, поэтому придадим нашему небесному телу более привычный вид, прописав в style нашего элемента canvas border-radius на 50 процентов. Получаем:
Уже лучше, однако по-прежнему нет ощущения, что перед нами сферический объект.
Теперь подготовим в графическом редакторе круг с тенью по краям и бликами. Он должен быть обязательно полупрозрачным, т.к. мы будем накладывать его на нашу планетарную карту. В оригинале он будет выглядеть так:
Сейчас добавляем в нашу анимацию эффект вращения, а также, накладываем подготовленную картинку с тенями поверх карты планеты.
Финальный код нашей анимированной планеты получается таким:
И код самой анимации:
Финальный результат анимации планеты в игре:
Все вопросы и предложения по улучшению этого варианта реализации буду рад увидеть в комментариях.
Спасибо за внимание!
Вычеркиваем
После непродолжительного подбора различных способов реализации, сразу были исключены варианты:
с gif-анимацией(из-за низкого качества изображения);с Flash(по договоренности, Flash-технологии решили в проекте не использовать);с анимацией с помощью JQuery посредством функции $().animate(по причине ее прожорливости).
CANVAS в помощь!
Итак, остановились мы на использовании Canvas и JavaScript, посчитав этот вариант оптимальным для реализации нашей задачи.
Пофантазируем...
Любым доступным способом находим, рисуем или генерируем карту нашей будущей планеты. Предположим, у нас это будет экзопланета, где есть вода и растительность. Выглядеть карта нашей планеты будет примерно так:
Нам необходимо половину изображения скопировать и добавить с правой стороны, т.к. наша карта будет двигаться по поверхности canvas-блока, и при крайнем положении начинать движение заново. Результат получается таким:
Создаем планету
В качестве космического пространства у нас выступит блок div с любым подходящим для этого бэкграундом, а внутри разместим элемент с id=«planet»:
<div style="background-image:url(space.jpg); width:1000px; height: 1000px;">
<canvas id="planet" width="300" height="300" style="position: absolute; left:200px; top: 200px;">
</canvas>
</div>
Далее заставляем нашу карту двигаться внутри созданного элемента canvas, который скоро превратится в планету:
$(function(){
var pl_id = 'planet';
var image = new Image();
image.src = 'images/planets/1/1/map.jpg';
// определяем длину и высоту элемента canvas
var width = $('#'+pl_id).width();
var height = $('#'+pl_id).height();
var canvas = document.getElementById(pl_id);
var id = canvas.getContext("2d");
var newMoveWidth = 0;
var newMoveHeight = 0;
var drawPl = function(){
id.clearRect(0, 0, width, height);
// рисуем карту с новыми координатами внутри элемента
id.drawImage(image, newMoveWidth, newMoveHeight, width, height, 0, 0, width, height);
if (newMoveWidth >= 899.5) newMoveWidth = 0; // если смещение достигло предела, начинаем сначала
else newMoveWidth = newMoveWidth+0.5; // иначе двигаем карту дальше
}
setInterval(drawPl, 50); // запускаем анимацию со скоростью 50 мс.
});
В результате произведенных действий, получаем примерно такую картину:
Закругляем...
Квадратных планет еще не открыли, поэтому придадим нашему небесному телу более привычный вид, прописав в style нашего элемента canvas border-radius на 50 процентов. Получаем:
Уже лучше, однако по-прежнему нет ощущения, что перед нами сферический объект.
Теперь подготовим в графическом редакторе круг с тенью по краям и бликами. Он должен быть обязательно полупрозрачным, т.к. мы будем накладывать его на нашу планетарную карту. В оригинале он будет выглядеть так:
Сейчас добавляем в нашу анимацию эффект вращения, а также, накладываем подготовленную картинку с тенями поверх карты планеты.
Финальный код нашей анимированной планеты получается таким:
<div style="background-image:url(space.jpg); width:1000px; height: 1000px;">
<canvas id="planet" width="300" height="300" style="position: absolute; left:200px; top: 200px; border-radius:50%">
</canvas>
</div>
И код самой анимации:
$(function(){
var pl_id = 'planet';
var image = new Image();
image.src = 'map2.jpg';
// загружаем изображение тени и бликов планеты
var fxShadow = new Image();
fxShadow.src = 'planet_shadow.png';
// определяем длину и высоту элемента canvas
var width = $('#'+pl_id).width();
var height = $('#'+pl_id).height();
// рассчитываем угол вращения планеты
var beta = 360/900;
var beta = (beta*Math.PI)/360;
var l = (Math.sqrt(width*width+width*width))/2;
var gam = Math.PI - ((Math.PI - (beta * Math.PI)/360)/2) - (Math.PI/4);
var b = 2*l*Math.sin(beta/2);
var x = b*Math.sin(gam);
var y = b*Math.cos(gam);
var p1 = Math.cos(beta);
var p2 = Math.sin(beta);
var canvas = document.getElementById(pl_id);
var id = canvas.getContext("2d");
var newMoveWidth = 0;
var newMoveHeight = 0;
var drawPl = function(){
id.clearRect(0, 0, width, height);
// применяем к нашей планете вращение
id.transform(p1, p2, -p2, p1, x, -y);
// рисуем карту с новыми координатами внутри элемента
id.drawImage(image, newMoveWidth, newMoveHeight, width, height, 0, 0, width, height);
//добавляем тень и блики
id.drawImage(fxShadow, 0, 0, width, height);
// если смещение достигло предела, начинаем сначала
if (newMoveWidth >= 899.5) newMoveWidth = 0;
else newMoveWidth = newMoveWidth+0.5; // иначе двигаем карту дальше
}
setInterval(drawPl, 50); // запускаем анимацию со скоростью 50 мс.
});
Финальный результат анимации планеты в игре:
Все вопросы и предложения по улучшению этого варианта реализации буду рад увидеть в комментариях.
Спасибо за внимание!