DEV Community

0 seconds of 0 secondsVolume 90%
Press shift question mark to access a list of keyboard shortcuts
00:00
00:00
00:00
 
Prince
Prince

Posted on

1

Particles effect using the html css and js

`<!DOCTYPE html>









Interactive Particle System

<br>
* {<br>
margin: 0;<br>
padding: 0;<br>
box-sizing: border-box;<br>
}</p>
<div class="highlight"><pre class="highlight plaintext"><code> body {
font-family: 'Arial', sans-serif;
overflow: hidden;
background-color: #0a0a0a;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
color: white;
}
#canvas {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 1;
}

.overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    z-index: 2;
    pointer-events: none;
}

.title {
    font-size: 2.5rem;
    font-weight: bold;
    text-shadow: 0 0 10px rgba(139, 92, 246, 0.8);
    color: #8b5cf6;
    opacity: 0;
    transition: opacity 2s ease;
    margin-bottom: 20px;
    text-align: center;
}

.subtitle {
    font-size: 1.2rem;
    opacity: 0;
    transition: opacity 2s ease;
    text-align: center;
    max-width: 80%;
    text-shadow: 0 0 5px rgba(255, 255, 255, 0.5);
}

.cta {
    position: absolute;
    bottom: 5%;
    font-size: 1.4rem;
    font-weight: bold;
    color: #8b5cf6;
    opacity: 0;
    transition: opacity 1s ease;
    text-align: center;
    z-index: 5;
    width: 100%;
    text-shadow: 0 0 10px rgba(139, 92, 246, 0.8);
}

.overlay-touch {
    position: absolute;
    width: 100%;
    height: 100%;
    z-index: 10;
    opacity: 0;
    pointer-events: all;
    cursor: pointer;
}
Enter fullscreen mode Exit fullscreen mode

&lt;/style&gt;
</code></pre></div>
<p></head><br>
<body><br>
<canvas id="canvas"></canvas></p>
<div class="highlight"><pre class="highlight plaintext"><code>&lt;!-- &lt;div class="overlay"&gt;
&lt;h1 class="title"&gt;Interactive Particle System&lt;/h1&gt;
&lt;h2 class="subtitle"&gt;Touch or click to interact with particles&lt;/h2&gt;
&lt;/div&gt; --&gt;

&lt;div class="cta"&gt;Double tap to create particle explosions&lt;/div&gt;

&lt;div class="overlay-touch"&gt;&lt;/div&gt;

&lt;script&gt;
// Canvas setup
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// Animation variables
let particles = [];
let connections = [];
let animationStage = 0;
let lastTime = 0;
let mouseX = 0, mouseY = 0;
let isUserInteracting = false;
let isFirstTouch = true;

// DOM elements
const title = document.querySelector('.title');
const subtitle = document.querySelector('.subtitle');
const cta = document.querySelector('.cta');
const touchOverlay = document.querySelector('.overlay-touch');

// Colors
const colors = [
    '#8b5cf6', // Purple
    '#3b82f6', // Blue
    '#ec4899', // Pink
    '#10b981', // Green
    '#f59e0b'  // Amber
];

// Particle class
class Particle {
    constructor(x, y, color, size = 3, speedFactor = 1, fixed = false) {
        this.x = x;
        this.y = y;
        this.size = size;
        this.color = color;
        this.baseX = x;
        this.baseY = y;
        this.density = (Math.random() * 30) + 1;
        this.speedFactor = speedFactor;
        this.fixed = fixed;
        this.vx = (Math.random() - 0.5) * 2;
        this.vy = (Math.random() - 0.5) * 2;
        this.friction = 0.95;
        this.life = 1;
        this.decay = Math.random() * 0.01 + 0.001;
        this.maxSize = size;
    }

    draw() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.size * this.life, 0, Math.PI * 2);
        ctx.closePath();

        // Create gradient for particle
        const gradient = ctx.createRadialGradient(
            this.x, this.y, 0,
            this.x, this.y, this.size * this.life
        );
        gradient.addColorStop(0, this.color);
        gradient.addColorStop(1, 'rgba(0,0,0,0)');

        ctx.fillStyle = gradient;
        ctx.fill();
    }

    update() {
        if (this.fixed) return;

        // Apply velocity
        this.x += this.vx * this.speedFactor;
        this.y += this.vy * this.speedFactor;

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

        // Apply gravity (subtle pull downward)
        this.vy += 0.02 * this.speedFactor;

        // Boundary checks with bounce effect
        if (this.x &amp;lt; this.size) {
            this.x = this.size;
            this.vx *= -0.8;
        }
        if (this.x &amp;gt; canvas.width - this.size) {
            this.x = canvas.width - this.size;
            this.vx *= -0.8;
        }
        if (this.y &amp;lt; this.size) {
            this.y = this.size;
            this.vy *= -0.8;
        }
        if (this.y &amp;gt; canvas.height - this.size) {
            this.y = canvas.height - this.size;
            this.vy *= -0.8;
        }

        // Mouse interaction
        if (isUserInteracting) {
            const dx = mouseX - this.x;
            const dy = mouseY - this.y;
            const distance = Math.sqrt(dx * dx + dy * dy);
            const forceDirectionX = dx / distance;
            const forceDirectionY = dy / distance;

            // Calculate force (stronger when closer)
            const maxDistance = 150;
            const force = (maxDistance - Math.min(maxDistance, distance)) / 10;

            if (distance &amp;lt; maxDistance) {
                this.vx += forceDirectionX * force / this.density;
                this.vy += forceDirectionY * force / this.density;
            }
        }

        // Decay particle life if it's an explosion particle
        if (this.decay &amp;gt; 0) {
            this.life -= this.decay;
            if (this.life &amp;lt;= 0) {
                this.life = 0;
            }
        }
    }

    isAlive() {
        return this.life &amp;gt; 0.01;
    }
}

// Create initial particles
function initParticles() {
    particles = [];
    for (let i = 0; i &amp;lt; 150; i++) {
        const x = Math.random() * canvas.width;
        const y = Math.random() * canvas.height;
        const color = colors[Math.floor(Math.random() * colors.length)];
        const size = Math.random() * 3 + 2;
        particles.push(new Particle(x, y, color, size));
    }
}

// Draw connections between particles
function connectParticles() {
    connections = [];
    const maxDistance = 150;

    for (let i = 0; i &amp;lt; particles.length; i++) {
        if (!particles[i].isAlive()) continue;

        for (let j = i + 1; j &amp;lt; particles.length; j++) {
            if (!particles[j].isAlive()) continue;

            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 &amp;lt; maxDistance) {
                const opacity = 1 - (distance / maxDistance);
                connections.push({
                    start: particles[i],
                    end: particles[j],
                    opacity: opacity * particles[i].life * particles[j].life
                });
            }
        }
    }
}

// Draw the connections
function drawConnections() {
    for (const connection of connections) {
        ctx.beginPath();
        ctx.moveTo(connection.start.x, connection.start.y);
        ctx.lineTo(connection.end.x, connection.end.y);

        const gradient = ctx.createLinearGradient(
            connection.start.x, connection.start.y,
            connection.end.x, connection.end.y
        );

        gradient.addColorStop(0, connection.start.color);
        gradient.addColorStop(1, connection.end.color);

        ctx.strokeStyle = gradient;
        ctx.globalAlpha = connection.opacity * 0.7;
        ctx.lineWidth = connection.opacity * 2;
        ctx.stroke();
        ctx.globalAlpha = 1;
    }
}

// Create particle explosion
function createExplosion(x, y) {
    const particleCount = Math.floor(Math.random() * 20) + 30;
    const baseHue = Math.floor(Math.random() * 360);

    for (let i = 0; i &amp;lt; particleCount; i++) {
        // Create color variations
        const hue = (baseHue + Math.random() * 30 - 15) % 360;
        const color = `hsl(${hue}, 80%, 60%)`;

        // Calculate random direction
        const angle = Math.random() * Math.PI * 2;
        const speed = Math.random() * 6 + 1;
        const size = Math.random() * 4 + 2;

        const particle = new Particle(x, y, color, size);
        particle.vx = Math.cos(angle) * speed;
        particle.vy = Math.sin(angle) * speed;
        particle.friction = 0.98;
        particle.decay = Math.random() * 0.02 + 0.005;

        particles.push(particle);
    }
}

// Animation loop
function animate(timestamp) {
    const deltaTime = timestamp - lastTime;
    lastTime = timestamp;

    // Clear canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Update and draw particles
    particles = particles.filter(particle =&amp;gt; particle.isAlive());

    for (const particle of particles) {
        particle.update();
        particle.draw();
    }

    // Connect particles
    connectParticles();
    drawConnections();

    // Progress the animation stages
    updateAnimation(deltaTime);
    requestAnimationFrame(animate);
}

// Handle animation stages
function updateAnimation(deltaTime) {
    if (animationStage === 0 &amp;amp;&amp;amp; lastTime &amp;gt; 1000) {
        // Show title
        title.style.opacity = '1';

        setTimeout(() =&amp;gt; {
            subtitle.style.opacity = '1';
            touchOverlay.style.opacity = '1';
            animationStage = 1;
        }, 2000);
    }
    else if (animationStage === 1 &amp;amp;&amp;amp; lastTime &amp;gt; 5000) {
        // Show CTA
        cta.style.opacity = '1';
        animationStage = 2;

        // Create random explosions occasionally
        setInterval(() =&amp;gt; {
            if (!isUserInteracting &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {
                const x = Math.random() * canvas.width;
                const y = Math.random() * canvas.height;
                createExplosion(x, y);
            }
        }, 3000);
    }
}

// Handle window resize
window.addEventListener('resize', () =&amp;gt; {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    initParticles();
});

// Handle mouse/touch events for user interaction
touchOverlay.addEventListener('mousemove', (e) =&amp;gt; {
    mouseX = e.clientX;
    mouseY = e.clientY;
});

touchOverlay.addEventListener('mousedown', () =&amp;gt; {
    isUserInteracting = true;
});

touchOverlay.addEventListener('mouseup', () =&amp;gt; {
    isUserInteracting = false;
});

touchOverlay.addEventListener('touchmove', (e) =&amp;gt; {
    e.preventDefault();
    mouseX = e.touches[0].clientX;
    mouseY = e.touches[0].clientY;
    isUserInteracting = true;

    // Create small particles while dragging
    if (Math.random() &amp;lt; 0.3) {
        const color = colors[Math.floor(Math.random() * colors.length)];
        const particle = new Particle(mouseX, mouseY, color, Math.random() * 2 + 1);
        particle.vx = (Math.random() - 0.5) * 2;
        particle.vy = (Math.random() - 0.5) * 2;
        particles.push(particle);
    }
});

touchOverlay.addEventListener('touchend', () =&amp;gt; {
    isUserInteracting = false;
});

// Create explosion on click/tap
touchOverlay.addEventListener('click', (e) =&amp;gt; {
    const x = e.clientX || e.touches[0].clientX;
    const y = e.clientY || e.touches[0].clientY;
    createExplosion(x, y);

    // Show/hide UI elements based on first touch
    if (isFirstTouch) {
        setTimeout(() =&amp;gt; {
            title.style.opacity = '0';
            subtitle.style.opacity = '0';
        }, 500);
        isFirstTouch = false;
    }
});

// Initialize and start animation
function init() {
    initParticles();
    requestAnimationFrame(animate);
}

init();
Enter fullscreen mode Exit fullscreen mode

&lt;/script&gt;
</code></pre></div>
<p></body><br>
</html>`</p>

Top comments (0)