Work CaseRoulette

This commit is contained in:
2025-12-07 03:26:54 +05:00
parent 39f8ec875b
commit bbd0dd11b0

View File

@ -20,6 +20,9 @@ const CENTER_INDEX = Math.floor(VISIBLE_ITEMS / 2);
const CONTAINER_WIDTH = 800;
const LINE_X = CONTAINER_WIDTH / 2;
const ANIMATION_DURATION = 10; // секунды
const ANIMATION_DURATION_MS = ANIMATION_DURATION * 1000;
function getRarityByWeight(weight?: number): Rarity {
if (weight === undefined || weight === null) return 'common';
if (weight <= 5) return 'legendary';
@ -105,50 +108,61 @@ export default function CaseRoulette({
const startAnimation = () => {
const widths = measureItemWidths();
if (widths.length === 0 || widths.length !== sequence.length) {
// Если не удалось измерить, используем базовую ширину
const winPosition = Math.floor(sequence.length / 2);
// Сколько "оборотов" хотим сделать до остановки
const EXTRA_SPINS = 3;
const averageItemWidth = ITEM_WIDTH + ITEM_GAP;
const extraDistance = EXTRA_SPINS * VISIBLE_ITEMS * averageItemWidth;
// fallback, если не смогли корректно измерить ширины
if (widths.length === 0 || widths.length !== sequence.length) {
const centerItemCenter =
winPosition * (ITEM_WIDTH + ITEM_GAP) + ITEM_WIDTH / 2;
const initialOffset = centerItemCenter - CONTAINER_WIDTH;
const finalOffset = centerItemCenter - LINE_X;
const finalOffset = centerItemCenter - LINE_X;
// стартовая позиция чуть левее финальной (едем вправо к ней)
const initialOffset = Math.max(finalOffset - extraDistance, 0);
// ставим ленту далеко "слева", чтобы она много проехала
setOffset(initialOffset);
animationTimeoutRef.current = setTimeout(() => {
setAnimating(true);
setOffset(finalOffset);
}, 200);
}, 50);
// 7 секунд анимации + небольшой запас
finishTimeoutRef.current = setTimeout(() => {
setAnimationFinished(true);
}, 7000);
}, ANIMATION_DURATION_MS + 200);
return;
}
const winPosition = Math.floor(sequence.length / 2);
// вариант с реальными ширинами
let cumulativeOffset = 0;
for (let i = 0; i < winPosition; i++) {
cumulativeOffset += widths[i] + ITEM_GAP;
}
const centerItemCenter = cumulativeOffset + widths[winPosition] / 2;
const initialOffset = centerItemCenter - CONTAINER_WIDTH;
const finalOffset = centerItemCenter - LINE_X;
// стартовая позиция чуть левее финальной (едем вправо к ней)
const initialOffset = Math.max(finalOffset - extraDistance, 0);
setOffset(initialOffset);
animationTimeoutRef.current = setTimeout(() => {
setAnimating(true);
setOffset(finalOffset);
}, 100);
}, 50);
finishTimeoutRef.current = setTimeout(() => {
setAnimationFinished(true);
}, 3100);
}, ANIMATION_DURATION_MS + 200);
};
// Даем время на рендер элементов
const renderTimeout = setTimeout(startAnimation, 100);
return () => {
@ -230,7 +244,7 @@ export default function CaseRoulette({
transform: `translateX(-${offset}px)`,
willChange: 'transform',
transition: animating
? 'transform 7s cubic-bezier(0.1, 0.8, 0.2, 1)'
? `transform ${ANIMATION_DURATION}s cubic-bezier(0.15, 0.85, 0.25, 1)`
: 'none',
}}
>