
代码雨_黑客帝国_canvas
完整代码
class CodeRain {
constructor(option = {}) {
this.option = {
// 父元素
elem: 'body',
// 字体大小
fontSize: 20,
// 速度 (ms)
speed: 20,
// 尾巴长度 0-1 越小尾巴越短
tail: 0.9,
// 绘制文字, 可以是每次生成一个随机字符或者固定字符
text: () => this.#randStr(),
// 字体颜色, 可以是函数生成随机颜色或者固定
color: () => this.#randColor(),
// canvsa背景颜色
bgColor: `#000`,
// 是否第一幕扫描效果下来
isScan: true,
...option
};
this.option.elem = typeof this.option.elem === 'string' ? document.querySelector(this.option.elem) : this.option.elem;
if (!this.option.elem.tagName) {
throw new Error(`[elem]父元素 参数错误`);
}
this.width = this.option.elem.offsetWidth;
this.height = this.option.elem.offsetHeight;
this.fontSize = this.option.fontSize * devicePixelRatio;
this.colWidth = this.fontSize;
this.colCount = Math.floor(this.width / this.colWidth);
this.nextRow = new Array(this.colCount).fill(0);
if (!this.option.isScan) {
for (let k in this.nextRow) {
if (Math.random() > 0.2) {
this.nextRow[k] = -Math.floor(Math.random() * (this.height / this.fontSize));
}
}
}
this.timer = null;
this.#init();
}
/**
* @description: 开始绘制
* @return {CodeRain}
*/
run() {
this.timer = setInterval(() => {
this.#draw();
}, this.option.speed);
return this;
}
/**
* @description: 停止动画
* @return {void}
*/
stop() {
if (this.timer) {
clearInterval(this.timer);
} else {
console.error('[CodeRain] 未在运行');
}
}
/**
* @description: 初始化
* @return {*}
*/
#init() {
this.canvas = document.createElement('canvas');
this.canvas.setAttribute('width', this.width);
this.canvas.setAttribute('height', this.height);
this.option.elem.appendChild(this.canvas);
this.ctx = this.canvas.getContext('2d');
this.ctx.fillStyle = this.option.bgColor;
this.ctx.fillRect(0, 0, this.width, this.height);
}
/**
* @description: 绘画一次
* @return {void}
*/
#draw() {
this.ctx.fillStyle = this.#colorToRgba(this.option.bgColor, 1 - this.option.tail);
this.ctx.fillRect(0, 0, this.width, this.height);
for (let i = 0; i < this.colCount; i++) {
const str = typeof this.option.text === 'function' ? this.option.text() : this.option.text;
const color = typeof this.option.color === 'function' ? this.option.color() : this.option.color
this.ctx.fillStyle = color;
// 等宽字体
this.ctx.font = `${this.fontSize}px "Roboto Mono"`;
const x = this.colWidth * i;
const y = this.fontSize * (this.nextRow[i] + 1);
this.ctx.fillText(str, x, y);
if (y > this.height && Math.random() > 0.99) {
this.nextRow[i] = 0;
} else {
this.nextRow[i]++;
}
}
}
/**
* @description: 随机一个字符串
* @return {string}
*/
#randStr() {
const str = `abcdefghijklmnopqrstuvwxyz0123456789".,;{}[]-_=+!#$&*`;
return str[Math.floor(Math.random() * str.length)];
}
/**
* @description: 随机颜色
* @return {string} 颜色hex
*/
#randColor() {
return `#${Math.random().toString(16).substring(3, 9)}`;
}
/**
* @description: 颜色转rgba
* @param {string} color 颜色值
* @param {number} alpha 透明度 0-1
* @return {string} rgba
*/
#colorToRgba(color, alpha = 1) {
let r, g, b;
if (color.startsWith('#')) {
if (color.length === 4) {
color = `#${color[1]}${color[1]}${color[2]}${color[2]}${color[3]}${color[3]}`;
}
r = parseInt(color.slice(1, 3), 16);
g = parseInt(color.slice(3, 5), 16);
b = parseInt(color.slice(5, 7), 16);
} else if (color.startsWith('rgb')) {
const rgbValues = color.match(/\d+/g).map(Number);
r = rgbValues[0];
g = rgbValues[1];
b = rgbValues[2];
} else if (color.startsWith('rgba')) {
const rgbaValues = color.match(/\d+/g).map(Number);
r = rgbaValues[0];
g = rgbaValues[1];
b = rgbaValues[2];
} else if (color.startsWith('hsl')) {
const hslValues = color.match(/\d+/g).map(Number);
const h = hslValues[0];
const s = hslValues[1] / 100;
const l = hslValues[2] / 100;
const c = (1 - Math.abs(2 * l - 1)) * s;
const x = c * (1 - Math.abs((h / 60) % 2 - 1));
const m = l - c / 2;
if (h < 60) {
r = c; g = x; b = 0;
} else if (h < 120) {
r = x; g = c; b = 0;
} else if (h < 180) {
r = 0; g = c; b = x;
} else if (h < 240) {
r = 0; g = x; b = c;
} else if (h < 300) {
r = x; g = 0; b = c;
} else {
r = c; g = 0; b = x;
}
r = Math.round((r + m) * 255);
g = Math.round((g + m) * 255);
b = Math.round((b + m) * 255);
} else {
throw new Error(`[${color}] 不支持这个颜色格式`);
}
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
}
使用方法
new CodeRain({
elem: '#codeRainBox',
color: 'green',
}).run();
实现效果
本文是原创文章,完整转载请注明来自 周明博客