冰雪奇缘魔法特效

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            overflow: hidden;
        }
        
        #canvas {
            background: #000;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
    <script src="./js/proton.min.js"></script>
    <script>
        // 获取canvs
        const canvas = document.getElementById("canvas");

        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        // 创建proton实例
        const proton = new Proton();

        // 创建主魔法线条
        const emitter1 = createEmitter();
        // 存活时间2
        emitter1.totalTime = 2;

        // 添加到proton中
        proton.addEmitter(emitter1);

        //创建canvas renderer
        const renderer = new Proton.CanvasRenderer(canvas);
        // 添加renderer
        proton.addRenderer(renderer);

        // 初始化主魔法线的变动函数
        let changeEmitter1 = changePosition(emitter1, Math.PI / 3.4);

        // 第二条魔法线出现的标志
        let flag = true;
        // 第三条魔法线出现的标志
        let flag2 = true;

        // 第二条魔法线
        let emitter2 = null;
        // 第三条魔法线
        let emitter3 = null;
        // 第二条魔法线变动函数
        let changeEmitter2 = null;
        // 第三条魔法线的变动函数
        let changeEmitter3 = null;

        // let theta = 0;
        // let a = 1000;

        // 初始化画布绘画循环
        function draw() {
            window.requestAnimationFrame(draw);

            // 发动第一条魔法线
            changeEmitter1.moveClockWise();

            // 在第一条魔法线发动的0.35秒后发动第二条
            if (emitter1.emitTime > 0.35 && flag) {
                emitter2 = createEmitter();
                emitter2.totalTime = 0.3;
                changeEmitter2 = changePosition(
                    emitter2,
                    changeEmitter1.get().theta,
                    0,
                    emitter1.p.x,
                    emitter1.p.y
                );
                proton.addEmitter(emitter2);
                flag = false;
            }

            // 如果第二条魔法线已经初始化完成
            if (emitter2 && changeEmitter2) {
                changeEmitter2.moveStyle1();
            }

            // 在第一条魔法线发动的0.8秒后发动第三条
            if (emitter1.emitTime > 0.8 && flag2) {
                emitter3 = createEmitter();
                emitter3.totalTime = 1.2;
                changeEmitter3 = changePosition(
                    emitter3, -1.2,
                    0,
                    emitter1.p.x,
                    emitter1.p.y
                );
                proton.addEmitter(emitter3);
                flag2 = false;
            }

            // 如果第三条魔法线已经初始化完成
            if (emitter3 && changeEmitter3) {
                changeEmitter3.moveStyle2();
            }

            // theta += 0.1;
            // a -= 1;

            // emitter.p.x = (a * Math.cos(theta)) / theta + canvas.width / 2;
            // emitter.p.y = (a * Math.sin(theta)) / theta + canvas.height / 2;

            proton.update();
        }

        draw();

        /**
         * 定义魔法线变化函数
         * @param {*} emitter
         * @param {*} theta 角度
         * @param {*} a y轴变化参数
         * @param {*} x 起始x坐标
         * @param {*} y 起始y坐标
         */
        function changePosition(emitter, theta = Math.PI / 2, a = 600, x, y) {
            return {
                // 第一条魔法线变化样式
                moveClockWise: () => {
                    theta += 0.1;
                    theta *= 1.001;
                    a -= 4;
                    emitter.p.x = (a * Math.cos(theta)) / theta + canvas.width / 2;
                    emitter.p.y = (a * Math.sin(theta)) / theta + canvas.height / 2;
                },
                // 第二条魔法线变化样式
                moveStyle1: () => {
                    theta -= 0.05;
                    a -= 20;
                    emitter.p.x = -(a * Math.cos(theta)) / theta + x;
                    emitter.p.y = (a * Math.sin(theta)) / theta + y;
                },
                // 第三条魔法线变化样式
                moveStyle2: () => {
                    theta -= 0.03;

                    a -= 20;
                    emitter.p.x = -(a * Math.cos(theta)) / theta + x;
                    emitter.p.y = (a * Math.sin(theta)) / theta + y;
                },

                // 获取当前魔法线的角度和y轴变化参数,用于确定后边出现的魔法线的位置
                get: () => {
                    return {
                        theta,
                        a
                    };
                }
            };
        }

        /**
         * 创建emitter
         */
        function createEmitter() {
            const emitter = new Proton.Emitter();
            // 每多少秒发射几颗粒子,particle
            emitter.rate = new Proton.Rate(new Proton.Span(2, 8), 0.01);

            // emitter.addInitialize(new Proton.Position(new Proton.CircleZone(0, 0, 1, 1)));
            // 质量
            emitter.addInitialize(new Proton.Mass(1));
            // 半径
            emitter.addInitialize(new Proton.Radius(1, 3));
            // 生命
            emitter.addInitialize(new Proton.Life(2));
            // 速度
            emitter.addInitialize(
                new Proton.Velocity(
                    new Proton.Span(-0.2, 0.2),
                    new Proton.Span(0, 180),
                    "polar"
                )
            );

            // 每个particle的颜色行为
            emitter.addBehaviour(new Proton.Color("#ffffff"));
            // 透明度从10 变化
            emitter.addBehaviour(new Proton.Alpha(1, 0));
            // 大小从0.6倍到0.4
            emitter.addBehaviour(new Proton.Scale(0.6, 0.4));

            // 起始位置
            emitter.p.x = canvas.width / 2;
            emitter.p.y = canvas.height / 2;

            // 发射
            emitter.emit();
            return emitter;
        }
    </script>

</body>

</html>

proton.js下载:

https://download.csdn.net/download/weixin_45932157/88767967

效果图:

在这里插入图片描述

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你的美,让我痴迷

你的好,我会永远记住你的。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值