3d粒子玫瑰花
使用前端技术实现不同三色玫瑰花,分别是红色、蓝色、粉色玫瑰花,大家可根据自己需要加一个背景图,也可以修改代码实现更多玫瑰花的不同颜色,没有做所有屏幕尺寸适配,某些屏幕可能需要缩放才能正常显示完整的玫瑰花,有兴趣的可以再做相关调整和修改,代码是公开的。
887bc895b9a8b756d173058764ec708.png
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>全屏完整玫瑰花</title>
        <style>
            html, body {
                margin: 0;
                padding: 0;
                width: 100%%;
                height: 100%%;
                overflow: hidden;
                background: #000;
            }
            canvas {
                display: block;
                position: absolute;
                top: 0;
                left: 0;
                width: 100%%;
                height: 100%%;
            }
        </style>
    </head>

    <body>
        <canvas id="c"></canvas>
    </body>
    <script>
        var b = document.body;
        var c = document.getElementsByTagName('canvas')[0];
        var a = c.getContext('2d');
        
        // 数学函数简写
        with(m = Math) C = cos, S = sin, P = pow, R = random;
        
        // 初始化画布尺寸和内存数组
        var m1 = [], m2 = [], m3 = [];
        var f; // 画布宽度
        var h; // 缩放参数
        
        // 设置画布为全屏并计算适当的缩放参数
        function resizeCanvas() {
            // 获取窗口尺寸
            var windowWidth = window.innerWidth;
            var windowHeight = window.innerHeight;
            
            // 设置画布尺寸
            c.width = f = windowWidth;
            c.height = windowHeight;
            
            // 根据窗口尺寸动态计算缩放参数
            // 窗口越小,h的绝对值越大(花越小)
            var minDimension = Math.min(windowWidth / 3, windowHeight);
            h = -Math.max(300, Math.min(450, 150000 / minDimension));
            
            // 清除画布
            a.fillStyle = "#000";
            a.fillRect(0, 0, c.width, c.height);
            
            // 重置内存数组
            m1 = [];
            m2 = [];
            m3 = [];
            
            // 输出调试信息
            console.log("Window size: " + windowWidth + "x" + windowHeight + ", h=" + h);
        }
        
        // 初始化时设置画布尺寸
        resizeCanvas();
        
        // 监听窗口大小变化,调整画布尺寸
        window.addEventListener('resize', resizeCanvas);
        
        // 玫瑰花生成函数
        function p(a, b, c) {
            if (c > 60) return [S(a * 7) * (13 + 5 / (.2 + P(b * 4, 4))) - S(b) * 50,
                b * 600 + 50, 625 + C(a * 7) * (13 + 5 / (.2 + P(b * 4, 4))) + b * 400, a * 1 - b / 2, a
            ];
            A = a * 2 - 1;
            B = b * 2 - 1;
            if (A * A + B * B < 1) {
                // 花瓣部分 - 增强层次感和生动效果
                if (c > 37) {
                    n = (j = c & 1) ? 6 : 4;
                    // 增加花瓣曲率变化,使花瓣更加立体
                    o = .5 / (a + .01) + C(b * 125) * 3.5 - a * 300;
                    w = b * h;
                    // 增加花瓣的层次变化
                    return [o * C(n) + w * S(n) + j * 610 - 390, o * S(n) - w * C(n) + 550 - j * 350,
                        1180 + C(B + A) * 120 - j * 300, // 增加深度变化
                        // 增强花瓣颜色变化,使其更加生动
                        .45 - a * .12 + P(1 - B * B, -h * 6) * .18 - a * b * .4 + C(a + b) / 4.5 + 
                        P(C((o * (a + 1.1) + (B > 0 ? w : -w)) / 25), 30) * .12 * (1 - B * B) + 
                        S(a * 5) * .05, // 添加细微波纹效果
                        // 增加花瓣色彩饱和度变化
                        o / 1e3 + .75 - o * w * 3e-6 + S(a * 4) * .05
                    ]
                }
                // 叶子部分 - 调整颜色更鲜艳,形状更小
                if (c > 32) {
                    c = c * 1.16 - .15;
                    // 缩小叶子形状,减小系数
                    o = a * 40 - 18; // 原来是 a * 45 - 20
                    // 减小叶子大小
                    w = b * b * h * 0.85; // 添加缩放因子0.85
                    z = o * S(c) + w * C(c) + 620;
                    return [o * C(c) - w * S(c), 
                        // 调整叶子位置和形状
                        28 + C(B * .5) * 90 - b * b * b * 55 - z / 2 - h, 
                        z, 
                        // 增强叶子颜色,使绿色更鲜艳
                        (b * b * .35 + P((1 - (A * A)), 7) * .18 + .32) * b * 1.1, // 增加绿色饱和度
                        // 增强叶子颜色变化
                        b * .85 + S(a * 3) * .08 // 添加色彩变化
                    ]
                }
                // 茎部分 - 略微调整使其更加鲜绿
                o = A * (2 - b) * (80 - c * 2);
                w = 99 - C(A) * 120 - C(b) * (-h - c * 4.9) + C(P(1 - b, 7)) * 50 + c * 2;
                z = o * S(c) + w * C(c) + 700;
                return [o * C(c) - w * S(c), B * 99 - C(P(b, 7)) * 50 - c / 3 - z / 1.35 + 450, z, 
                    // 略微调整茎的颜色
                    (1 - b / 1.2) * .92 + a * .1, 
                    P((1 - b), 20) / 4 + .07 // 增加绿色饱和度
                ]
            }
        }
        
        // 渲染函数
        function render() {
            // 获取窗口尺寸
            var windowWidth = window.innerWidth;
            var windowHeight = window.innerHeight;
            var sectionWidth = windowWidth / 3;
            
            // 计算每个区域的中心点
            var centerX1 = sectionWidth / 2;
            var centerX2 = sectionWidth * 1.5;
            var centerX3 = sectionWidth * 2.5;
            var centerY = windowHeight / 2;
            
            // 计算花朵大小和偏移量
            // 根据屏幕尺寸动态计算,确保花朵完整显示
            var flowerSize = Math.min(sectionWidth, windowHeight) * 0.4;
            var xOffset = 80;
            var yOffset = 120;
            
            // 渲染循环
            for(i=0; i<1.5e4; i++) {
                // 确定绘制区域
                var region = Math.floor(i %% 3);
                
                if(s=p(R(), R(), i%%46/.74)) {
                    z = s[2];
                    
                    // 根据区域选择中心点和偏移
                    var centerX;
                    var currentM;
                    
                    if(region == 0) {
                        centerX = centerX1;
                        currentM = m1;
                    } else if(region == 1) {
                        centerX = centerX2;
                        currentM = m2;
                    } else {
                        centerX = centerX3;
                        currentM = m3;
                    }
                    
                    // 计算坐标,使花朵居中显示
                    // 使用动态计算的偏移量,确保花朵完整显示
                    x = ~~(s[0]*600/z-h) + centerX - xOffset;
                    y = ~~(s[1]*600/z-h) + centerY - yOffset;
                    
                    // 确保坐标在画布范围内
                    if(x >= 0 && x < windowWidth && y >= 0 && y < windowHeight) {
                        // 检查像素是否已绘制,或者当前像素是否更靠前
                        var q = y*f+x;
                        if(!currentM[q] || currentM[q]>z) {
                            currentM[q] = z;
                            
                            // 根据区域选择不同的颜色
                            if(region == 0) {
                                // 红色玫瑰 - 原始颜色
                                a.fillStyle = "rgb("+~(s[3]*h*(1+R()*.1))+","+~(s[4]*h*(1+R()*.08))+","+~(s[3]*s[3]*-85-R()*12)+")";
                            } else if(region == 1) {
                                // 蓝色玫瑰 - 增加蓝色分量,减少红色分量
                                a.fillStyle = "rgb("+~(s[3]*h*0.2*(1+R()*.1))+","+~(s[4]*h*0.4*(1+R()*.08))+","+~(s[3]*h*1.2*(1+R()*.15))+")";
                            } else {
                                // 粉色玫瑰 - 增加红色和蓝色分量
                                a.fillStyle = "rgb("+~(s[3]*h*1.2*(1+R()*.15))+","+~(s[4]*h*0.3*(1+R()*.08))+","+~(s[3]*h*0.9*(1+R()*.1))+")";
                            }
                            
                            a.fillRect(x, y, 1, 1);
                        }
                    }
                }
            }
            
            // 请求下一帧动画
            requestAnimationFrame(render);
        }
        
        // 开始渲染
        render();
    </script>
</html>

本文最后更新时间 2025-06-01
文章链接地址:
https://xzlo.blog/index.php/archives/48/
本站文章除注明[转载|引用|原文]出处外,均为本站原生内容,转载前请注明出处

留言