Вращение кругового меню по часовой стрелке
Решил сделать круговое меню, но затупил когда При клике на стрелку "вперёд" должен быть поворот по часовой стрелке со смещением всех элементов на следующую позицию. При начальной позиции на 0 градусов сверху всё работает, но нужно чтобы всё начиналось с 120 градусов: 
В итоге сейчас сразу переходит на пятый элемент. В чём тут проблема и как её можно исправить?
<div class="circle-carousel">
<div class="container">
<div class="wraper">
<ul class="circle-container">
<li class="circle-item selected">
<img class="circle-item-image" src="/images/thumb-001.jpg" alt="">
</li>
<li class="circle-item">
<img class="circle-item-image" src="/images/thumb-002.jpg" alt="">
</li>
<li class="circle-item">
<img class="circle-item-image" src="/images/thumb-003.jpg" alt="">
</li>
<li class="circle-item">
<img class="circle-item-image" src="/images/thumb-004.jpg" alt="">
</li>
<li class="circle-item">
<img class="circle-item-image" src="/images/thumb-005.jpg" alt="">
</li>
<li class="circle-item">
<img class="circle-item-image" src="/images/thumb-003.jpg" alt="">
</li>
</ul>
<div class="circle-content">
</div>
<div class="circle-nav">
<div class="circle-nav-prev">
<a href="#">←</a>
</div>
<div class="circle-nav-next">
<a href="#">→</a>
</div>
</div>
</div>
</div>
$(function($) {
function appendContent(elem) {
$('.circle-content .circle-content-teaser-title').html(elem.find('.circle-item-title').text());
$('.circle-content .circle-content-teaser-desc').html(elem.find('.circle-item-desc').text());
$('.circle-content .circle-content-readmore').attr('href', elem.find('.circle-item-link').text());
}
var degree = 0;
function rotateElem(elem) {
var indexCurent;
var countElem = $('.circle-container .circle-item').length;
var indexElem = $('.circle-container .circle-item').index(elem);
$('.circle-container .circle-item').each(function(index) { // текущий элемент
if ($(this).hasClass('selected')) {
indexCurent = index;
}
});
$('.circle-container .circle-item.selected').removeClass('selected');
if (indexCurent < indexElem) {
degree = degree - ((360 / countElem) * (indexElem - indexCurent));
}
if (indexCurent > indexElem) {
degree = degree + ((360 / countElem) * (indexCurent - indexElem));
}
$('.circle-container').css({
'-webkit-transform': 'rotate(' + degree + 'deg)',
'-moz-transform': 'rotate(' + degree + 'deg)',
'-ms-transform': 'rotate(' + degree + 'deg)',
'-o-transform': 'rotate(' + degree + 'deg)',
'transform': 'rotate(' + degree + 'deg)'
});
elem.addClass('selected');
}
function rotatePrev(elem) {
$('.circle-container .circle-item.selected').removeClass('selected');
var countElem = $('.circle-container .circle-item').length;
var indexElem = $('.circle-container .circle-item').index(elem);
degree = degree + (360 / countElem);
$('.circle-container').css({
'-webkit-transform': 'rotate(' + degree + 'deg)',
'-moz-transform': 'rotate(' + degree + 'deg)',
'-ms-transform': 'rotate(' + degree + 'deg)',
'-o-transform': 'rotate(' + degree + 'deg)',
'transform': 'rotate(' + degree + 'deg)'
});
elem.addClass('selected');
}
function rotateNext(elem) {
$('.circle-container .circle-item.selected').removeClass('selected');
var countElem = $('.circle-container .circle-item').length;
var indexElem = $('.circle-container .circle-item').index(elem);
degree = degree - (360 / countElem);
$('.circle-container').css({
'-webkit-transform': 'rotate(' + degree + 'deg)',
'-moz-transform': 'rotate(' + degree + 'deg)',
'-ms-transform': 'rotate(' + degree + 'deg)',
'-o-transform': 'rotate(' + degree + 'deg)',
'transform': 'rotate(' + degree + 'deg)'
});
elem.addClass('selected');
}
$('.circle-container .circle-item').on('click', function(e) {
e.preventDefault();
var elem = $(this);
rotateElem(elem);
appendContent(elem);
});
$('.circle-nav .circle-nav-prev a').on('click', function(e) {
e.preventDefault();
var prev = $('.circle-container .circle-item.selected').prev();
if (prev.length == 0) {
prev = $('.circle-container .circle-item:last-child');
}
rotatePrev(prev);
appendContent(prev);
});
$('.circle-nav .circle-nav-next a').on('click', function(e) {
e.preventDefault();
var next = $('.circle-container .circle-item.selected').next();
if (next.length == 0) {
next = $('.circle-container .circle-item:first-child');
}
rotateNext(next);
appendContent(next);
});
appendContent($('.circle-container .circle-item.selected'));
});
Ответы (1 шт):
В чём тут проблема и как её можно исправить?
Основная проблема - это недопонимание назначения сочетаний клавиш Ctrl+C/Ctrl+V. Данная комбинация существует для мультиплицирования, в целях ускорения написания кода. Но, сто́ит чётко представлять предмет копирования и быть уверенным в его работоспособности, дабы не множить возможные проблемы и ошибки.
Зачастую проще написать собственное решение "с нуля" под свои задачи:
const OFFSET = 120; // Коррекция начального угла
const CARОUSEL = $('ul');
const NODES = $(CARОUSEL).children('li');
const LENGTH = $(NODES).length;
$(NODES).each((ind, el) => { $(el).css('--round', (1 / LENGTH) * ind + (1 / 360) * OFFSET) });
$('#reset').on('click', () => { $(CARОUSEL).css('--angle', ''); $(NODES).each((ind, el) => { $(el).toggleClass('select', ind > 0 ? false : true) }) });
$('#prev').on('click', () => fNav(1));
$('#next').on('click', () => fNav(-1));
$(CARОUSEL).on('wheel', () => { event.stopPropagation(); event.preventDefault(); fNav(Math.sign(event.deltaY) * -1) });
$(CARОUSEL).on('click', () => { let target = event.target.closest('li'); if (target) fNav(0, target) });
function fNav(dir, target) {
let curr = parseFloat($(CARОUSEL).css('--angle'));
let active = $(CARОUSEL).children('li.select');
let actInd = $(NODES).index(active);
let diff = actInd - $(NODES).index(target);
if (target) {
dir = Math.sign(diff) * (Math.abs(diff) > Math.floor(LENGTH / 2) ? Math.abs(diff) - LENGTH : Math.abs(diff));
} else {
target = dir > 0 ? actInd-- > 0 ? $(NODES).eq(actInd) : $(NODES).eq(LENGTH - 1) : actInd++ < LENGTH - 1 ? $(NODES).eq(actInd) : $(NODES).eq(0);
}
$(active).toggleClass('select', false);
$(target).toggleClass('select', true);
$(CARОUSEL).css('--angle', curr + (1 / LENGTH) * dir);
}
ul {
--angle: 0;
list-style-type: none;
position: relative;
height: 250px; width: 250px;
margin: 0; padding: 0;
border-radius: 50%;
filter: drop-shadow(0 5px 2px #0008);
}
li {
--round: 0;
position: absolute; left: 50%;
height: 50%;
transform-origin: center bottom;
transform: translate(-50%, 0%) rotate(calc((var(--round) + var(--angle)) * 1turn));
transition: transform 1s ease-out;
}
li > div {
position: absolute; left: 50%;
display: grid; place-items: center;
height: 2.5em; width: 2.5em;
border-radius: 50%;
transform-origin: center center;
transform: translate(-50%, 0%) rotate(calc((var(--round) + var(--angle)) * -1turn));
font: 16px/1em 'Arial Black';
box-shadow: inset 0 0 2px 1px #fa0;
transition: .25s ease-out, transform 1s ease-out;
cursor: pointer;
}
li > div:hover {
box-shadow: inset 0 0 2px 5px #fa0;
transition: .125s ease-in-out, transform 1s ease-out;
}
li.select > div {
box-shadow: inset 0 0 2px 3em #fa0;
pointer-events: none;
}
button { font: 22px/1em 'Arial Black'; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<button id="prev">◀</button><button id="reset">❌</button><button id="next">▶</button>
<ul>
<li class="select"><div>1</div></li>
<li><div>2</div></li>
<li><div>3</div></li>
<li><div>4</div></li>
<li><div>5</div></li>
<li><div>6</div></li>
<li><div>7</div></li>
<li><div>8</div></li>
<li><div>9</div></li>
<li><div>10</div></li>
<li><div>11</div></li>
<li><div>12</div></li>
</ul>
Перебор осуществляется колесом мыши, кнопками навигации или нажатием на соответствующий пункт.
Это же решение на "чистом" JavaScript - https://codepen.io/UModeL/full/bGzLwmZ.