bubbles

by carlhong

HTML

<div id="container"></div>

CSS

body {
    margin: 0;
    overflow: hidden;
    background-color: #000;
}

.logo {
    position: absolute;
    width: 0;
    height: 0;
    border-radius: 50%; /* 圆形 */
    transition: transform 0.2s ease, filter 0.2s ease;
    opacity: 0;
    animation: fade-in 1s forwards;
    filter: brightness(1.5) drop-shadow(0 0 10px rgba(255, 255, 255, 0.8)); /* 默认发光效果 */
}

@keyframes fade-in {
    from { opacity: 0; transform: scale(0.5); }
    to { opacity: 1; transform: scale(1); }
}

@keyframes glow {
    0% { filter: brightness(1.5) drop-shadow(0 0 10px rgba(255, 255, 255, 0.8)); }
    50% { filter: brightness(2) drop-shadow(0 0 20px rgba(255, 255, 255, 1)); }
    100% { filter: brightness(1.5) drop-shadow(0 0 10px rgba(255, 255, 255, 0.8)); }
}

JavaScript

const numLogos = 5; // 同时漂浮的圆形数量
const totalLogos = 7; // 总共的不同圆形
const logos = [];
const colors = Array.from({ length: totalLogos }, () =>
    `hsl(${Math.random() * 360}, 100%, 50%)`
);

const screenWidth = window.innerWidth;
const screenHeight = window.innerHeight;

function createLogoElement(color) {
    const logo = document.createElement('div');
    logo.classList.add('logo');
    logo.style.backgroundColor = color;
    document.body.appendChild(logo);
    return logo;
}

function getRandomSize() {
    return Math.random() * 50 + 70; // 70px to 120px
}

function getRandomPosition(size) {
    let position;
    let isOverlapping;
    do {
        isOverlapping = false;
        position = {
            x: Math.random() * (screenWidth - size),
            y: Math.random() * (screenHeight - size),
        };

        // 检查是否与已有 Logo 重叠
        for (const { position: otherPos, size: otherSize } of logos) {
            const distX = position.x - otherPos.x;
            const distY = position.y - otherPos.y;
            const distance = Math.sqrt(distX * distX + distY * distY);
            if (distance < (size + otherSize) / 2) {
                isOverlapping = true;
                break;
            }
        }
    } while (isOverlapping);

    return position;
}

function getRandomDirection() {
    let dx = Math.random() * 2 - 1;
    let dy = Math.random() * 2 - 1;
    const magnitude = Math.sqrt(dx * dx + dy * dy);
    return { dx: dx / magnitude, dy: dy / magnitude };
}

function initLogos() {
    for (let i = 0; i < numLogos; i++) {
        const color = colors[Math.floor(Math.random() * colors.length)];
        const logo = createLogoElement(color);
        const size = getRandomSize();
        logo.style.width = `${size}px`;
        logo.style.height = `${size}px`;
        const position = getRandomPosition(size);
        const direction = getRandomDirection();
        logos.push({ logo, size, position, direction });
        setPosition(logo, position);
   ...