Animowane gwiazdozbiory cząsteczek


No dobra, przestań się gapić na te cholerne kropki i zacznij programować!

Widziałem animacje podobne do powyższej na kilku stronach i spodobała mi się prostota pomysłu, więc napiszmy taki programik - wystarczy nam 42 linie kodu.

Przepis wygląda z grubsza tak:

- kilka tuzinów losowych cząsteczek (particles) odbija się od brzegów Canvas
- obliczamy odległość między każdą parą cząsteczek
- jeżeli odległość jest mniejsza niż ustalony próg, rysujemy między nimi linię

Oto pełen kod, a dokładniejszy opis jest poniżej:

<html>
<body bgcolor=black>
<canvas id="myCanvaswidth="800height="600"></canvas>
<script>
 
function line(particle, particle2) {
  context.beginPath();
  context.moveTo(particle.xparticle.y);
  context.lineTo(particle2.x, particle2.y);
  context.stroke();
}
 
function animate() {
  context.clearRect(00canvas.widthcanvas.height);
  for (let i = 0i < maxParticlesi++) {
    let particle = particles[i];
    context.fillRect(particle.x - particleSize / 2particle.y - particleSize / 2particleSizeparticleSize);
    for (let j = ij < maxParticlesj++) {
      if (i != j) {
        let particle2 = particles[j];
        let distanceX = Math.abs(particle.x - particle2.x);
        let distanceY = Math.abs(particle.y - particle2.y);
        if (distanceX < threshold && distanceY < threshold) {
          context.lineWidth = ((threshold * 2) - (distanceX + distanceY)) / 50;
          let color = 200 - Math.floor(distanceX + distanceY);
          context.strokeStyle = 'rgb(' + color + ',' + color + ',' + color + ')';
          line(particle, particle2);
        }
      }
    }
    particle.x = particle.x + particle.vx;
    particle.y = particle.y + particle.vy;
    if (particle.x > canvas.width - particleSize || particle.x < particleSize)
      particle.vx = -particle.vx;
    if (particle.y > canvas.height - particleSize || particle.y < particleSize)
      particle.vy = -particle.vy;
  }
  window.requestAnimationFrame(animate);
}
 
let canvas = document.getElementById('myCanvas');
let context = canvas.getContext('2d');
let particles = [];
let particleSize = 4;
let maxParticles = 40;
let threshold = 100;
for (let i = 0i < maxParticlesi++) {
  let particle = {
    xMath.random() * canvas.width,
    yMath.random() * canvas.height,
    vxMath.random(),
    vyMath.random()
  }
  particles.push(particle);
}
context.fillStyle = 'white';
animate();
 
</script>
</body>
</html>


[1-4] ustawienia HTML
[6-11] funkcja, która rysuje linię między dwiema cząsteczkami
[13-39] główna funkcja animacji:
[14] czyszczenie poprzedniej ramki
[15-37] dla każdej cząsteczki:
[18-27] sprawdź z każdą pozostałą cząsteczką
[19] upewnij się, że nie sprawdzasz cząsteczki samej ze sobą
[21-22] oblicz przybliżoną odległość między cząsteczkami (jako sumę różnic współrzędnych X i Y). Możesz użyć dokładnej odległości [sqrt(distanceX^2+distanceY^2)], ale to tylko zwalnia program, a tak naprawdę różnica nie jest widoczna.
[23] Jeżeli różnica jest mniejsza niż założony próg...
[24] ...szerokość...
[25-26] ...i kolor linii (odcień szarości z równymi wartościami składników RGB (czerwony/zielony/niebieski) zależy od odległości. Ciekawostka: Math.floor jest tylko niezbędne dla iOS - inne platformy obsługują wartości zmiennoprzecinkowe.
[31-32] Cząsteczka rusza się w obu osiach
[34-36] Odbicie od krawędzi
[41-46] Ustawienia Canvas i parametrów.
[47-54] Inicjalizacja cząsteczek z losowymi współrzędnymi i prędkościami.
[57] Do dzieła!

Eksperymentuj z różnymi parametrami, na przykład maxParticles = 100 i threshold = 40.


Inne samouczki:

Fraktale - 25 linii JavaScript

Złudzenie optyczne - 18 linii

Sinus scroll - 30 linii

Gra "Angry Chickens"

Walentynkowe serca

Animowane krzywe kwadratowe - 40 linii

Eksperyment z enginem fizyki


Rozbijanie muru kulą - 14 linii Python/Blender 3d


Efekt domino - 10 linii Python/Blender 3d


English version of this page