*{margin:0;overflow:hidden;}
const canvas = document.createElement('canvas')
const c = canvas.getContext('2d')
canvas.width = innerWidth
canvas.height = innerHeight
document.body.append(canvas)
c.fillStyle = 'black'
c.fillRect(0, 0, canvas.width, canvas.height)
class Floater {
constructor(x, y, size, draw) {
this.x = x
this.y = y
let t = Math.random() * 7
let v = Math.random() * 1 + .2
this.v = v
this.vx = Math.cos(t) * v
this.vy = Math.sin(t) * v
this.draw = draw
this.size = size
t = Math.random() * 7
v = Math.random() * .2
this.svx = Math.cos(t) * v
this.svy = Math.sin(t) * v
}
update() {
this.x += this.vx
this.y += this.vy
this.draw(this)
if (this.x < -this.size) {
this.x = innerWidth + this.size
}
if (this.x > innerWidth + this.size) {
this.x = -this.size
}
if (this.y < -this.size) {
this.y = innerHeight + this.size
}
if (this.y > innerHeight + this.size) {
this.y = -this.size
}
}
}
function bigCirc(t) {
c.fillStyle = '#888'
c.strokeStyle = 'white'
c.lineWidth = 5
c.beginPath()
c.arc(t.x, t.y, t.size, 0, 7)
c.fill()
c.stroke()
if (Math.random() < .01) {
const a = Math.random() * 7
t.v = Math.random() * 1
t.dx = Math.cos(a) * t.v
t.dy = Math.sin(a) * t.v
t.turn = true
}
if (t.turn) {
t.vx += (t.dx - t.vx) / 52
t.vy += (t.dy - t.vy) / 52
}
}
function littleCirc(t) {
const dx = this.x - big.x
const dy = this.y - big.y
const dist = Math.sqrt(dx * dx + dy * dy)
if (dist < big.size * 2) {
const t = Math.atan2(dy, dx) / Math.PI * 180
this.vx += Math.cos(t) * this.v * .2
this.vy += Math.sin(t) * this.v * .2
} else {
this.vx += ((-big.vx + t.svx) - this.vx) / 2
this.vy += ((-big.vy + t.svy) - this.vy) / 2
}
this.vx *= .999
this.vy *= .999
c.fillStyle = 'white'
c.beginPath()
c.arc(t.x, t.y, t.size, 0, 7)
c.fill()
}
const big = new Floater(
innerWidth / 2, innerHeight / 2,
100,
bigCirc
)
let littles = []
let NUM = 100
for (let i = 0; i < 100; i++) {
littles.push(new Floater(
Math.random() * innerWidth,
Math.random() * innerHeight,
10,
littleCirc
))
}
onresize = e => {
canvas.width = innerWidth
canvas.height = innerHeight
c.globalAlpha = 1
c.globalCompositeOperation = 'source-over'
c.fillStyle = 'black'
c.fillRect(0, 0, canvas.width, canvas.height)
}
onresize()
function loop() {
c.globalCompositeOperation = 'source-over'
c.fillStyle = 'rgba(0, 0, 0, 0.15)'
c.fillRect(0, 0, canvas.width, canvas.height)
c.globalCompositeOperation = 'hard-light'
big.update()
littles.forEach(l => l.update())
c.globalAlpha = .5
c.globalCompositeOperation = 'darken'
c.drawImage(canvas, 0, 0, canvas.width + 4, canvas.height + 4)
requestAnimationFrame(loop)
}
loop()
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.