DEV Community

Play Button Pause Button
Prince
Prince

Posted on

Physics effects with the normal css , html and javascript

Follow us on the instagram: https://www.instagram.com/prince_codes1/

Code:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Interactive Particle Physics</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      background: #000;
      height: 100vh;
      overflow: hidden;
      display: flex;
      justify-content: center;
      align-items: center;
      font-family: 'Arial', sans-serif;
      color: white;
    }

    canvas {
      position: absolute;
      top: 0;
      left: 0;
      z-index: 1;
    }

    .controls {
      position: absolute;
      bottom: 20px;
      left: 50%;
      transform: translateX(-50%);
      z-index: 10;
      display: flex;
      gap: 15px;
      background: rgba(0, 0, 0, 0.7);
      padding: 15px 25px;
      border-radius: 50px;
      backdrop-filter: blur(10px);
      border: 1px solid rgba(255, 255, 255, 0.1);
    }

    .control-btn {
      background: none;
      border: none;
      color: white;
      font-size: 16px;
      cursor: pointer;
      padding: 8px 16px;
      border-radius: 50px;
      transition: all 0.3s;
      border: 1px solid rgba(255, 255, 255, 0.2);
    }

    .control-btn:hover, .control-btn.active {
      background: rgba(255, 255, 255, 0.2);
      transform: translateY(-2px);
      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
    }

    .info-panel {
      position: absolute;
      top: 20px;
      left: 20px;
      z-index: 10;
      background: rgba(0, 0, 0, 0.7);
      padding: 15px;
      border-radius: 10px;
      backdrop-filter: blur(10px);
      border: 1px solid rgba(255, 255, 255, 0.1);
      font-size: 14px;
      opacity: 0.8;
      transition: opacity 0.3s;
    }

    .info-panel:hover {
      opacity: 1;
    }

    .title {
      position: absolute;
      top: 20px;
      left: 50%;
      transform: translateX(-50%);
      z-index: 10;
      font-size: 24px;
      font-weight: bold;
      letter-spacing: 2px;
      text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
    }
  </style>
</head>
<body>
  <canvas id="canvas"></canvas>

  <div class="title">INTERACTIVE PARTICLE PHYSICS</div>



  <div class="controls">
    <button class="control-btn active" data-mode="attract">Attract</button>
    <button class="control-btn" data-mode="repel">Repel</button>
    <button class="control-btn" data-mode="orbit">Orbit</button>
    <button class="control-btn" data-mode="chaos">Chaos</button>
    <button class="control-btn" data-mode="reset">Reset</button>
  </div>

  <script>
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');

    // Set canvas size
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    // Particles array
    let particles = [];
    let mode = 'attract';

    // Mouse position
    const mouse = {
      x: null,
      y: null,
      down: false,
      prevX: null,
      prevY: null
    };

    // Particle class
    class Particle {
      constructor(x, y, vx, vy) {
        this.x = x;
        this.y = y;
        this.size = Math.random() * 3 + 2;
        this.color = `hsl(${Math.random() * 360}, 100%, 70%)`;
        this.vx = vx;
        this.vy = vy;
        this.alpha = 1;
        this.trail = [];
        this.trailLength = 20;
      }

      update() {
        // Update position
        this.x += this.vx;
        this.y += this.vy;

        // Add position to trail
        this.trail.unshift({ x: this.x, y: this.y });
        if (this.trail.length > this.trailLength) {
          this.trail.pop();
        }

        // Check boundaries
        if (this.x < 0 || this.x > canvas.width) this.vx *= -0.8;
        if (this.y < 0 || this.y > canvas.height) this.vy *= -0.8;

        // Apply friction
        this.vx *= 0.99;
        this.vy *= 0.99;

        // Interact with other particles based on mode
        for (let i = 0; i < particles.length; i++) {
          const particle = particles[i];
          if (this === particle) continue;

          const dx = particle.x - this.x;
          const dy = particle.y - this.y;
          const distance = Math.sqrt(dx * dx + dy * dy);

          if (distance < 150) {
            const forceX = dx / distance;
            const forceY = dy / distance;
            const force = (150 - distance) / 150;

            if (mode === 'attract') {
              this.vx += forceX * force * 0.03;
              this.vy += forceY * force * 0.03;
            } else if (mode === 'repel') {
              this.vx -= forceX * force * 0.1;
              this.vy -= forceY * force * 0.1;
            } else if (mode === 'orbit') {
              this.vx += forceY * force * 0.05;
              this.vy -= forceX * force * 0.05;
            } else if (mode === 'chaos') {
              this.vx += (Math.random() - 0.5) * force * 0.2;
              this.vy += (Math.random() - 0.5) * force * 0.2;
            }
          }
        }
      }

      draw() {
        // Draw trail
        for (let i = 0; i < this.trail.length; i++) {
          const alpha = (this.trail.length - i) / this.trail.length * 0.6;
          const size = this.size * (1 - i / this.trail.length);

          ctx.beginPath();
          ctx.arc(this.trail[i].x, this.trail[i].y, size, 0, Math.PI * 2);
          ctx.fillStyle = this.color.replace('hsl', 'hsla').replace(')', `, ${alpha})`);
          ctx.fill();
        }

        // Draw particle
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
        ctx.fillStyle = this.color;
        ctx.fill();

        // Draw glow
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.size * 2, 0, Math.PI * 2);
        const gradient = ctx.createRadialGradient(
          this.x, this.y, this.size,
          this.x, this.y, this.size * 4
        );
        gradient.addColorStop(0, this.color.replace('hsl', 'hsla').replace(')', ', 0.4)'));
        gradient.addColorStop(1, this.color.replace('hsl', 'hsla').replace(')', ', 0)'));
        ctx.fillStyle = gradient;
        ctx.fill();
      }
    }

    // Create particles when mouse is dragged
    function createParticles() {
      if (mouse.down && mouse.prevX !== null) {
        const speedX = (mouse.x - mouse.prevX) * 0.2;
        const speedY = (mouse.y - mouse.prevY) * 0.2;

        // Create multiple particles with slight variations
        for (let i = 0; i < 2; i++) {
          const randomOffsetX = (Math.random() - 0.5) * 10;
          const randomOffsetY = (Math.random() - 0.5) * 10;
          const randomSpeedX = speedX + (Math.random() - 0.5) * 2;
          const randomSpeedY = speedY + (Math.random() - 0.5) * 2;

          particles.push(new Particle(
            mouse.x + randomOffsetX,
            mouse.y + randomOffsetY,
            randomSpeedX,
            randomSpeedY
          ));
        }
      }

      mouse.prevX = mouse.x;
      mouse.prevY = mouse.y;
    }

    // Animation loop
    function animate() {
      // Clear canvas with semi-transparent black for trail effect
      ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      // Create particles if mouse is down
      if (mouse.down) {
        createParticles();
      }

      // Update and draw particles
      for (let i = 0; i < particles.length; i++) {
        particles[i].update();
        particles[i].draw();

        // Remove particles with very low velocity
        const speed = Math.sqrt(
          particles[i].vx * particles[i].vx + 
          particles[i].vy * particles[i].vy
        );

        if (speed < 0.05 && particles.length > 100) {
          particles.splice(i, 1);
          i--;
        }
      }

      // Draw connections between close particles
      drawConnections();

      requestAnimationFrame(animate);
    }

    // Draw connections between particles
    function drawConnections() {
      for (let i = 0; i < particles.length; i++) {
        for (let j = i + 1; j < particles.length; j++) {
          const dx = particles[i].x - particles[j].x;
          const dy = particles[i].y - particles[j].y;
          const distance = Math.sqrt(dx * dx + dy * dy);

          if (distance < 100) {
            ctx.beginPath();
            ctx.moveTo(particles[i].x, particles[i].y);
            ctx.lineTo(particles[j].x, particles[j].y);
            const alpha = (100 - distance) / 100 * 0.2;
            ctx.strokeStyle = `rgba(255, 255, 255, ${alpha})`;
            ctx.lineWidth = 1;
            ctx.stroke();
          }
        }
      }
    }

    // Event listeners
    window.addEventListener('resize', () => {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    });

    canvas.addEventListener('mousedown', (e) => {
      mouse.down = true;
      mouse.x = e.clientX;
      mouse.y = e.clientY;
      mouse.prevX = e.clientX;
      mouse.prevY = e.clientY;
    });

    canvas.addEventListener('mouseup', () => {
      mouse.down = false;
      mouse.prevX = null;
      mouse.prevY = null;
    });

    canvas.addEventListener('mousemove', (e) => {
      mouse.x = e.clientX;
      mouse.y = e.clientY;
    });

    // Mobile support
    canvas.addEventListener('touchstart', (e) => {
      mouse.down = true;
      mouse.x = e.touches[0].clientX;
      mouse.y = e.touches[0].clientY;
      mouse.prevX = e.touches[0].clientX;
      mouse.prevY = e.touches[0].clientY;
    });

    canvas.addEventListener('touchend', () => {
      mouse.down = false;
      mouse.prevX = null;
      mouse.prevY = null;
    });

    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault();
      mouse.x = e.touches[0].clientX;
      mouse.y = e.touches[0].clientY;
    });

    // Mode buttons
    const buttons = document.querySelectorAll('.control-btn');
    buttons.forEach(button => {
      button.addEventListener('click', () => {
        // Set active button
        buttons.forEach(btn => btn.classList.remove('active'));
        button.classList.add('active');

        // Set mode
        mode = button.dataset.mode;

        // Reset particles if reset button
        if (mode === 'reset') {
          particles = [];
        }
      });
    });

    // Start animation
    animate();

    // Add initial particles
    for (let i = 0; i < 50; i++) {
      const x = Math.random() * canvas.width;
      const y = Math.random() * canvas.height;
      const vx = (Math.random() - 0.5) * 2;
      const vy = (Math.random() - 0.5) * 2;

      particles.push(new Particle(x, y, vx, vy));
    }

    // Create initial bursts
    function createInitialBurst() {
      const x = Math.random() * canvas.width;
      const y = Math.random() * canvas.height;

      for (let i = 0; i < 20; i++) {
        const angle = Math.random() * Math.PI * 2;
        const speed = Math.random() * 5 + 1;
        const vx = Math.cos(angle) * speed;
        const vy = Math.sin(angle) * speed;

        particles.push(new Particle(x, y, vx, vy));
      }
    }

    // Create initial bursts
    for (let i = 0; i < 3; i++) {
      setTimeout(() => {
        createInitialBurst();
      }, i * 1000);
    }
  </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.