效果演示

部分源码如下

// 雪花对象构造函数
export default function Snowflake(ctx) {
    /**
     * @type {CanvasRenderingContext2D}
     */
    this.ctx = ctx;
    this.reset();
}

Snowflake.prototype.reset = function () {
    this.x = Math.random() * this.ctx.canvas.width;
    this.y = -10;
    this.radius = Math.random() * 3 + 1; // 半径1-4
    this.speed = Math.random() * 2 + 1;  // 下落速度1-3
    this.sway = Math.random() * 2;       // 左右摆动幅度
    this.swayAngle = Math.random() * Math.PI * 2; // 摆动角度
};

Snowflake.prototype.update = function () {
    this.y += this.speed;
    this.swayAngle += 0.01;
    this.x += Math.sin(this.swayAngle) * this.sway;

    // 超出屏幕则重置
    if (this.y > this.ctx.canvas.height + 10) {
        this.reset();
    }
};

Snowflake.prototype.draw = function () {
    this.ctx.beginPath();
    this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    this.ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
    this.ctx.shadowColor = 'white';
    this.ctx.shadowBlur = 5;
    this.ctx.fill();
};