Saudações! Quero mostrar uma das maneiras de como realizar o livre movimento de partículas no intervalo especificado. Usarei o ReactJS para concluir esta tarefa. Mas o próprio algoritmo ainda será geral e você poderá usá-lo em qualquer lugar.

No final do artigo, criaremos 
uma coisa dessas com você.
Caminho errado
A primeira coisa que vem à mente para resolver esse problema é simplesmente aleatorizar X e Y. Vamos ver o que acontece.
Aqui, simplesmente randomizamos o turno a cada segundo no intervalo de -50 a 50 em X e em Y:
Math.random() * 100 - 50 
E a transição é suave usando a propriedade de transição css:
 transition: transform 1s linear; 
Como você pode ver, o resultado não é exatamente o que queríamos. Obviamente, você pode configurá-lo para que a mudança seja adicionada a uma posição existente, e será mais parecida com a verdade. Mas ainda assim, precisamos seguir um caminho um pouco diferente.
Caminho certo
O método anterior parece tão torto por vários motivos:
- Na realidade, uma partícula não pode mudar de direção tão abruptamente.
- Partículas para cada período de tempo devem passar uma certa distância
E isso sugere que precisamos aleatoriamente exatamente a direção na qual a partícula se moverá, e em um certo intervalo de graus, para que não haja curvas acentuadas. Então, vamos resolver o primeiro problema.
E para resolver o segundo problema, indicaremos antecipadamente o passo pelo qual a partícula precisa ser deslocada ao longo do intervalo de tempo.
Agora você precisa se lembrar do curso básico de trigonometria. Sabemos o comprimento 
l ângulo 
deg . Precisa encontrar 
X e 
Y
pecado é a razão do lado oposto à hipotenusa.
cos é a razão do lado para a hipotenusa.
Temos as seguintes fórmulas para calcular:
 x = cos(deg) * l y = sin(deg) * l 
Mas há uma coisa. No javaScript, 
Math.sin assume um ângulo em radianos (um 
valor de -1 a 1 ). Portanto, antes de lançar um canto, você deve primeiro convertê-lo em radianos.
 deg() = deg() * Pi / 180 
Escrevemos uma função que receberá um ângulo na entrada e a distância pela qual a partícula precisa ser deslocada. E a função 
{ x, y } com nossos valores para o turno retornará a função.
 function getShift(deg, step) { return { x: +(Math.cos(deg * Math.PI / 180) * step).toFixed(), y: +(Math.sin(deg * Math.PI / 180) * step).toFixed(), }; }; 
Testaremos o que nossa função produzirá. Suponha que movamos a partícula 
10px cada vez. Vamos ver o que o 
getShift retorna para diferentes ângulos.

 getShift(30, 10);  
Bem, ao que parece, você concorda?
Agora tente consertar nosso primeiro aplicativo por escrito.
Já não é ruim! Resta perceber a estrutura além da qual a partícula não será capaz de voar. Desde agora, provavelmente depois de algum tempo, o círculo azul voará para fora da tela.
Para criar a estrutura, você precisará adicionar uma nova constante. E também adicione uma condição. É aqui que o loop while funciona para nós. Se houver uma restrição no caminho, giraremos a esquina até a curva do quadro.
Para maior clareza, adicione um quadrado amarelo, além do qual o círculo não será capaz de voar. Aqui está o que aconteceu:
Nosso algoritmo está completamente pronto para uso. O próximo passo é implementar esse algoritmo no ReactJS usando seus recursos.
Portando o algoritmo para o ReactJS
Ao portar nosso aplicativo para o ReactJS, definiremos as seguintes tarefas:
- Crie um MovingPartwrapperMovingPartno qual você possa lançar qualquer coisa.
- No estado, armazenaremos os valores de X e Y, pois somente eles são necessários para redesenhar o componente.
- Lá fora, um componente será lançado em um intervalo, uma borda além da qual é impossível avançar e a etapa pela qual o elemento será deslocado em um intervalo de tempo.
- Vamos desenhar um pouco de beleza com vários componentes do MovingPart, a fim de imaginar onde ele pode ser aplicado na vida real.
Como resultado, obtemos o seguinte exemplo:
Vamos pegar os dados iniciais da matriz de 
data .
Depois disso, descrevemos o componente 
MovingPart :
- O intervalo (intervalo), a distância (distância) e a mudança em um passo (passo) saímos dos adereços;
- A rotação máxima durante o movimento (maxRotate) e o ângulo de deslocamento atual (deg) são determinados dentro do elemento;
- Os valores x e y são levados para o estado do componente;
- O método getShift é definido como o método interno do componente.
Depois disso, usando o loop de 
map , renderize todos os elementos, agrupando-os com nosso componente 
MovingPart criado.
Obrigado pela atenção! Este foi meu primeiro artigo sobre Habré, espero que seja útil. Experimente, experimente.