initial commit

This commit is contained in:
yhl452493373
2021-12-16 13:31:42 +08:00
parent d57e6a739c
commit 762eedcff8
4 changed files with 386 additions and 1 deletions

299
js/particle.js Executable file
View File

@@ -0,0 +1,299 @@
;
/*
* 原项目地址:https://github.com/AnCIity/ui-login-canvas
* 原作者:AnCity
* 修改:yhl452493373
* 不依赖外部库仅使用canvas
*/
(function () {
/**
* 生成颜色范围内随机色
* https://stackoverflow.com/questions/25193110/random-color-between-two-selected-rgb-colors-javascript 最下方答案
* @param color1 颜色1
* @param color2 颜色2
* @private
*/
var randomColor = function (color1, color2) {
this.regs = {
"hex3": /^#([a-f\d])([a-f\d])([a-f\d])$/i,
"hex6": /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,
"rgb": /^rgb\s*\(\s*([\d.]+%?)\s*,\s*([\d.]+%?)\s*,\s*([\d.]+%?)\s*\)$/
};
this.colorObject1 = this.getValues(color1);
this.colorObject2 = this.getValues(color2);
}
/**
* 将传颜色字符串转为带rgb数值的对象
* @param color 颜色
* @returns 转换结果若为false则转换失败说明颜色字符串错误
*/
randomColor.prototype.getValues = function (color) {
var values = false;
for (var prop in this.regs) {
// noinspection JSUnfilteredForInLoop
if (this.regs[prop].test(color)) {
values = {};
// noinspection JSUnfilteredForInLoop
values.r = color.replace(this.regs[prop], "$1");
// noinspection JSUnfilteredForInLoop
values.g = color.replace(this.regs[prop], "$2");
// noinspection JSUnfilteredForInLoop
values.b = color.replace(this.regs[prop], "$3");
if (prop === "rgb") {
values.r = Number(values.r);
values.g = Number(values.g);
values.b = Number(values.b);
} else {
values.r = parseInt(values.r, 16);
values.g = parseInt(values.g, 16);
values.b = parseInt(values.b, 16);
}
break;
}
}
return values;
}
/**
* 生成随机色
* @returns {string|boolean}
*/
randomColor.prototype.getColor = function () {
if (this.colorObject1 && this.colorObject2) {
var random = Math.random();
var r = randomColor.getRandom(this.colorObject1.r, this.colorObject2.r, random);
var g = randomColor.getRandom(this.colorObject1.g, this.colorObject2.g, random);
var b = randomColor.getRandom(this.colorObject1.b, this.colorObject2.b, random);
return "#" + r + g + b;
}
return false;
};
/**
* 字符串补位如将a左侧补位变为0a
*
* @param str 需要补位的字符串
* @param pad_length 补位后字符串的长度
* @param pad_string 用于补位的字符串
* @param pad_type 补位方式
* @returns {string|*}
* @private
*/
randomColor.str_pad = function (str, pad_length, pad_string, pad_type) {
var len = pad_length - str.length;
if (len < 0) {
return str
}
var pad = new Array(len + 1).join(pad_string);
if (pad_type === "STR_PAD_LEFT") {
return pad + str
}
return str + pad;
}
/**
* 获取RGB其中之一随机色范围
* @param color1 颜色1 RGB其中之一
* @param color2 颜色2 RGB其中之一
* @param percent 随机到的范围百分比
* @returns {string|*}
* @private
*/
randomColor.getRandom = function (color1, color2, percent) {
var color = color1 + Math.floor((color2 - color1) * percent);
if (color < 0)
color = 0;
return randomColor.str_pad(color.toString(16), 2, "0", "STR_PAD_LEFT");
}
/**
* 定义插件对象
*
* @param options {{
* canvas:HTMLCanvasElement
* width:number?,
* height:number?,
* ballNumber:number,
* ballMinSize:number,
* ballMaxSize:number,
* fps:number,
* color:string|[string,string]
* }}
*/
var particle = function (options) {
this.ball = [];
this.canvas = options.canvas;
if (this.canvas.style.width !== '' || this.canvas.style.height !== '') {
throw new Error('请勿在粒子动效的canvas上的style中添加width仅允许通过参数传递')
} else if (this.canvas.getAttribute('width') != null || this.canvas.getAttribute('height') != null) {
throw new Error('请勿在粒子动效的canvas上的添加width、height属性仅允许通过参数传递')
}
this.canvas.width = options.width || parseInt(getComputedStyle(this.canvas).width);
this.canvas.height = options.height || parseInt(getComputedStyle(this.canvas).height);
this.canvas.style.width = this.canvas.width + 'px';
this.canvas.style.height = this.canvas.height + 'px';
this.context = this.canvas.getContext('2d');
this.ballNumber = options.ballNumber
this.ballMinSize = options.ballMinSize;
this.ballMaxSize = options.ballMaxSize;
this.color = options.color;
if (this.color instanceof Array) {
if (this.color.length > 1)
this.randomColor = new randomColor(this.color[0], this.color[1]);
else
this.color = options.color[0];
}
var that = this;
this.__draw(true);
self.setInterval(function () {
that.__draw(false);
}, 1000 / options.fps);
};
/**
* 插件重设方法
*
* @param options {{
* width:number?,
* height:number?,
* ballNumber:number?,
* ballMinSize:number?,
* ballMaxSize:number?,
* color:string?
* }}
*/
particle.prototype.reDraw = function (options) {
if (options) {
if (options.hasOwnProperty('width')) {
this.canvas.width = options.width;
this.canvas.style.width = this.canvas.width+'px';
}
if (options.hasOwnProperty('height')) {
this.canvas.height = options.height;
this.canvas.style.height = this.canvas.height+'px';
}
if (options.hasOwnProperty('ballNumber'))
this.ballNumber = options.ballNumber;
if (options.hasOwnProperty('ballMinSize'))
this.ballMinSize = options.ballMinSize;
if (options.hasOwnProperty('ballMaxSize'))
this.ballMaxSize = options.ballMaxSize;
if (options.hasOwnProperty('color')) {
this.color = options.color;
if (this.color instanceof Array) {
if (this.color.length > 0)
this.randomColor = new randomColor(this.color[0], this.color[1]);
else
this.color = options.color[0];
}
}
this.__draw(true);
} else {
this.canvas.style.width = '';
this.canvas.style.height = '';
this.canvas.width='';
this.canvas.height='';
this.canvas.width = parseInt(getComputedStyle(this.canvas).width);
this.canvas.height = parseInt(getComputedStyle(this.canvas).height);
this.canvas.style.width = this.canvas.width+'px';
this.canvas.style.height = this.canvas.height+'px';
this.__draw(false);
}
}
/**
* 绘制点
* @param force 是否强制绘制。为true时会清空并重新生成所有点并重新绘制点用于初始化为false时不会重新生成点会清空并重绘点
* @private
*/
particle.prototype.__draw = function (force) {
//初始化小球数据
if (force) {
this.ball = [];
this.__ballConfigure();
}
//重绘canvas
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
var i = 0;
while (i < this.ballNumber) {
//绘制小球
this.context.beginPath();
if (this.ball[i].size > 0)
this.context.arc(this.ball[i].x, this.ball[i].y, this.ball[i].size, 0, Math.PI * 2, true);
this.context.closePath();
this.context.fillStyle = this.ball[i].color;
this.context.fill();
//赋予小球加速度
this.ball[i].x += this.ball[i].vx;
this.ball[i].y += this.ball[i].vy;
this.ball[i].size -= this.ball[i].sizeReduce;
if (this.ball[i].size < this.ballMinSize || this.ball[i].size <= 0) {
this.ball[i].size = this.ballMinSize;
this.ball[i].sizeReduce *= -1;
this.ball[i].color = this.__randomColor();
} else if (this.ball[i].size > this.ballMaxSize) {
this.ball[i].size = this.ballMaxSize;
this.ball[i].sizeReduce *= -1;
}
//防止小球出界
if (this.ball[i].x <= 0 || this.ball[i].x >= this.canvas.width) {
this.ball[i].vx = -this.ball[i].vx;
}
if (this.ball[i].y <= 0 || this.ball[i].y >= this.canvas.height) {
this.ball[i].vy = -this.ball[i].vy;
}
i++;
}
};
/**
* 根据配置生成小球并放入数组
* @private
*/
particle.prototype.__ballConfigure = function () {
//获取随机小球配置
var j = 0;
while (j < this.ballNumber) {
this.ball[j] = {
x: Math.ceil(Math.random() * this.canvas.width),
y: Math.ceil(Math.random() * this.canvas.height),
vx: particle.__noZeroRandom(-1, 1),
vy: particle.__noZeroRandom(-1, 1),
size: particle.__noZeroRandom(this.ballMinSize, this.ballMaxSize),
color: this.__randomColor(),
sizeReduce: 0.1
};
j++;
}
};
/**
* 利用 randomColor 生成范围随机色,如果没有范围,则返回指定色
*
* @returns {*|string|string[]}
*/
particle.prototype.__randomColor = function () {
return this.color instanceof Array ? this.randomColor.getColor() : this.color;
}
/**
* 生成不为0随机数,直接挂载到对象上,而非实例上
* @param min 最小
* @param max 最大
* @returns {number} 生成值
* @private
*/
particle.__noZeroRandom = function (min, max) {
var k = 0;
while (k === 0) {
k = Math.floor(Math.random() * (max - min + 1) + min);
}
return k;
}
window.Particle = particle;
})();