Canvas背景动画(一) 粒子矩阵特效

Canvas背景动画(一) 粒子矩阵特效

  1. 效果演示:
    粒子矩阵光影流动效果
  2. 代码附上
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>canvas背景动画一</title>
        <style>
            canvas {
                position: absolute;
                top: 0;
                left: 0;
            }
        </style>
    </head>

    <body>
        <canvas id="canvasBox"></canvas>

        <script type="text/javascript">
		var c = document.getElementById('canvasBox')
            var w = (c.width = window.innerWidth),
                h = (c.height = window.innerHeight),
                ctx = c.getContext("2d"),
                opts = {
                    len: 50, // 长度 定义基础模块大小
                    count: 50, // 粒子数量
                    baseTime: 10, // 粒子基础运动时间
                    addedTime: 10, // 新增粒子间隔
                    dieChance: 0.05, // 粒子随机消散
                    spawnChance: 1, // 火花比例
                    sparkChance: 0.1, // 火花产随机数
                    sparkDist: 10, // 火花区域
                    sparkSize: 2 ,// 火花大小
                    color: "hsl(hue,100%,light%)", // 颜色系数(色相、饱和度、亮度)
                    baseLight: 50, // 光源开始数值
                    addedLight: 10, //新增光源间隔
                    shadowToTimePropMult: 6, // 阴影显示时间比例
                    baseLightInputMultiplier: 0.01, // 光源初始系数
                    addedLightInputMultiplier: 0.02,// 新增光源初始系数
                    cx: w / 2,
                    cy: h / 2,
                    repaintAlpha: 0.04, // 重绘粒子系数
                    hueChange: 0.1, // 颜色色相变化系数
                },
                tick = 0, // 初始色相值
                lines = [], // 线路数组
                dieX = w / 2 / opts.len,
                dieY = h / 2 / opts.len,
                baseRad = (Math.PI * 2) / 6;
            ctx.fillStyle = "black";
            ctx.fillRect(0, 0, w, h);

            function loop() {
                window.requestAnimationFrame(loop);
                ++tick;
                ctx.globalCompositeOperation = "source-over";
                ctx.shadowBlur = 0;
                ctx.fillStyle = "rgba(0,0,0,alp)".replace(
                    "alp",
                    opts.repaintAlpha
                );
                ctx.fillRect(0, 0, w, h);
                ctx.globalCompositeOperation = "lighter";
                if (
                    lines.length < opts.count &&
                    Math.random() < opts.spawnChance
                )
                    lines.push(new Line());
                lines.map(function (line) {
                    line.step();
                });
            }

            function Line() {
                this.reset();
            }
            Line.prototype.reset = function () {
                this.x = 0;
                this.y = 0;
                this.addedX = 0;
                this.addedY = 0;
                this.rad = 0;
                this.lightInputMultiplier =
                    opts.baseLightInputMultiplier +
                    opts.addedLightInputMultiplier * Math.random();
                this.color = opts.color.replace("hue", tick * opts.hueChange);
                this.cumulativeTime = 0;
                this.beginPhase();
            };
            Line.prototype.beginPhase = function () {
                this.x += this.addedX;
                this.y += this.addedY;
                this.time = 0;
                this.targetTime =
                    (opts.baseTime + opts.addedTime * Math.random()) | 0;
                this.rad += baseRad * (Math.random() < 0.5 ? 1 : -1);
                this.addedX = Math.cos(this.rad);
                this.addedY = Math.sin(this.rad);
                if (
                    Math.random() < opts.dieChance ||
                    this.x > dieX ||
                    this.x < -dieX ||
                    this.y > dieY ||
                    this.y < -dieY
                )
                    this.reset();
            };
            Line.prototype.step = function () {
                ++this.time;
                ++this.cumulativeTime;
                if (this.time >= this.targetTime) this.beginPhase();
                var prop = this.time / this.targetTime,
                    wave = Math.sin((prop * Math.PI) / 2),
                    x = this.addedX * wave,
                    y = this.addedY * wave;
                ctx.shadowBlur = prop * opts.shadowToTimePropMult;
                ctx.fillStyle = ctx.shadowColor = this.color.replace(
                    "light",
                    opts.baseLight +
                        opts.addedLight *
                            Math.sin(
                                this.cumulativeTime * this.lightInputMultiplier
                            )
                );
                ctx.fillRect(
                    opts.cx + (this.x + x) * opts.len,
                    opts.cy + (this.y + y) * opts.len,
                    2,
                    2
                );
                if (Math.random() < opts.sparkChance)
                    ctx.fillRect(
                        opts.cx +
                            (this.x + x) * opts.len +
                            Math.random() *
                                opts.sparkDist *
                                (Math.random() < 0.5 ? 1 : -1) -
                            opts.sparkSize / 2,
                        opts.cy +
                            (this.y + y) * opts.len +
                            Math.random() *
                                opts.sparkDist *
                                (Math.random() < 0.5 ? 1 : -1) -
                            opts.sparkSize / 2,
                        opts.sparkSize,
                        opts.sparkSize
                    );
            };
            loop();
            window.addEventListener("resize", function () {
                w = c.width = window.innerWidth;
                h = c.height = window.innerHeight;
                ctx.fillStyle = "black";
                ctx.fillRect(0, 0, w, h);
                opts.cx = w / 2;
                opts.cy = h / 2;
                dieX = w / 2 / opts.len;
                dieY = h / 2 / opts.len;
            });
        </script>
    </body>
</html>

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值