A ray fired from a fixed origin toward the mouse. Where it hits the circle, the surface normal is the unit vector from the centre to the hit point; the reflection is the standard d − 2(d·n)n.
See also: Reflect a line off another line — same reflection formula, flat mirror; Circle ↔ line intersection — same quadratic, different output.
// 1. Ray-circle intersection (quadratic in t along d)
m = origin - centre
a = d . d
b = 2 * (m . d)
c = (m . m) - r * r
disc = b*b - 4*a*c
if (disc < 0) return null // ray misses
t = (-b - sqrt(disc)) / (2 * a)
if (t < 0) return null // hit is behind origin
hit = origin + d * t
// 2. Reflect direction about the surface normal
n = (hit - centre) / r
reflected = d - n * (2 * (d . n))
const cx = 180, cy = 150, r = 60
const ox = 20, oy = 150 // ray origin
const dx = mouseX - ox
const dy = mouseY - oy
const mx = ox - cx, my = oy - cy
const a = dx * dx + dy * dy
const b = 2 * (mx * dx + my * dy)
const c = mx * mx + my * my - r * r
const disc = b * b - 4 * a * c
if (disc >= 0) {
const t = (-b - Math.sqrt(disc)) / (2 * a)
if (t > 0 && t < 1) { // hit before reaching the mouse
const hx = ox + dx * t
const hy = oy + dy * t
// unit normal at hit
const nx = (hx - cx) / r
const ny = (hy - cy) / r
// reflect direction (kept un-normalised; only direction matters)
const dDotN = dx * nx + dy * ny
const rdx = dx - 2 * dDotN * nx
const rdy = dy - 2 * dDotN * ny
}
}