React - алгоритм вращателя рулетки - PullRequest
0 голосов
/ 16 апреля 2020

Я пытался сделать вращатель рулетки с помощью React. Но я имею дело с некоторыми проблемами, связанными с переходами и ролями.

Это первая версия алгоритма: Функции обратного вызова выполняются каждый раз, когда изменяется реквизит, названный победителем

const slideRef = useRef(null);
function getRandomArbitrary(min, max) {
  return Math.random() * (max - min) + min;
}
const spinnerAnimation = useCallback(() => {
  const numbers = {
    0: 560,
    11: -410,
    5: 160,
    10: 320,
    6: 480,
    9: 720,
    7: 880,
    8: 1050,
    1: 1135,
    14: 960,
    2: 800,
    13: 640,
    3: 400,
    12: 240,
    4: 80,
  };
  const cycles = Math.floor(getRandomArbitrary(2, 4));
  const dev = getRandomArbitrary(0, 80);
  const scrollAmount = 480 + numbers[winner] + dev + 1200 * cycles;
  slideRef.current.classList.remove('spin_animation');
  slideRef.current.style = 'background-position-x: -212.5px';
  setTimeout(() => {
    slideRef.current.classList.add('spin_animation');
    slideRef.current.style = `background-position-x: ${`-${scrollAmount}px
  }, 10);
}, [winner]);

. Для этого я использую фон и отображаю каждое расстояние: enter image description here

My проблема в том, что есть время, когда оно не останавливается на нужном числе, а также когда мы изменяем размер окна браузера, оно ломается. Есть ли другой способ сделать спиннер или как это улучшить?

1 Ответ

0 голосов
/ 16 апреля 2020

Я думал, что сделать спиннер с фоном будет проще, чем работать с элементами. Но с фоном очень сложно заставить его реагировать.

Итак, я сделал алгоритм, который принимает ширину билета и вычисляет позицию на основе порядка и количества строк.

       const spinWheel = useCallback(() => {
    // Receives the winner prop and search for his position in the spinner be
    const order = [8, 1, 14, 2, 13, 3, 12, 4, 0, 11, 5, 10, 6, 9, 7];
    const position = order.indexOf(winner);

    // Determine position where to land
    const rows = 12;
    const card = 80 + 2 * 2;
    let landingPosition = rows * 15 * card + position * card;

    const randomize = Math.floor(Math.random() * 75) - 75 / 2;
    landingPosition += randomize;

    const axes = {
      x: Math.floor(Math.random() * 50) / 100,
      y: Math.floor(Math.random() * 20) / 100,
    };

    // Set animations and spinner translation
    wheelRef.current.style.transitionTimingFunction = `all 6000ms cubic-bezie
    wheelRef.current.style.transitionDuration = `6s`;
    wheelRef.current.style.transform = `translate3d(-${landingPosition}px, 0p

    // Reset animations and translation to init a new round
    setTimeout(() => {
      wheelRef.current.style.transitionTimingFunction = '';
      wheelRef.current.style.transitionDuration = '';
      const resetTo = -(position * card + randomize);
      wheelRef.current.style.transform = `translate3d(${resetTo}px, 0px, 0px)
    }, 7000);
  }, [winner]);

Поскольку это обратный вызов, эта функция будет выполняться при каждом изменении реквизита победителя.

...