Коротко — нужно сравнивать предыдущий порядок с текущим и показывать сообщение только для тех элементов, у которых индекс (или позиция в DOM) действительно изменился. Ниже два простых варианта решения: 1) для логики с массивами (по id) и 2) для реальных DOM-элементов (позиция на странице, FLIP).
1) Если у вас просто массив объектов с уникальным id
- Сохраните предыдущее состояние (или карту id->индекс).
- После обновления списка пройдитесь по новому списку и покажите сообщение, если старый индекс !== новый.
Пример:
const prev = [ {id:1}, {id:2}, {id:3} ];
// ... список поменялся
const current = [ {id:2}, {id:1}, {id:3} ];
const prevIndex = new Map(prev.map((it, i) => [it.id, i]));
current.forEach((it, i) => {
const oldI = prevIndex.get(it.id);
if (oldI !== undefined && oldI !== i) {
console.log(`Элемент ${it.id} сдвинулся: старый индекс ${oldI}, новый ${i}`);
}
});
Ожидаемый вывод для примера:
"Элемент 2 сдвинулся: старый индекс 1, новый 0"
"Элемент 1 сдвинулся: старый индекс 0, новый 1"
(элемент 3 не выводится, потому что его позиция не изменилась)
2) Если вам важно реальное смещение в DOM (визуально сдвинулся на странице)
Используйте FLIP: измерьте getBoundingClientRect перед изменением DOM, внесите изменения, измерьте после и сравните. Сообщение показывайте только для тех элементов, у которых rect.top/left/height/width отличаются.
Пример:
const nodes = Array.from(container.children); // узлы до изменений
const before = new Map(nodes.map(n => [n.dataset.id, n.getBoundingClientRect()]));
// внесли изменения в DOM (перестановка элементов)
const afterNodes = Array.from(container.children);
afterNodes.forEach(n => {
const id = n.dataset.id;
const b = before.get(id);
if (!b) return; // новый элемент — можно отдельно обработать
const a = n.getBoundingClientRect();
if (b.top !== a.top || b.left !== a.left) {
// элемент реально сдвинулся по экрану
showMessageFor(n, `Сдвинулся с ${Math.round(b.top)} до ${Math.round(a.top)}`);
}
});
Бонус: для плавного визуального перехода применяют FLIP-анимацию (invert + play), но это уже отдельная тема.
Частые замечания
- Используйте уникальные ключи / id, иначе вы не сможете корректно сопоставить элементы.
- Новые или удалённые элементы обрабатывайте отдельно (oldIndex === undefined или элемент из oldMap не найден в новом списке).
- Если вы используете React/Vue — пользуйтесь стабилизированными key, и сравнение индексов делайте на уровне данных, а не на DOM, или измеряйте rect, если нужна визуальная проверка.
Если пришлёте ваш полный код (тот jsbin), я подскажу точные правки и вставлю готовую функцию, которая покажет сообщение только для реально сдвинувшихся элементов.