<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas 光源发光特效</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
}
canvas {
display: block;
}
.credit {
position: fixed;
bottom: 10px;
right: 10px;
color: rgba(255, 255, 255, 0.3);
font-family: Arial, sans-serif;
font-size: 12px;
}
</style>
</head>
<body>
<canvas id="glowCanvas"></canvas>
<script>
// 光源发光特效插件
class GlowEffect {
constructor(canvasId, options = {}) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext('2d');
this.particles = [];
this.lightSources = [];
this.animationId = null;
// 默认配置
this.config = {
particleCount: 100,
maxParticleSize: 3,
glowIntensity: 0.8,
lightColor: '#ffffff',
backgroundColor: '#000000',
...options
};
this.init();
}
init() {
this.resizeCanvas();
window.addEventListener('resize', this.resizeCanvas.bind(this));
// 创建粒子
for (let i = 0; i < this.config.particleCount; i++) {
this.particles.push(this.createParticle());
}
// 添加鼠标光源
this.canvas.addEventListener('mousemove', (e) => {
this.addLightSource(e.clientX, e.clientY);
});
// 添加触摸光源(移动设备)
this.canvas.addEventListener('touchmove', (e) => {
e.preventDefault();
const touch = e.touches[0];
this.addLightSource(touch.clientX, touch.clientY);
});
// 自动添加随机光源
setInterval(() => {
if (this.lightSources.length < 3) { // 最多3个自动光源
const x = Math.random() * this.canvas.width;
const y = Math.random() * this.canvas.height;
this.addLightSource(x, y, true);
}
}, 3000);
this.animate();
}
resizeCanvas() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
}
createParticle() {
return {
x: Math.random() * this.canvas.width,
y: Math.random() * this.canvas.height,
size: Math.random() * this.config.maxParticleSize,
speedX: Math.random() * 0.5 - 0.25,
speedY: Math.random() * 0.5 - 0.25
};
}
addLightSource(x, y, isAuto = false) {
this.lightSources.push({
x,
y,
radius: 100 + Math.random() * 50,
intensity: 0.8 + Math.random() * 0.2,
isAuto,
life: isAuto ? 100 + Math.random() * 100 : Infinity
});
// 限制光源数量
if (this.lightSources.length > 5) {
this.lightSources.shift();
}
}
updateParticles() {
for (let i = 0; i < this.particles.length; i++) {
const p = this.particles[i];
p.x += p.speedX;
p.y += p.speedY;
// 边界检查
if (p.x < 0 || p.x > this.canvas.width) p.speedX *= -1;
if (p.y < 0 || p.y > this.canvas.height) p.speedY *= -1;
// 随机改变方向
if (Math.random() < 0.01) {
p.speedX = Math.random() * 0.5 - 0.25;
p.speedY = Math.random() * 0.5 - 0.25;
}
}
}
updateLightSources() {
for (let i = this.lightSources.length - 1; i >= 0; i--) {
const light = this.lightSources[i];
if (light.isAuto) {
light.life--;
if (light.life <= 0) {
this.lightSources.splice(i, 1);
continue;
}
// 自动光源轻微移动
light.x += Math.random() * 2 - 1;
light.y += Math.random() * 2 - 1;
}
}
}
draw() {
// 清除画布
this.ctx.fillStyle = this.config.backgroundColor;
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
// 绘制发光效果
for (const light of this.lightSources) {
const gradient = this.ctx.createRadialGradient(
light.x, light.y, 0,
light.x, light.y, light.radius
);
gradient.addColorStop(0, this.config.lightColor);
gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
this.ctx.globalCompositeOperation = 'lighter';
this.ctx.fillStyle = gradient;
this.ctx.beginPath();
this.ctx.arc(light.x, light.y, light.radius, 0, Math.PI * 2);
this.ctx.fill();
}
// 绘制粒子
this.ctx.globalCompositeOperation = 'lighter';
for (const p of this.particles) {
// 计算粒子亮度(基于最近的光源)
let brightness = 0;
for (const light of this.lightSources) {
const dx = p.x - light.x;
const dy = p.y - light.y;
const distance = Math.sqrt(dx * dx + dy * dy);
const lightEffect = Math.max(0, 1 - distance / light.radius) * light.intensity;
brightness = Math.max(brightness, lightEffect);
}
if (brightness > 0) {
const alpha = brightness * this.config.glowIntensity;
this.ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`;
this.ctx.beginPath();
this.ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
this.ctx.fill();
}
}
}
animate() {
this.updateParticles();
this.updateLightSources();
this.draw();
this.animationId = requestAnimationFrame(this.animate.bind(this));
}
destroy() {
if (this.animationId) {
cancelAnimationFrame(this.animationId);
}
// 移除事件监听器等清理工作
}
}
// 初始化插件
document.addEventListener('DOMContentLoaded', () => {
const glowEffect = new GlowEffect('glowCanvas', {
particleCount: 150,
maxParticleSize: 4,
glowIntensity: 0.9,
lightColor: '#4a8cff'
});
});
</script>
</body>
</html>
Canvas 光源发光特效实现
8110

被折叠的 条评论
为什么被折叠?



