博客文章统计
截止2025年05月09日,已发布 97 篇文章
JS特效-新年(灯笼) - Cesii Blog
文章目录

JS特效-新年(灯笼)

2025-04-27 16:53 99
(function () {
    // 动态添加样式
    const style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = `
        /* 基础样式重置 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        /* 防止页面滚动 */
        body {
            overflow: hidden;
            width: 100vw;
            height: 100vh;
        }

        /* 灯笼容器样式 */
        .deng-box {
            position: fixed;
            top: -30px;
            left: 10px;
            z-index: 9999;
            pointer-events: none;
            animation: float 5s ease-in-out infinite;
            filter: drop-shadow(0 0 15px rgba(255, 215, 0, 0.6));
        }

        .deng-box1 {
            position: fixed;
            top: -30px;
            right: 10px;
            z-index: 9999;
            pointer-events: none;
            animation: float 7s ease-in-out infinite 1s;
            filter: drop-shadow(0 0 15px rgba(255, 215, 0, 0.6));
        }

        /* 灯笼主体 - 经典中国红 */
        .deng-box1 .deng,
        .deng {
            position: relative;
            width: 140px;
            height: 110px;
            margin: 50px;
            background: #d8000f;
            border-radius: 50% 50%;
            transform-origin: 50% -120px;
            animation: swing 3s infinite ease-in-out;
            box-shadow: -5px 5px 60px 8px rgba(250, 108, 0, 0.6),
                        0 0 20px rgba(255, 255, 0, 0.4) inset;
            transition: all 0.3s;
            cursor: pointer;
        }

        .deng:hover {
            transform: scale(1.08);
            box-shadow: -5px 5px 70px 10px rgba(250, 108, 0, 0.7),
                        0 0 30px rgba(255, 255, 0, 0.5) inset;
            filter: brightness(1.1);
        }

        .deng-box1 .deng {
            animation: swing 5s infinite ease-in-out;
        }

        /* 灯笼内部装饰 */
        .deng-a {
            position: relative;
            width: 120px;
            height: 110px;
            background: rgba(216, 0, 15, 0.1);
            margin: 15px 8px 8px 8px;
            border-radius: 50% 50%;
            border: 2px solid #dc8f03;
            box-shadow: 0 0 12px rgba(255, 215, 0, 0.5) inset;
            overflow: hidden;
        }

        .deng-a:before {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: radial-gradient(circle at center, transparent 30%, rgba(255, 215, 0, 0.3) 100%);
            border-radius: 50%;
        }

        .deng-b {
            position: relative;
            width: 55px;
            height: 110px;
            background: rgba(216, 0, 15, 0.1);
            margin: -4px 8px 8px 32px;
            border-radius: 50% 50%;
            border: 2px solid #dc8f03;
            box-shadow: 0 0 12px rgba(255, 215, 0, 0.5) inset;
            overflow: hidden;
        }

        .deng-b:before {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: radial-gradient(circle at center, transparent 30%, rgba(255, 215, 0, 0.3) 100%);
            border-radius: 50%;
        }

        /* 灯笼挂绳 */
        .xian {
            position: absolute;
            top: -25px;
            left: 70px;
            width: 2px;
            height: 25px;
            background: linear-gradient(to bottom, #dc8f03, #f5d742);
            box-shadow: 0 0 4px rgba(255, 215, 0, 0.6);
        }

        /* 灯笼穗子 - 金色渐变 */
        .shui-a {
            position: relative;
            width: 5px;
            height: 25px;
            margin: -5px 0 0 67px;
            animation: swing 4s infinite ease-in-out;
            transform-origin: 50% -50px;
            background: linear-gradient(to bottom, #dc8f03, #ffcc00);
            border-radius: 0 0 5px 5px;
        }

        .shui-b {
            position: absolute;
            top: 16px;
            left: -2px;
            width: 10px;
            height: 10px;
            background: #dc8f03;
            border-radius: 50%;
            box-shadow: 0 0 6px #ffcc00;
        }

        .shui-c {
            position: absolute;
            top: 20px;
            left: -2px;
            width: 10px;
            height: 45px;
            background: linear-gradient(to bottom, #dc8f03, #ffcc00);
            border-radius: 0 0 0 5px;
        }

        /* 灯笼顶部和底部装饰 */
        .deng:before {
            position: absolute;
            top: -7px;
            left: 34px;
            height: 12px;
            width: 70px;
            content: " ";
            display: block;
            z-index: 999;
            border-radius: 5px 5px 0 0;
            border: solid 2px #dc8f03;
            background: linear-gradient(to right, #dc8f03, #ffa500, #dc8f03);
            box-shadow: 0 0 10px rgba(255, 215, 0, 0.7);
        }

        .deng:after {
            position: absolute;
            bottom: -7px;
            left: 10px;
            height: 12px;
            width: 70px;
            content: " ";
            display: block;
            margin-left: 25px;
            border-radius: 0 0 5px 5px;
            border: solid 2px #dc8f03;
            background: linear-gradient(to right, #dc8f03, #ffa500, #dc8f03);
            box-shadow: 0 0 10px rgba(255, 215, 0, 0.7);
        }

        /* 灯笼文字 - 经典红色 */
        .deng-t {
            font-family: "华文行楷", "楷体", Arial, sans-serif;
            font-size: 3.8rem;
            color: #ffd700;
            text-shadow: 0 0 12px #D8000F;
            font-weight: bold;
            line-height: 105px;
            text-align: center;
            user-select: none;
        }

        /* 灯笼光晕效果 - 金色 */
        .light-effect {
            position: fixed;
            width: 200px;
            height: 200px;
            border-radius: 50%;
            background: radial-gradient(circle at center, rgba(255, 215, 0, 0.5) 0%, transparent 70%);
            filter: blur(25px);
            z-index: -1;
            pointer-events: none;
            opacity: 0;
            animation: lightPulse 3s infinite ease-in-out;
        }

        /* 高亮节日文字元素 - 红色 */
        .festival-text {
            position: fixed;
            font-family: "华文行楷", "楷体", sans-serif;
            font-size: 4rem;
            color: #d8000f;
            text-shadow: 0 0 10px #ffd700;
            animation: floatText 30s infinite ease-in-out;
            opacity: 0;
            z-index: -1;
            pointer-events: none;
            font-weight: bold;
            transition: opacity 2s ease-in-out;
        }

        /* 节日祝福语 */
        .greeting {
            position: fixed;
            bottom: 30px;
            left: 0;
            width: 100%;
            text-align: center;
            font-family: "华文行楷", "楷体", sans-serif;
            font-size: 3rem;
            color: #d8000f;
            text-shadow: 0 0 15px #ffd700;
            z-index: 9999;
            pointer-events: none;
            animation: textGlow 3s infinite alternate;
        }

        /* 灯笼点击效果 - 金色 */
        .click-effect {
            position: fixed;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background: radial-gradient(circle, rgba(255, 215, 0, 0.7) 0%, rgba(255, 215, 0, 0) 70%);
            animation: clickEffect 1s ease-out forwards;
            pointer-events: none;
            z-index: 9999;
        }

        /* 灯笼粒子效果 - 金色 */
        .lantern-particle {
            position: fixed;
            width: 5px;
            height: 5px;
            border-radius: 50%;
            background: rgba(255, 215, 0, 0.7);
            box-shadow: 0 0 8px #ffd700;
            animation: particleFloat 4s linear infinite;
            pointer-events: none;
            z-index: -1;
        }

        /* 鞭炮效果 */
        .firecracker {
            position: fixed;
            width: 6px;
            height: 18px;
            background: linear-gradient(to bottom, #ff0000, #ff6600);
            border-radius: 2px;
            z-index: 9999;
            animation: firecrackerFall 1s ease-in forwards;
        }

        .explosion {
            position: fixed;
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: radial-gradient(circle, #ff6600, #ff0000);
            box-shadow: 0 0 15px #ff6600;
            z-index: 9999;
            animation: explosion 0.5s ease-out forwards;
        }

        .explosion-particle {
            position: fixed;
            width: 3px;
            height: 3px;
            border-radius: 50%;
            background: #ffcc00;
            box-shadow: 0 0 6px #ffcc00;
            z-index: 9999;
            animation: explosionParticle 1s ease-out forwards;
        }

        .paper-fragment {
            position: fixed;
            width: 3px;
            height: 5px;
            background: linear-gradient(to bottom, rgba(255, 0, 0, 0.8), rgba(255, 204, 0, 0.6));
            border-radius: 2px 5px;
            z-index: 9999;
            animation: fragmentFall 1.5s ease-in forwards;
            transform-origin: center;
            box-shadow: 0 0 4px rgba(255, 0, 0, 0.5);
        }

        /* 动画效果 */
        @keyframes swing {
            0% {
                transform: rotate(-10deg);
            }
            50% {
                transform: rotate(10deg);
            }
            100% {
                transform: rotate(-10deg);
            }
        }

        @keyframes float {
            0%, 100% {
                transform: translateY(0);
            }
            50% {
                transform: translateY(-20px);
            }
        }

        @keyframes clickEffect {
            0% {
                transform: scale(0.5);
                opacity: 1;
            }
            100% {
                transform: scale(3);
                opacity: 0;
            }
        }

        @keyframes floatText {
            0%, 100% {
                transform: translate(var(--startX), var(--startY)) rotate(var(--rotate)) scale(1);
                opacity: 0;
            }
            20%, 80% {
                opacity: 0.8;
            }
            50% {
                transform: translate(var(--midX), var(--midY)) rotate(var(--rotate)) scale(1.1);
            }
        }

        @keyframes particleFloat {
            0% {
                transform: translate(0, 0) scale(1);
                opacity: 0;
            }
            10% {
                opacity: 1;
            }
            90% {
                opacity: 1;
            }
            100% {
                transform: translate(var(--px), var(--py)) scale(0);
                opacity: 0;
            }
        }

        @keyframes firecrackerFall {
            0% {
                transform: translateY(-150px) rotate(0deg);
                opacity: 1;
            }
            100% {
                transform: translateY(0) rotate(360deg);
                opacity: 1;
            }
        }

        @keyframes explosion {
            0% {
                transform: scale(0.5);
                opacity: 1;
            }
            100% {
                transform: scale(12);
                opacity: 0;
            }
        }

        @keyframes explosionParticle {
            0% {
                transform: translate(0, 0) scale(1);
                opacity: 1;
            }
            100% {
                transform: translate(var(--px), var(--py)) scale(0);
                opacity: 0;
            }
        }

        @keyframes fragmentFall {
            0% {
                transform: translate(0, 0) rotate(0deg) scale(1);
                opacity: 1;
            }
            100% {
                transform: translate(var(--px), var(--py)) rotate(var(--rotate)) scale(0.3);
                opacity: 0;
            }
        }

        @keyframes lightPulse {
            0%, 100% {
                opacity: 0.3;
                transform: scale(0.9);
            }
            50% {
                opacity: 0.6;
                transform: scale(1.1);
            }
        }

        @keyframes textGlow {
            0% {
                text-shadow: 0 0 10px #ffd700;
            }
            100% {
                text-shadow: 0 0 25px #ffd700;
            }
        }

        /* 响应式调整 */
        @media (max-width: 768px) {
            .deng-box, .deng-box1 {
                transform: scale(0.7);
            }

            .greeting {
                font-size: 2.2rem;
            }

            .festival-text {
                font-size: 3rem;
            }

            .deng {
                width: 120px;
                height: 90px;
            }

            .deng-t {
                font-size: 3.2rem;
                line-height: 85px;
            }
        }
    `;
    document.head.appendChild(style);

    // 经典节日文字
    const texts = ['福', '禄', '寿', '喜', '财', '吉', '祥', '春', '节', '乐'];

    // 添加高亮节日文字元素
    function createFestivalTexts() {
        for (let i = 0; i < 15; i++) {
            const text = document.createElement('div');
            text.className = 'festival-text';
            text.textContent = texts[Math.floor(Math.random() * texts.length)];

            // 随机起始位置
            const startX = Math.random() * window.innerWidth;
            const startY = Math.random() * window.innerHeight;
            text.style.left = `${startX}px`;
            text.style.top = `${startY}px`;

            // 随机运动路径
            const midX = startX + (Math.random() - 0.5) * 300;
            const midY = startY + (Math.random() - 0.5) * 300;

            text.style.setProperty('--startX', '0px');
            text.style.setProperty('--startY', '0px');
            text.style.setProperty('--midX', `${midX - startX}px`);
            text.style.setProperty('--midY', `${midY - startY}px`);
            text.style.setProperty('--rotate', `${Math.random() * 30 - 15}deg`);

            // 随机动画时间
            const duration = Math.random() * 20 + 25;
            text.style.animationDuration = `${duration}s`;

            // 随机延迟
            text.style.animationDelay = `${Math.random() * 8}s`;

            // 随机大小
            const size = Math.random() * 2 + 3;
            text.style.fontSize = `${size}rem`;

            document.body.appendChild(text);

            // 随机显示/隐藏
            animateTextFade(text);
        }
    }

    // 文字淡入淡出动画
    function animateTextFade(text) {
        let isVisible = false;
        const minDelay = 3000;
        const maxDelay = 8000;

        function toggleVisibility() {
            isVisible = !isVisible;
            text.style.opacity = isVisible ? '0.8' : '0';

            const nextDelay = Math.random() * (maxDelay - minDelay) + minDelay;
            setTimeout(toggleVisibility, nextDelay);
        }

        // 初始延迟
        const initialDelay = Math.random() * 5000;
        setTimeout(toggleVisibility, initialDelay);
    }

    // 创建鞭炮爆炸效果
    function createFirecrackerExplosion(x, y) {
        // 创建鞭炮下落效果 - 从当前位置上方150px处落下
        const firecracker = document.createElement('div');
        firecracker.className = 'firecracker';
        firecracker.style.left = `${x}px`;
        firecracker.style.top = `${y - 150}px`;
        document.body.appendChild(firecracker);

        // 鞭炮落地后爆炸
        setTimeout(() => {
            firecracker.remove();

            // 创建爆炸中心
            const explosion = document.createElement('div');
            explosion.className = 'explosion';
            explosion.style.left = `${x - 4}px`;
            explosion.style.top = `${y - 4}px`;
            document.body.appendChild(explosion);

            // 创建爆炸粒子
            for (let i = 0; i < 20; i++) {
                const particle = document.createElement('div');
                particle.className = 'explosion-particle';
                particle.style.left = `${x}px`;
                particle.style.top = `${y}px`;

                // 随机运动方向
                const px = (Math.random() - 0.5) * 100;
                const py = (Math.random() - 0.5) * 100;
                particle.style.setProperty('--px', `${px}px`);
                particle.style.setProperty('--py', `${py}px`);

                document.body.appendChild(particle);

                // 移除粒子
                setTimeout(() => {
                    particle.remove();
                }, 1000);
            }

            // 创建爆炸碎片
            for (let i = 0; i < 20; i++) {
                const fragment = document.createElement('div');
                fragment.className = 'paper-fragment';
                fragment.style.left = `${x}px`;
                fragment.style.top = `${y}px`;

                // 随机运动方向
                const px = (Math.random() - 0.5) * 100;
                const py = Math.random() * 100 + 50;
                fragment.style.setProperty('--px', `${px}px`);
                fragment.style.setProperty('--py', `${py}px`);
                fragment.style.setProperty('--rotate', `${Math.random() * 360}deg`);

                document.body.appendChild(fragment);

                // 移除碎片
                setTimeout(() => {
                    fragment.remove();
                }, 1500);
            }

            // 移除爆炸中心
            setTimeout(() => {
                explosion.remove();
            }, 500);

        }, 1000);
    }

    // 随机生成鞭炮爆炸 - 修改后的版本
    function randomFirecracker() {
        // 在整个页面范围内随机位置
        const x = Math.random() * window.innerWidth;
        const y = Math.random() * window.innerHeight;

        // 确保鞭炮不会太靠近边缘
        const margin = 50;
        const adjustedX = Math.max(margin, Math.min(x, window.innerWidth - margin));
        const adjustedY = Math.max(margin, Math.min(y, window.innerHeight - margin));

        createFirecrackerExplosion(adjustedX, adjustedY);

        // 随机下次爆炸时间
        const nextDelay = Math.random() * 3000 + 2000;
        setTimeout(randomFirecracker, nextDelay);
    }

    // 创建灯笼粒子效果
    function createLanternParticles(x, y, count = 10) {
        for (let i = 0; i < count; i++) {
            const particle = document.createElement('div');
            particle.className = 'lantern-particle';

            particle.style.left = `${x}px`;
            particle.style.top = `${y}px`;

            // 随机运动方向
            const px = (Math.random() - 0.5) * 200;
            const py = (Math.random() - 0.5) * 200;
            particle.style.setProperty('--px', `${px}px`);
            particle.style.setProperty('--py', `${py}px`);

            // 随机大小
            const size = Math.random() * 3 + 3;
            particle.style.width = `${size}px`;
            particle.style.height = `${size}px`;

            // 随机动画时间
            const duration = Math.random() * 2 + 3;
            particle.style.animationDuration = `${duration}s`;

            document.body.appendChild(particle);

            // 动画结束后移除
            setTimeout(() => {
                particle.remove();
            }, duration * 1000);
        }
    }

    // 创建灯笼光晕效果
    function createLightEffect(x, y) {
        const light = document.createElement('div');
        light.className = 'light-effect';
        light.style.left = `${x - 100}px`;
        light.style.top = `${y - 100}px`;
        document.body.appendChild(light);

        // 淡出效果
        setTimeout(() => {
            light.style.opacity = '0';
            light.style.transition = 'opacity 1s';

            // 移除元素
            setTimeout(() => {
            light.remove();
            }, 1000);
        }, 800);
    }

    // 创建灯笼点击效果
    function createClickEffect(x, y) {
        const effect = document.createElement('div');
        effect.className = 'click-effect';
        effect.style.left = `${x - 25}px`;
        effect.style.top = `${y - 25}px`;
        document.body.appendChild(effect);

        // 创建粒子效果
        createLanternParticles(x, y, 20);

        // 动画结束后移除
        setTimeout(() => {
            effect.remove();
        }, 1000);
    }

    // 创建灯笼
    const createLantern = (boxClass, text) => {
        const box = document.createElement('div');
        box.className = boxClass;

        const deng = document.createElement('div');
        deng.className = 'deng';

        const xian = document.createElement('div');
        xian.className = 'xian';

        const dengA = document.createElement('div');
        dengA.className = 'deng-a';

        const dengB = document.createElement('div');
        dengB.className = 'deng-b';

        const dengT = document.createElement('div');
        dengT.className = 'deng-t';
        dengT.innerText = text;

        const shuiA = document.createElement('div');
        shuiA.className = 'shui shui-a';

        const shuiC = document.createElement('div');
        shuiC.className = 'shui-c';

        const shuiB = document.createElement('div');
        shuiB.className = 'shui-b';

        dengB.appendChild(dengT);
        dengA.appendChild(dengB);
        shuiA.appendChild(shuiC);
        shuiA.appendChild(shuiB);
        deng.appendChild(xian);
        deng.appendChild(dengA);
        deng.appendChild(shuiA);
        box.appendChild(deng);

        // 添加灯笼点击事件
        deng.addEventListener('click', (e) => {
            createClickEffect(e.clientX, e.clientY);
            createLightEffect(e.clientX, e.clientY);
            createFirecrackerExplosion(e.clientX, e.clientY);
        });

        // 初始粒子效果
        const initialX = box.offsetLeft + 70;
        const initialY = box.offsetTop + 55;
        createLanternParticles(initialX, initialY, 10);
        setInterval(() => {
            createLanternParticles(initialX, initialY, 5);
        }, 4000);

        document.body.appendChild(box);

        // 为灯笼添加光晕效果
        createLightEffect(initialX, initialY);
    };

    // 创建灯笼1 (春)
    createLantern('deng-box', '春');

    // 创建灯笼2 (节)
    createLantern('deng-box1', '节');

    // 添加节日祝福语
    const greeting = document.createElement('div');
    greeting.className = 'greeting';
    greeting.textContent = '新春快乐 万事如意';
    document.body.appendChild(greeting);

    // 创建高亮节日文字
    createFestivalTexts();

    // 开始随机鞭炮爆炸
    setTimeout(randomFirecracker, 2000);

    // 持续更新节日文字位置
    setInterval(() => {
        // 移除屏幕外的文字
        document.querySelectorAll('.festival-text').forEach(text => {
            const rect = text.getBoundingClientRect();
            if (rect.right < 0 || rect.bottom < 0 || 
                rect.left > window.innerWidth || rect.top > window.innerHeight) {
                text.remove();
            }
        });

        // 补充新的文字
        const currentCount = document.querySelectorAll('.festival-text').length;
        if (currentCount < 15) {
            createFestivalTexts();
        }
    }, 5000);
})();