Чистое математическое решение для итерации круговой карусели

Я изо всех сил пытаюсь придумать чистое решение для этого:

  • В карусели 7 элементов, поэтому 0 - 6.
  • Индекс 3 является средним
  • Если, например, щелкнуть второй элемент (индекс 1), каждый элемент должен переместиться на 2 позиции вправо. Если щелкнуть последний элемент (индекс 6), ему нужно будет переместиться на 3 позиции влево.
function centerCarouselOn(index, callback) {
  var items = $('li', carousel);
  var middleIdx = Math.floor(items.length / 2);
  var direction = null;
  var iterCount = 0;

  if(index === middleIdx) return;

  if(index > middleIdx) {
    direction = 'left';
    iterCount = (index - middleIdx);
  }
  else {
    direction = 'right';
    iterCount = (middleIdx - index);
  }

  $('li', carousel).each(function(k, v) {
    var li = $(v);

    // Here I need to iterate n places to the left or right
    // e.g:
    // direction = left, iterCount = 3
    // Then each li by index would need this sequence:
    // 0: 6, 5, 4
    // 1: 0, 6, 5
    // 2: 1, 0, 6
    // 3: 2, 1, 0
    // 4: 3, 2, 1
    // 5: 4, 3, 1
    // 6: 5, 4, 3 (this one moves to center - index 3)
  });

}

person Dominic    schedule 14.11.2012    source источник
comment
Вы можете проверить мой подход здесь: github.com/mgechev/jqcarousel. Вот демонстрация: carousel.mgechev.com   -  person Minko Gechev    schedule 14.11.2012
comment
Тогда каждому li по индексу понадобится эта последовательность. Почему последовательность?   -  person Evren Kuzucuoglu    schedule 14.11.2012
comment
Поскольку карусель состоит из людей разных форм и размеров, существует путь анимации по умолчанию, но затем каждый человек также может переопределить этот путь (сливается с путем по умолчанию), чтобы он выглядел лучше. Итак, чтобы хорошо выглядеть, каждый человек должен пройти эти пути. + спасибо @MinkoGechev, у меня возникли проблемы с извлечением того, что мне нужно для моего более простого, менее универсального решения, но, тем не менее, это красивый код!   -  person Dominic    schedule 14.11.2012
comment
Итак, в вашем примере кто-то нажал на человека 6, который оказывается на 3 позиции правее по сравнению с передним li карусели, и вы хотите переместить всех 3 раза на 1 позицию влево, верно?   -  person Evren Kuzucuoglu    schedule 14.11.2012
comment
@EvrenKuzucuoglu да точно   -  person Dominic    schedule 14.11.2012


Ответы (2)


это не включает никакого кода для анимации, а также предполагает, что элемент carousel является родительским <ul> для <li>s.

Должно изменять индексы каждого <li> для каждого «хода». Все, что вам действительно нужно сделать, это переместить последний элемент в первую позицию или первый элемент в последнюю позицию (в зависимости от направления, в котором вы двигаетесь). Я также добавил timeout в 1 секунду, чтобы вы могли видеть, как он проходит.

function centerCarouselOn(index, callback) {
  var items = $('li', carousel);
  var middleIdx = Math.floor(items.length / 2);
  var direction = null;
  var iterCount = 0;

  if(index === middleIdx) return;

  // if iterCount is positive, we are going right; else, we are going left
  iterCount = middleIdx - index;

  // this funciton gets called recursively until all moves are complete
  function moveCarousel() {
    if (iterCount===0) return;

    if (iterCount > 0) {
      // take the last element, prepend it to the carousel
      $('li', carousel).last().prependTo(carousel);
      iterCount--;
    } else if (iterCount < 0) {
      // take the first element, append it to the carousel
      $('li', carousel).first().appendTo(carousel);
      iterCount++;
    }

    // execute callback to apply css changes at each step
    callback();

    // set a delay, then repeat.
    window.setTimeout(moveCarousel, 1000);
  }

  // start moving the carousel
  moveCarousel(iterCount);
}
person madlee    schedule 14.11.2012
comment
Спасибо, я ценю время, которое вы потратили, чтобы ответить на этот вопрос. К сожалению, мне нужно двигаться постепенно, так как на каждом этапе есть определенный набор CSS, через который должен пройти каждый элемент! - person Dominic; 14.11.2012
comment
отредактировано, чтобы добавить вызов метода обратного вызова, который вы передаете в файл centerCarouselOn. Я предполагаю, что именно здесь вы применяете добавочные изменения CSS? я считаю, что это должно работать. - person madlee; 14.11.2012
comment
Я не использовал ваш код, но оказалось, что анимация выглядит намного лучше, если она не анимируется между ними, а проходит весь путь до того места, где она должна идти, поэтому я выберу ее в качестве ответа. - person Dominic; 14.11.2012

Всем спасибо за внимание, вот как я это сделал в итоге:

function centerCarouselOn(index, callback) {
  var items = $('li', carousel);
  var numItems = carousel.children().length;
  var middleIdx = Math.floor(items.length / 2);
  var direction = null;
  var iterCount = 0;

  if(index === middleIdx) return;

  if(index > middleIdx) {
    direction = 'left';
    iterCount = (index - middleIdx);
  }
  else {
    direction = 'right';
    iterCount = (middleIdx - index);
  }

  $('li', carousel).each(function(k, v) {
    var li = $(v);

    // Here I need to iterate n places to the left or right
    // e.g:
    // direction = left, iterCount = 3
    // Then each li by index would need this sequence:
    // 0: 6, 5, 4
    // 1: 0, 6, 5
    // 2: 1, 0, 6
    // 3: 2, 1, 0
    // 4: 3, 2, 1
    // 5: 4, 3, 1
    // 6: 5, 4, 3 (this one moves to center - index 3)

    if(direction === 'right') {
      for(var i = k; i < (k + iterCount); i++) {
        var thisIter = i;
        var nextIter = (++thisIter >= numItems) ? (thisIter - numItems) : thisIter;

        console.log(k + ': ' + nextIter);

      }
    }
    else {
      for(var i = k; i > (k - iterCount); i--) {
        var thisIter = i;
        var nextIter = (--thisIter < 0) ? (numItems + thisIter) : thisIter;

        console.log(k + ': ' + nextIter);
      }
    }
  });
}

Оказывается, анимация выглядит дерьмово, поэтому вместо этого я просто вычисляю конечную позицию (и в качестве бонуса это более эффективно):

$('li', carousel).each(function(k, v) {
  var li = $(v);

  var nextIdx = 0;

  if(direction === 'right') {
    nextIter = ((k + iterCount) > (numItems - 1)) ? ((k + iterCount) - numItems) : (k + iterCount);
  }
  else {
    nextIter = (k - iterCount) >= 0 ? (k - iterCount) : numItems - (iterCount - k);
  }

  _animateTo(li, nextIter, direction);
});
person Dominic    schedule 14.11.2012