Расставляем элементы по кругу с помощью jQuery и геометрии
Все началось с одной маленькой идеи. Впрочем как всегда.
Что получилось:
Как это сделать?
Для начала, хочу сразу предупредить, что для реализации подобных вещей не помешают базовые знания тригонометрии.
Концептуально, показанный на скриншоте выше зодиакальный круг — это просто сетка ссылок в контейнере.
Что–то вроде:
<div class="signs">
<a href="#" class="signs__item">Лев</a>
<a href="#" class="signs__item">Овен</a>
<!-- ... -->
</div>
Если отключить в браузере JavaScript, то вместо круга мы увидим самую обычную сетку (прим. я не привожу здесь css для сетки, поскольку в проекте использовал kube.css).
Для того, чтобы оживить эту сетку, и превратить в кольцо, нужно сообщить каждой ссылке определенные координаты относительно блока-монитора.
Итак, у нас есть 12 элементов, которые мы должны равномерно распределить на окружности (360 o), т.е. получается 12 секторов с углами в 30o.
Обратимся к базовой тригонометрии и вспомним, что y — это синус угла, а x это его косинус.
Математические функции в Javascript работают с радианами, поэтому перед вычислениями нужно перевести градусы в радианы по формуле:
RAD = DEG * (PI / 180)
RAD - угол в радианах,
DEG - угол в градусах
Отобразим эту формулу в виде простейшей функции–конвертёра:
function toRad(deg) {
return deg * (Math.PI / 180);
}
Теперь нам нужно определить центр координат, а также смещение контейнера, в котором будет строиться наш круг:
// root - элемент-контейнер в котором будет выстраиваться круг
// для вычисления смещения используем стандартные функции jQuery
var x = root.position().left,
var y = root.position().top;
// определяем - требуется ли использовать смещение в расчётах
// если нет - просто обнуляем x и y
if(root.css('position') == 'relative')
x = y = 0;
// вычисляем наш центр координат
// для этого складываем смещение и ширину/высоту и просто делим на 2
var cx = Math.round((root[0].offsetWidth + x) / 2),
cy = Math.round((root[0].offsetHeight + y) / 2);
Смещение нужно, только в том случае, если позиционирование root не является относительным (css position: relative).
В обратном случае все элементы внутри и без этого будут позиционироваться относительно родительского элемента благодаря CSS.
Итак, фундамент готов - осталось только дописать вычисление позиции каждого отдельного элемента:
/*
Вычисляем угол поворота одного сектора в радианах
*/
var sectorAngle = toRad(360 / sectorsCount);
/*
radius - радиус окружности которую мы строим
cx - центр по оси X
radius * cos - получаем абсциссу
sectorAngle * iter - получаем угол поворота для текущего элемента
*/
var toLeft = Math.round(cx + (options.radius * Math.cos(sectorAngle * iter))));
iter - индекс обрабатываемого элемента, с помощью которого делается угловой сдвиг,
radius - радиус окружности заданный в опциях виджета,
cx - вычисленный ранее центр оси координат Ox.
Таким образом мы получили координату x. Таким же нехитрым способом определяется и y:
// ордината
var toTop = Math.round(cy + (options.radius * Math.cos(sectorAngle * iter))));
Ну, а зная требуемые координаты элемента, нам остаётся лишь позиционировать элементы.
Для этого мы можем использовать jQuery метод css, либо, для более эффектной, плавной расстановки элементов методом animate:
/*
Чтобы всё расставлялось плавно - используем jquery метод animate
*/
$elem.animate({
left : toLeft,
top : toTop,
opacity : 1
},options.animationSpeed);
Код целиком: