\n
\n \n
\n
Sincronización: 0%
\n 0.5 ? '#0ff' : '#f0f';\n }\n update() { \n this.x += this.vx;\n this.y += this.vy;\n if (this.x < 0 || this.x > width || this.y < 0 || this.y > height) this.reset();\n }\n draw() { \n ctx.beginPath();\n ctx.arc(this.x, this.y, 1, 0, Math.PI * 2);\n ctx.fill();\n ctx.fillStyle = this.color;\n }\n}\n\nfor (let i = 0; i < 200; i++) particles.push(new Particle());\n\nlet syncProgress = 0;\nfunction animate() { \n ctx.fillStyle = 'rgba(0,0,0,0.1)';\n ctx.fillRect(0, 0, width, height);\n \n ctx.lineWidth = 0.5;\n particles.forEach(p => {\n p.update();\n ctx.strokeStyle = p.color;\n ctx.beginPath();\n ctx.moveTo(p.x, p.y);\n // Simple attractor logic\n let dx = width / 2 - p.x;\n let dy = height / 2 - p.y;\n ctx.lineTo(p.x + dx * 0.01, p.y + dy * 0.01);\n ctx.stroke();\n });\n\n syncProgress += 0.1;\n if (syncProgress >