Перемещение по отрезку

У меня есть отрезок от i1 до i2
Мне нужно научится перемещатся по этому отрезку по кругу.
Если от 0 до 10 отрезок, я стою на индексе 2 и сдвинусь на -3, то окажусь на 10 индексе
Если сдвинусь на -14, то окажусь на 10 индексе
введите сюда описание изображения

Также я могу двигаться и в правую сторону.

/**
 * Функция для сдвига индекса
 * @param {number} length - Длина элементов
 * @param {number} index - Индекс текущего элемента
 * @param {number} shift - Сдвиг
 */
function shiftDigit(length, index, shift) {
  const indexSumShift = index + shift;
  if (indexSumShift < 0) {
    return length + indexSumShift;
  }
  return (index + shift) % length;
}

console.log(shiftDigit(11, 3, -5));

Мой код не имеет особого смысла, потому что я запутался

UPD: Я подумал, правильнее будет ещё указать, с какого значения индекс отрезка начинается и где заканчивается:

/**
 * Функция для сдвига индекса
 * @param {number} start - Начало отрезка
 * @param {number} end - Конец отрезка
 * @param {number} index - Индекс текущего элемента
 * @param {number} shift - Сдвиг
 */
function shiftDigit(start, end, index, shift) {

}

console.log(shiftDigit(0, 10, 3, -15));


Ответы (2 шт):

Автор решения: MBo

Приводим диапазон к 0..size-1.
Прибавляем сдвиг. Если результат отрицательный, то после взятия модуля он лежит в диапазоне -size..-1, приводим его к положительному добавлением size.
Второй раз берём модуль на случай, если результат был положительный.
Приводим обратно к start...end

  function shiftDigit(start, end, index, shift) {
       let size = end - start + 1;
       return start + ((index - start + shift) % size + size) % size;
   }     

   console.log(shiftDigit(0, 10, 3, -15));
   console.log(shiftDigit(0, 10, 3, 15));

→ Ссылка
Автор решения: Дмытрык

смотреть метод doShift. Все остальное для визуализации

const app = new Vue({
  el: '#app',
  data() {
    return {
      length: 5,
      activeIndex: 2,
      multi: 2
    }
  },
  methods: {
    doShift(active, shift, length) {
      const z = (active + shift) % length
      this.activeIndex = z < 0 ? length + z : z
    }
  },

});
.index {
  padding: 10px;
  width: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 5px;
  border: 1px solid;
}

.control {
  padding: 8px;
  margin: 4px;
  cursor: pointer;
}

.active {
  background-color: red;
}
.wrap {
  display: flex;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<div id="app">
<div class="wrap">
  <div v-for="i in length" class="index" :class="activeIndex === i-1 ? 'active' : ''">{{i-1}}</div>
</div>
  <button v-for="i in length" class="control" @click="doShift(activeIndex, i*multi, length)">+{{i*multi}}</button>
  <button v-for="i in length" class="control" @click="doShift(activeIndex, +('-' +i*multi), length)">-{{i*multi}}</button>
</div>

→ Ссылка