jparticles
Version:
A lightweight, efficient and easy-to-use Canvas library for building some cool particle effects.
195 lines (194 loc) • 7.55 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var shape_1 = __importDefault(require("./common/shape"));
var utils_1 = require("./utils/index");
var constants_1 = require("./common/constants");
var Snow = /** @class */ (function (_super) {
__extends(Snow, _super);
function Snow(selector, options) {
var _this = _super.call(this, Snow.defaultConfig, selector, options) || this;
// 下雪的开始时间
_this.startTime = Date.now();
// 当存在持续时间参数时,雪花是否全部降落
_this.isFinished = false;
_this.bootstrap();
return _this;
}
/**
* 初始化数据和运行程序
*/
Snow.prototype.init = function () {
this.createSnowflakes();
};
/**
* 创建单个雪花,包含大小、位置、速度等信息
*/
Snow.prototype.createSnowflake = function () {
var _a = this.options, maxR = _a.maxR, minR = _a.minR, maxSpeed = _a.maxSpeed, minSpeed = _a.minSpeed, spin = _a.spin, spinMaxSpeed = _a.spinMaxSpeed, spinMinSpeed = _a.spinMinSpeed;
var r = utils_1.randomInRange(maxR, minR);
return {
r: r,
x: Math.random() * this.canvasWidth,
y: -r,
vx: utils_1.randomSpeed(maxSpeed, minSpeed),
// 半径越大,垂直速度越快,这样比较有近快远慢的层次效果
vy: Math.abs(r * utils_1.randomSpeed(maxSpeed, minSpeed)),
color: this.getColor(),
swingAt: Date.now(),
shape: this.getShapeData(),
// 定义粒子的旋转角度
rotate: spin ? utils_1.randomInRange(0, 360) : 0,
// 粒子的旋转速度
rotateSpeed: utils_1.randomSpeed(spinMaxSpeed, spinMinSpeed),
};
};
/**
* 随机创建雪花
*/
Snow.prototype.createSnowflakes = function () {
var count = Math.max(0, Math.ceil(Math.random() * this.options.num));
while (count--) {
this.elements.push(this.createSnowflake());
}
};
/**
* 绘图
* 设计一种模式(解耦逻辑混杂),当触发 resize 事件调用 draw 方法时:
* 如果是暂停 -> 调用 elements 的重新绘制 drawShape()
* 如果是运动中 -> 正常逻辑,内部不考虑暂停逻辑
*/
Snow.prototype.draw = function () {
var _this = this;
var _a = this, canvasWidth = _a.canvasWidth, canvasHeight = _a.canvasHeight, isPaused = _a.isPaused;
var _b = this.options, maxR = _b.maxR, swing = _b.swing, swingInterval = _b.swingInterval, swingProbability = _b.swingProbability, duration = _b.duration;
this.clearCanvasAndSetGlobalAttrs();
this.elements.forEach(function (snowflake, i, array) {
var x = snowflake.x, y = snowflake.y, r = snowflake.r;
// 更新旋转角度
_this.updateElementRotate(snowflake);
_this.drawShape(snowflake);
// 暂停(isPaused)且窗口改变(resize)的时候也会调用绘图方法
// 所以需要运动的判断需要在内部
if (isPaused) {
return;
}
snowflake.x += snowflake.vx;
snowflake.y += snowflake.vy;
// 变换飘落方向,根据一定的几率
if (swing &&
Date.now() - snowflake.swingAt > swingInterval &&
// 半径越小,变换几率越小
Math.random() < (r / maxR) * swingProbability) {
snowflake.swingAt = Date.now();
snowflake.vx *= -1;
}
if (x + r < 0 || x - r > canvasWidth) {
// 雪花从侧边出去 => 删除
// 有持续时间 ? 不添加 : 添加一个新雪花
duration
? array.splice(i, 1)
: array.splice(i, 1, _this.createSnowflake());
}
else if (y - r > canvasHeight) {
// 雪花从底部出去 => 删除
array.splice(i, 1);
}
});
if (isPaused) {
return;
}
// 当有 duration 参数时,判断持续时间是否用完
// 没有 duration 参数时,一直可用
var timeEnd = duration ? Date.now() - this.startTime > duration : false;
if (!timeEnd && Math.random() > 0.9) {
// 添加雪花
this.createSnowflakes();
}
if (this.elements.length) {
this.requestAnimationFrame();
}
else {
this.isFinished = true;
this.eventEmitter.trigger(constants_1.EVENT_NAMES_SNOW.FINISHED);
}
};
/**
* 更新元素自旋数据
*/
Snow.prototype.updateElementRotate = function (element) {
if (!this.options.spin || this.isPaused) {
return;
}
// 更新旋转角度
element.rotate += element.rotateSpeed;
// 大于等于 360 度时,回到 0-360 范围,避免变量数值一直累计超过 MAX_SAFE_INTEGER
if (element.rotate >= 360) {
element.rotate = element.rotate - 360;
}
};
/**
* 方法:当存在持续时间时,再次下雪
*/
Snow.prototype.fallAgain = function () {
if (this.isRunningSupported &&
!this.isCanvasRemoved &&
!this.isPaused &&
this.isFinished) {
this.isFinished = false;
this.startTime = Date.now();
this.createSnowflakes();
this.draw();
}
};
/**
* 事件:当存在持续时间时,雪花全部降落后触发的事件
*/
Snow.prototype.onFinished = function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
(_a = this.eventEmitter).on.apply(_a, __spreadArray([constants_1.EVENT_NAMES_SNOW.FINISHED], args));
return this;
};
Snow.defaultConfig = {
num: 6,
color: '#fff',
maxR: 6.5,
minR: 0.5,
maxSpeed: 0.6,
minSpeed: 0.1,
swing: true,
swingInterval: 2000,
swingProbability: 0.06,
spin: false,
spinMaxSpeed: 5,
spinMinSpeed: 1,
};
return Snow;
}(shape_1.default));
exports.default = Snow;