最近弄了PiKa监控,它支持自定义JS,看到了一个粒子特效,就给它搞了一个,演示效果看图:
代码如下:
(function () {
// 控制开关:0=静态不跟随鼠标,1=正常跟随鼠标
var mouseSwitch = 1;
function init() {
if (!document.body) {
setTimeout(init, 100);
return;
}
var canvasContainer = document.createElement('div');
canvasContainer.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99999;
pointer-events: none;
`;
var canvas = document.createElement('canvas');
canvas.id = 'tyParticlesCanvas';
canvasContainer.appendChild(canvas);
document.body.appendChild(canvasContainer);
var ctx = canvas.getContext('2d');
var particles = [];
var dpr = window.devicePixelRatio || 1;
var mouse = {
x: window.innerWidth / 2,
y: window.innerHeight / 2,
tx: window.innerWidth / 2,
ty: window.innerHeight / 2,
active: false,
radius: 190
};
var scroll = {
lastY: window.pageYOffset || document.documentElement.scrollTop || 0,
velocity: 0,
targetVelocity: 0,
direction: 0,
burst: 0,
targetBurst: 0
};
var colors = [
{ r: 255, g: 79, b: 163 },
{ r: 139, g: 92, b: 246 },
{ r: 103, g: 232, b: 249 },
{ r: 255, g: 124, b: 195 },
{ r: 80, g: 220, b: 120 },
{ r: 255, g: 210, b: 80 },
{ r: 230, g: 70, b: 80 },
{ r: 90, g: 170, b: 255 },
{ r: 255, g: 100, b: 70 },
{ r: 170, g: 255, b: 220 },
{ r: 200, g: 150, b: 255 },
{ r: 255, g: 245, b: 110 },
{ r: 60, g: 190, b: 190 },
{ r: 245, g: 130, b: 220 },
{ r: 155, g: 225, b: 90 }
];
function rgba(c, a) {
return 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + a + ')';
}
function resizeCanvas() {
var width = window.innerWidth;
var height = window.innerHeight;
canvas.width = width * dpr;
canvas.height = height * dpr;
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
createParticles();
}
function particleCount() {
var w = window.innerWidth;
if (w < 576) return 30;
if (w < 992) return 55;
return 135;
}
function createParticles() {
particles = [];
var count = particleCount();
for (var i = 0; i < count; i++) {
var color = colors[Math.floor(Math.random() * colors.length)];
particles.push({
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
vx: (Math.random() - 0.5) * 0.28,
vy: (Math.random() - 0.5) * 0.28,
size: Math.random() * 4.5 + 0.75,
color: color,
alpha: Math.random() * 0.45 + 0.35,
floatOffset: Math.random() * Math.PI * 2,
floatSpeed: Math.random() * 0.008 + 0.004,
depth: Math.random() * 1.4 + 0.35,
inertiaY: 0,
inertiaX: 0
});
}
}
function updateMouse() {
mouse.x += (mouse.tx - mouse.x) * 0.08;
mouse.y += (mouse.ty - mouse.y) * 0.08;
}
function updateScrollVelocity() {
var currentY = window.pageYOffset || document.documentElement.scrollTop || 0;
var diff = currentY - scroll.lastY;
scroll.lastY = currentY;
if (diff > 0) scroll.direction = 1;
else if (diff < 0) scroll.direction = -1;
else scroll.direction = 0;
scroll.targetVelocity = diff * 0.075;
scroll.targetBurst = Math.max(-18, Math.min(18, diff * 0.18));
scroll.velocity += (scroll.targetVelocity - scroll.velocity) * 0.12;
scroll.burst += (scroll.targetBurst - scroll.burst) * 0.18;
scroll.velocity *= 0.91;
scroll.burst *= 0.88;
scroll.targetBurst *= 0.72;
}
function drawParticle(p) {
ctx.beginPath();
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
ctx.fillStyle = rgba(p.color, p.alpha);
ctx.shadowBlur = 16;
ctx.shadowColor = rgba(p.color, .85);
ctx.fill();
ctx.shadowBlur = 0;
}
function updateParticle(p, time) {
var floatX = Math.cos(time * p.floatSpeed + p.floatOffset) * 0.35;
var floatY = Math.sin(time * p.floatSpeed + p.floatOffset) * 0.35;
var scrollDriftY = -scroll.velocity * p.depth;
var scrollBurstY = -scroll.burst * p.depth * 0.16;
var scrollDriftX = Math.sin(time * 0.001 + p.floatOffset) * Math.abs(scroll.velocity) * 0.08 * p.depth;
p.inertiaY += scrollBurstY;
p.inertiaX += scrollDriftX;
p.inertiaY *= 0.88;
p.inertiaX *= 0.90;
p.x += p.vx + floatX + p.inertiaX;
p.y += p.vy + floatY + scrollDriftY + p.inertiaY;
// 通过mouseSwitch判断是否开启鼠标交互
if (mouseSwitch === 1 && mouse.active) {
var dx = mouse.x - p.x;
var dy = mouse.y - p.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < mouse.radius) {
var force = (1 - dist / mouse.radius);
p.x += dx * force * 0.020;
p.y += dy * force * 0.020;
p.x += Math.sin(time * 0.004 + p.floatOffset) * force * 0.8;
p.y += Math.cos(time * 0.004 + p.floatOffset) * force * 0.8;
}
}
if (p.x < -50) p.x = window.innerWidth + 50;
if (p.x > window.innerWidth + 50) p.x = -50;
if (p.y < -50) p.y = window.innerHeight + 50;
if (p.y > window.innerHeight + 50) p.y = -50;
}
function connectParticles() {
var maxDist = window.innerWidth < 576 ? 105 : 145;
var scrollBoost = Math.min(Math.abs(scroll.velocity) * 0.018, 0.12);
for (var i = 0; i < particles.length; i++) {
for (var j = i + 1; j < particles.length; j++) {
var dx = particles[i].x - particles[j].x;
var dy = particles[i].y - particles[j].y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < maxDist) {
var opacity = (1 - dist / maxDist) * (0.16 + scrollBoost);
ctx.beginPath();
ctx.moveTo(particles[i].x, particles[i].y);
ctx.lineTo(particles[j].x, particles[j].y);
ctx.strokeStyle = 'rgba(255,124,195,' + opacity + ')';
ctx.lineWidth = 1.4;
ctx.stroke();
}
}
}
}
// 开关为0时不绘制鼠标连线
function connectMouse() {
if(mouseSwitch !== 1) return;
if (!mouse.active) return;
for (var i = 0; i < particles.length; i++) {
var dx = mouse.x - particles[i].x;
var dy = mouse.y - particles[i].y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < mouse.radius) {
var opacity = (1 - dist / mouse.radius) * 0.24;
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
ctx.lineTo(particles[i].x, particles[i].y);
ctx.strokeStyle = 'rgba(103,232,249,' + opacity + ')';
ctx.lineWidth = 1.4;
ctx.stroke();
}
}
}
function drawScrollWind() {
var strength = Math.min(Math.abs(scroll.velocity) * 0.035, 0.22);
if (strength < 0.015) return;
var direction = scroll.direction || 1;
var lineCount = 9;
for (var i = 0; i < lineCount; i++) {
var x = (window.innerWidth / lineCount) * i + Math.sin(Date.now() * 0.001 + i) * 28;
var y = (Date.now() * 0.08 * direction + i * 120) % (window.innerHeight + 160) - 80;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + 18 * direction, y - 90 * direction);
ctx.strokeStyle = 'rgba(255,124,195,' + strength + ')';
ctx.lineWidth = 1;
ctx.stroke();
}
}
function animate(time) {
ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
updateMouse();
updateScrollVelocity();
drawScrollWind();
for (var i = 0; i < particles.length; i++) {
updateParticle(particles[i], time);
drawParticle(particles[i]);
}
connectParticles();
connectMouse();
requestAnimationFrame(animate);
}
window.addEventListener('resize', function () {
dpr = window.devicePixelRatio || 1;
resizeCanvas();
});
window.addEventListener('mousemove', function (e) {
mouse.tx = e.clientX;mouse.ty = e.clientY;mouse.active = true;
});
window.addEventListener('mouseleave', function () { mouse.active = false; });
window.addEventListener('touchmove', function (e) {
if (!e.touches || !e.touches.length) return;
mouse.tx = e.touches[0].clientX;mouse.ty = e.touches[0].clientY;mouse.active = true;
}, { passive: true });
window.addEventListener('touchend', function () { mouse.active = false; });
resizeCanvas();
requestAnimationFrame(animate);
}
init();
})();
评论 (0)
评论已关闭