js实现灯光秀
使用JavaScript实现灯光秀效果
通过Canvas绘制动态灯光效果,结合随机颜色生成和动画循环实现视觉冲击力。以下代码示例展示基础实现方式:
const canvas = document.getElementById('lightShow');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const lights = [];
for (let i = 0; i < 100; i++) {
lights.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
radius: Math.random() * 10 + 5,
color: `hsl(${Math.random() * 360}, 100%, 50%)`,
speedX: Math.random() * 4 - 2,
speedY: Math.random() * 4 - 2
});
}
function animate() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
lights.forEach(light => {
ctx.beginPath();
ctx.arc(light.x, light.y, light.radius, 0, Math.PI * 2);
ctx.fillStyle = light.color;
ctx.fill();
light.x += light.speedX;
light.y += light.speedY;
if (light.x < 0 || light.x > canvas.width) light.speedX *= -1;
if (light.y < 0 || light.y > canvas.height) light.speedY *= -1;
});
requestAnimationFrame(animate);
}
animate();
添加交互式灯光控制
通过事件监听实现用户交互效果,灯光会跟随鼠标移动产生波纹:

let mouseX = 0;
let mouseY = 0;
window.addEventListener('mousemove', (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
lights.push({
x: mouseX,
y: mouseY,
radius: 15,
color: `hsl(${Math.random() * 360}, 100%, 50%)`,
speedX: Math.random() * 6 - 3,
speedY: Math.random() * 6 - 3,
life: 100
});
});
function animate() {
// ...原有动画代码...
lights.forEach((light, index) => {
if (light.life) {
light.life--;
light.radius *= 0.95;
if (light.life <= 0) {
lights.splice(index, 1);
}
}
});
}
使用WebGL实现高级效果
对于更复杂的3D灯光效果,建议使用Three.js库:

import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const particles = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particles * 3);
const colors = new Float32Array(particles * 3);
for (let i = 0; i < positions.length; i += 3) {
positions[i] = (Math.random() - 0.5) * 200;
positions[i+1] = (Math.random() - 0.5) * 200;
positions[i+2] = (Math.random() - 0.5) * 200;
colors[i] = Math.random();
colors[i+1] = Math.random();
colors[i+2] = Math.random();
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1,
vertexColors: true,
transparent: true,
opacity: 0.8
});
const particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
camera.position.z = 100;
function animate() {
requestAnimationFrame(animate);
particleSystem.rotation.x += 0.001;
particleSystem.rotation.y += 0.002;
renderer.render(scene, camera);
}
animate();
性能优化建议
限制帧率避免过度消耗资源:
let fps = 30;
let now;
let then = Date.now();
const interval = 1000/fps;
function animate() {
requestAnimationFrame(animate);
now = Date.now();
const delta = now - then;
if (delta > interval) {
then = now - (delta % interval);
// 绘制代码放在这里
}
}
使用离屏Canvas预渲染静态元素:
const bufferCanvas = document.createElement('canvas');
bufferCanvas.width = canvas.width;
bufferCanvas.height = canvas.height;
const bufferCtx = bufferCanvas.getContext('2d');
// 预渲染背景等不变元素
bufferCtx.fillStyle = 'black';
bufferCtx.fillRect(0, 0, bufferCanvas.width, bufferCanvas.height);
// 在主Canvas中复用
ctx.drawImage(bufferCanvas, 0, 0);






