先上图
实际是动态图,这里不能发视频
话不多说直接上代码
首先找你的login页面 定义一个空盒子,用来做canvas的容器
这里用id选择器,方便后续的js操作
然后,找到你项目的utils目录,这里我们一般是用来放项目中用到的辅助工具函数或文件的地方,
定义一个StarryParticles.ts文件,
因为是vue项目,所以我们要在这里默认导出一个函数,然后再login页面导入执行,就可以了
具体操作如下:
在utils导出
在login导入
这里会遇到一个问题,就是你要在导出的函数中使用id选择器获取dom,但是,在login页面执行函数的时候,页面还未加载完成,就获取dom,是获取不到的,这和在vue中画echarts遇到的情况很像,所以,我这里的解决办法是,在页面加载完成之后,在延时器中调用导出的函数
onMounted(() => {
setTimeout(() => {
StarryParticles();
}, 200);
});
然后,就可以正常执行这个函数啦
最后,在StarryParticles.ts导出的函数具体如下:
// @ts-nocheck 开头写这个注释是为了关闭ts类型检查对当前页面的检查,有时候这个类型检查很sb
export const StarryParticles = () => {
window.requestAnimFrame = (function () {
return window.requestAnimationFrame;
})();
var t,
e,
n,
o = document.getElementById('canvas'),
r = o.getContext('2d'),
i = 1900,
s = '0.' + Math.floor(9 * Math.random()) + 1,
a = 2 * o.width,
c = 0,
l = [];
function u() {
window.requestAnimFrame(u), p(), h();
}
function d() {
(t = o.width / 2), (e = o.height / 2), (l = []);
for (var r = 0; r < i; r++)
(n = {
x: Math.random() * o.width,
y: Math.random() * o.height,
z: Math.random() * o.width,
o: '0.' + Math.floor(99 * Math.random()) + 1,
}),
l.push(n);
}
function p() {
for (var t = 0; t < i; t++) (n = l[t]), n.z--, n.z <= 0 && (n.z = o.width);
}
function h() {
var u, p, h;
if (((o.width === window.innerWidth && o.width === window.innerWidth) || ((o.width = window.innerWidth), (o.height = window.innerHeight), d()), 0 === c)) {
(r.fillStyle = 'rgba(0,10,20,1)'), r.fillRect(0, 0, o.width, o.height), (r.fillStyle = 'rgba(209, 255, 255, ' + s + ')');
for (var f = 0; f < i; f++) (n = l[f]), (u = (n.x - t) * (a / n.z)), (u += t), (p = (n.y - e) * (a / n.z)), (p += e), (h = (a / n.z) * 1), r.fillRect(u, p, h, h), (r.fillStyle = 'rgba(209, 255, 255, ' + n.o + ')');
}
}
d(), u();
}
当然还有别的画法,但是如果是在vue3的话需要引入一个库
pnpm add particles.vue3
官方地址我也贴在下面
我用到的另外两张图如下:
同样是在StarryParticles.ts导出的函数
first
let canvas = document.querySelector('#canvas');
let context = canvas.getContext('2d');
let cw = (canvas.width = window.innerWidth);
let ch = (canvas.height = window.innerHeight);
class Boom {
// 爆炸物是没有确定的结束点坐标, 这个可以通过设定一定的阀值来限定
constructor(startX, startY) {
this.startLocation = { x: startX, y: startY };
this.nowLocation = { x: startX, y: startY };
// 速度
this.speed = Math.random() * 3;
// 加速度
this.acceleration = 1;
// 没有确定的结束点,所以没有固定的角度,可以随机角度扩散
this.angle = Math.random() * Math.PI * 2;
// 这里设置阀值为100
this.targetCount = 100;
// 当前计算为1,用于判断是否会超出阀值
this.nowNum = 1;
// 透明度
this.alpha = 1;
// 重力系数
this.gravity = 0;
this.decay = 0.015;
// 线段集合
this.collection = new Array(2);
// 是否到达目标点
this.arrived = false;
}
draw() {
context.beginPath();
try {
context.moveTo(this.collection[0][0], this.collection[0][1]);
} catch (e) {
context.moveTo(this.nowLocation.x, this.nowLocation.y);
}
context.lineWidth = 1;
context.lineCap = 'round';
context.lineTo(this.nowLocation.x, this.nowLocation.y);
// 设置由透明度减小产生的渐隐效果,看起来没这么突兀
context.strokeStyle = `rgba(255, 255, 255, ${this.alpha})`;
context.stroke();
}
update() {
this.collection.shift();
this.collection.push([this.nowLocation.x, this.nowLocation.y]);
this.speed *= this.acceleration;
let vx = Math.cos(this.angle) * this.speed;
// 加上重力系数,运动轨迹会趋向下
let vy = Math.sin(this.angle) * this.speed + this.gravity;
// 当前计算大于阀值的时候的时候,开始进行渐隐处理
if (this.nowNum >= this.targetCount) {
this.alpha -= this.decay;
} else {
this.nowLocation.x += vx;
this.nowLocation.y += vy;
this.nowNum++;
}
// 透明度为0的话,可以进行移除处理,释放空间
if (this.alpha <= 0) {
this.arrived = true;
}
}
init() {
this.draw();
this.update();
}
}
class Animate {
constructor() {
// 定义一个数组做为爆炸点的集合
this.booms = [];
}
pushBoom() {
// 实例化爆炸效果,随机条数的射线扩散
for (let bi = Math.random() * 10 + 20; bi > 0; bi--) {
this.booms.push(new Boom(cw / 2, ch / 2));
}
}
run() {
window.requestAnimationFrame(this.run.bind(this));
context.clearRect(0, 0, cw, ch);
let bnum = this.booms.length;
while (bnum--) {
// 触发动画
this.booms[bnum].init();
if (this.booms[bnum].arrived) {
// 到达目标透明度后,把炸点给移除,释放空间
this.booms.splice(bnum, 1);
}
}
this.pushBoom();
}
}
let a = new Animate();
a.run();
second
//整个星空的画布 canvas
var canvas: HTMLCanvasElement = document.getElementById('canvas')!,
ctx = canvas.getContext('2d')!,
w = (canvas.width = window.innerWidth),
h = (canvas.height = window.innerHeight),
hue = 217,
stars: string | any[] = [],
count = 0,
maxStars = 1600;
//canvas2是每一颗星星的画法
var canvas2 = document.createElement('canvas')!,
ctx2 = canvas2.getContext('2d')!;
canvas2.width = 100;
canvas2.height = 100;
var half = canvas2.width / 2,
gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half); //中心渐变
gradient2.addColorStop(0.025, '#fff');
/*gradient2.addColorStop(0.1, 'hsl(' + hue + ', 61%, 33%)');
gradient2.addColorStop(0.25, 'hsl(' + hue + ', 64%, 6%)');*/
gradient2.addColorStop(0.1, 'rgba(33, 73, 136,0.9)');
gradient2.addColorStop(0.25, 'rgba(33, 73, 136,0.05)');
gradient2.addColorStop(1, 'transparent');
ctx2.fillStyle = gradient2;
ctx2.beginPath();
ctx2.arc(half, half, half, 0, Math.PI * 2);
ctx2.fill();
// End cache
function random(min: number, max?: number) {
if (arguments.length < 2) {
max = min;
min = 0;
}
if (min > max) {
var hold = max;
max = min;
min = hold;
}
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function maxOrbit(x: number, y: number) {
var max = Math.max(x, y),
diameter = Math.round(Math.sqrt(max * max + max * max));
return diameter / 2;
}
var Star = function (this: any) {
this.orbitRadius = random(maxOrbit(w, h)); //星星运动轨迹旋转半径
this.radius = random(60, this.orbitRadius) / 24; //星星半径
this.orbitX = w / 2;
this.orbitY = h / 2;
this.timePassed = random(0, maxStars);
this.speed = random(this.orbitRadius) / 900000; //900000初始值
this.alpha = random(2, 10) / 10;
count++;
stars[count] = this;
};
Star.prototype.draw = function () {
var x = Math.sin(this.timePassed) * this.orbitRadius + this.orbitX,
y = Math.cos(this.timePassed) * this.orbitRadius + this.orbitY,
twinkle = random(10);
//实现闪烁的效果
if (twinkle === 1 && this.alpha > 0) {
this.alpha -= 0.05;
} else if (twinkle === 2 && this.alpha < 1) {
this.alpha += 0.05;
}
ctx.globalAlpha = this.alpha;
ctx.drawImage(canvas2, x - this.radius / 2, y - this.radius / 2, this.radius, this.radius);
this.timePassed += this.speed;
};
for (var i = 0; i < maxStars; i++) {
new Star();
}
function animation() {
//ctx.globalCompositeOperation = 'source-over';
//ctx.globalAlpha = 1;
//ctx.fillStyle = 'hsla(' + 217 + ', 64%, 6%, 1)';
//ctx.fillRect(0, 0, w, h);
ctx.clearRect(0, 0, w, h);
ctx.globalCompositeOperation = 'lighter';
for (var i = 1, l = stars.length; i < l; i++) {
stars[i].draw();
}
//drawText();
window.requestAnimationFrame(animation);
}
/*function drawChat(WhichCanvas,chat){}*/
animation();
//输入值 color[ r: g: b]
function changeColorOfCanvas2(colorR: string | number, colorG: string | number, colorB: string | number) {
//hue = color || 0;
ctx2 = canvas2.getContext('2d');
canvas2.width = 100;
canvas2.height = 100;
var half = canvas2.width / 2,
gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half); //中心渐变
gradient2.addColorStop(0.025, '#fff');
gradient2.addColorStop(0.1, 'rgba(' + colorR + ',' + colorG + ', ' + colorB + ',0.9)');
gradient2.addColorStop(0.25, 'rgba(' + colorR + ', ' + colorG + ',' + colorB + ',0.05)');
gradient2.addColorStop(1, 'transparent');
ctx2.fillStyle = gradient2;
ctx2.beginPath();
ctx2.arc(half, half, half, 0, Math.PI * 2);
ctx2.fill();
}
var colors = [
{ r: 255, g: 255, b: 255 },
// { r: 0, g: 200, b: 0 },
{ r: 0, g: 200, b: 200 },
// { r: 200, g: 0, b: 200 },
];
function randomNum(min: number, max: number) {
var num = Math.floor(Math.random() * (max + 1 - min) + min);
return num;
}
var currentColor = {
r: 33,
g: 73,
b: 136,
};
/*changeColorOfCanvas2(colors[0]);*/
function animateColor(targetColor: { r: any; g: any; b: any }) {
var colorR = (targetColor.r - currentColor.r) / 30;
var colorG = (targetColor.g - currentColor.g) / 30;
var colorB = (targetColor.b - currentColor.b) / 30;
console.log(colorR);
for (var i = 1; i <= 30; i++) {
var colorstep = {
r: Math.floor(currentColor.r + colorR * i),
g: Math.floor(currentColor.g + colorG * i),
b: Math.floor(currentColor.b + colorB * i),
};
setTimeout(() => {
changeColorOfCanvas2(colorstep.r, colorstep.g, colorstep.b);
}, i * (1000 / 30));
}
currentColor = targetColor;
}
function animateColors(colors: string | any[]) {
var randomindex = randomNum(0, colors.length - 1);
var randomColor = colors[randomindex];
animateColor(randomColor);
return randomColor;
}
animateColors(colors);