const canvas = document.querySelector('canvas'),
  ctx = canvas.getContext('2d')
let timer, totalBall,
  balls = []

class Ball {
  constructor(x, y, r, vel) {
    this.x = x
    this.y = y
    this.r = r
    this.vel = vel
    this.angle = 2 * Math.PI * Math.random()
  }

  update() {
    this.angle += -Math.PI / 12 / 2 + Math.PI / 12 * Math.random()
    this.x += this.vel * Math.cos(this.angle)
    this.y += this.vel * Math.sin(this.angle)
  }

  draw() {
    ctx.fillStyle = '#eee'
    ctx.beginPath()
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI)
    ctx.fill()
  }
}

function init() {
  initCanvas()
  bindEvents()
}

function initCanvas() {
  let i = 0

  cancelAnimationFrame(timer)
  canvas.width = document.querySelector('.main').offsetWidth
  canvas.height = document.querySelector('.main').offsetHeight
  totalBall = canvas.width * canvas.height / 20000
  balls = []
  for (; i < totalBall; i++) {
    balls.push(new Ball(10 + (canvas.width - 20) * Math.random(), 10 + (canvas.height - 20) * Math.random(), 10, 0.5))
  }
  update()
}

function update() {
  detectCollide()
  balls.forEach(ball => {
    ball.update()
  })
  draw()
  timer = requestAnimationFrame(update)
}

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  balls.forEach(ball => {
    ball.draw()
  })
  linkBalls()
}

function linkBalls() {
  for (let i = 0; i < balls.length; i++) {
    for (let j = i; j < balls.length; j++) {
      const distance = Math.sqrt(Math.pow(balls[i].x - balls[j].x, 2) + Math.pow(balls[i].y - balls[j].y, 2))

      if (distance < 200) {
        ctx.strokeStyle = `rgba(230, 230, 230, ${50 / distance})`
        ctx.lineWidth = 1
        ctx.beginPath()
        ctx.moveTo(balls[i].x, balls[i].y)
        ctx.lineTo(balls[j].x, balls[j].y)
        ctx.stroke()
      }
    }
  }
}

function detectCollide() {
  balls.forEach(ball => {
    if (ball.x - ball.r < 0 || ball.x + ball.r > canvas.width) {
      ball.angle -= Math.PI
    }
    if (ball.y - ball.r < 0 || ball.y + ball.r > canvas.height) {
      ball.angle -= Math.PI
    }
  })
}

function bindEvents() {
  window.addEventListener('resize', initCanvas)
}

init()

@@ -74,16 +74,29 @@
 t('2d')%0A
+%3C%3C%3C%3C%3C%3C%3C HEAD%0A
 let time
@@ -109,16 +109,74 @@
 alBall,%0A
+=======%0Alet timer, totalBall, mouseX, mouseY,%0A%3E%3E%3E%3E%3E%3E%3E dev%0A
   balls 
@@ -1386,24 +1386,38 @@
 linkBalls()%0A
+  linkMouse()%0A
 %7D%0A%0Afunction 
@@ -1893,32 +1893,765 @@
  %7D%0A    %7D%0A  %7D%0A%7D%0A%0A
+function linkMouse() %7B%0A    if (!mouseX %7C%7C !mouseY) %7B%0A        return%0A    %7D%0A    for (let i = 0; i %3C balls.length; i++) %7B%0A        const distance = Math.sqrt((balls%5Bi%5D.x - mouseX) ** 2 + (balls%5Bi%5D.y - mouseY) ** 2)%0A        if (distance %3C 300) %7B%0A            ctx.strokeStyle = %60rgba(230, 230, 230, $%7B50 / distance%7D)%60%0A            ctx.lineWidth = 1%0A            ctx.beginPath()%0A            ctx.moveTo(balls%5Bi%5D.x, balls%5Bi%5D.y)%0A            ctx.lineTo(mouseX, mouseY)%0A            ctx.stroke()%0A        %7D%0A    %7D%0A  %7D%0A%7D%0A%0Afunction mousemove(e) %7B%0A  let %7Btarget%7D = e%0A%0A  mouseX = e.offsetX%0A  mouseY = e.offsetY%0A  while (target.className !== 'main') %7B%0A    mouseX += target.offsetLeft%0A    mouseY += target.offsetTop%0A    target = target.offsetParent%0A  %7D%0A%0A%7D%0A%0A
 function detectC
@@ -2918,16 +2918,16 @@
 nts() %7B%0A
-
   window
@@ -2966,16 +2966,91 @@
 Canvas)%0A
+  document.querySelector('.main').addEventListener('mousemove', mousemove)%0A
 %7D%0A%0Ainit(

resolve conflict