Реалізація вільного переміщення частинок на ReactJS

Вітаю! Хочу вам показати один із способів, як реалізувати вільне переміщення часток у зазначеному діапазоні. Для виконання цього завдання я буду використовувати ReactJS. Але сам алгоритм все одно буде спільним, і ви можете його використовувати де завгодно.

В кінці статті, ми створимо з вами таку штуку.

Неправильний спосіб

Перше, що приходить в голову для вирішення цієї задачі, це просто рандомить X і Y. Давайте подивимося, що з цього вийде.

Тут ми просто рандомим зрушення кожну секунду в проміжку від -50 до 50 по X і по Y:

Math.random() * 100 - 50

А плавність переходу здійснюється за допомогою css властивості transition:

transition: transform 1s linear;

Як бачите, вийшло не зовсім те, що ми хотіли. Звичайно можна налаштувати так, щоб зсув додавався до вже існуючої позиції, тоді буде більше схоже на правду. Але все одно нам потрібно зайти трохи з іншого боку.

Правильний спосіб

Попередній метод здається таким кривим з кількох причин:

  1. В реальності частинка не може так різко міняти напрям.
  2. Частка за кожен відрізок часу має пройти певну відстань

І це наводить на думку, що рандомить потрібно саме напрямок, в якому буде рухатися частинка, причому в певному інтервалі градусів, щоб не було різких поворотів. Так ми вирішимо першу проблему.

А для вирішення другої проблеми, ми будемо заздалегідь вказувати крок, на який потрібно зрушувати частку за інтервал часу.

Тепер доведеться згадати базовий курс тригонометрії. Нам відома довжина l і кут deg. Потрібно знайти X і Y.

sin — відношення противолежащей сторони до гіпотенузі.
cos — відношення прилеглій сторони до гіпотенузі.

У нас вийдуть такі формули для обчислення:


x = cos(deg) * l
y = sin(deg) * l

Але є одне але. В javaScript Math.sin приймає кут в радіанах (значення від -1 до 1). Тому перш ніж прокидати кут, потрібно його попередньо перевести в радіани.

Читайте також  Реалізація BottomAppBar. Частина 2: Меню і елемент управління Navigation Drawer
deg(радий) = deg(гр) * Pi / 180

Напишемо функцію, яка на вхід буде отримувати кут, і відстань, на яке потрібно зрушити частку. А функція буде повертати об’єкт { x, y } c нашими значеннями для зсуву.


function getShift(deg, step) {
 return {
 x: +(Math.cos(deg * Math.PI / 180) * step).toFixed(),
 y: +(Math.sin(deg * Math.PI / 180) * step).toFixed(),
};
};

Потестим, що буде виводити наша функція. Припустимо, ми будемо кожен раз зрушувати частку на 10px. Подивимося, що поверне getShift при різних значеннях кутів.


getShift(30, 10); // {x: 9, y: 5}
getShift(90, 10); // {x 0, y: 10}
getShift(135, 10); // {x: -7, y: 7}
getShift(210, 10); // {x: -9, y: -5}
getShift(-30, 10); // {x: 9, y: -5}

Ну що ж, схоже на правду, згодні?

Тепер спробуємо виправити наше перше писане додаток.


Вже непогано! Залишилось реалізувати рамки, за які частинка не зможе вилітати. Так як зараз скоріше всього через якийсь час синій коло відлетить за межі екрану.

Для того, щоб зробити рамки, потрібно буде додати нову константу. А також додати одну умову. Тут нам підійде цикл while. Якщо на шляху зустрінеться обмеження, то ми будемо повертати кут до тих пір, поки на вивернемо від рамки.

Для наочності додамо жовтий квадрат, за межі якого коло не зможе вилітати. Ось що вийшло:


Наш алгоритм повністю готовий до використання. Наступний крок – це реалізація даного алгоритму на ReactJS c використанням його можливостей.

Переносимо алгоритм на ReactJS

При перенесенні нашого додатка на ReactJS поставимо перед собою наступні завдання:

  1. Створимо компонент-обгортку MovingPart в яку можна буде прокинути що завгодно.
  2. В стані будемо зберігати значення X і Y, так як тільки вони потрібні для перемальовування компонента.
  3. Зовні компонент будемо прокидывать інтервал, межу, за яку не можна виходити і крок, на який буде зрушуватися елемент за один інтервал часу.
  4. Отрисуем невелику красивість з декількома компонентами MovingPart, для того, щоб приблизно уявити, де це може застосовуватися в реальному житті
Читайте також  Нарешті з'явилася задача, яку зможуть вирішити тільки квантові комп'ютери

В результаті отримаємо наступний приклад:


Вихідні дані будемо брати з масиву data.

Після цього описуємо компонент MovingPart:

  • Інтервал (interval), відстань (distance) і зсув за один крок (step) отримуємо ззовні з props;
  • Максимальний поворот при русі (maxRotate) і поточний кут зсуву (deg) визначаємо всередині елемента;
  • Значення x і y виносимо в стан компонента;
  • Метод getShift визначаємо як внутрішній метод компонента.

Після цього з допомогою циклу map рендерим всі елементи, обертаючи їх нашим створеним компонентом MovingPart.

Спасибі за увагу! Це була моя перша стаття на хабре, сподіваюся вона буде корисна. Пробуйте, експериментуйте.

Степан Лютий

Обожнюю технології в сучасному світі. Хоча частенько і замислююся над тим, як далеко вони нас заведуть. Не те, щоб я прям і знаюся на ядрах, пікселях, коллайдерах і інших парсеках. Просто приходжу в захват від того, що може в творчому пориві вигадати людський розум.

You may also like...

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *