canvas = {
const gridsize = 100
const margin = 8
const width = gridsize * 8 + margin*2
const height = gridsize * 8 + margin*2
const period = 200
const whiterad = 3
const colors = [0,1,2,3,4,5,6].map(i => `hsl(${(i*360/7)|0}, 55%, 60%)`)
const color = (a, b) => Color(colors[a]).mix(Color(colors[b]))
const ctx = []
const elem = document.createElement('div')
elem.style['max-width'] = width + 'px'
elem.style.height = height + 'px'
elem.style.position = 'relative'
const c = [0,1].map((_, i) => {
const canvas = document.createElement('canvas')
canvas.style.position = 'absolute'
canvas.style.display = 'block'
canvas.style.width = "100%"
canvas.style.height = "100%"
elem.appendChild(canvas)
return canvas
})
let back, fore
let t = 0
let tbase = 0
let last = null
const resize = () => {
const w = elem.clientWidth || width
elem.style.height = `${w}px`
console.log('cw', w)
c.forEach((canvas, i) => {
canvas.width = w * devicePixelRatio; canvas.height = w * devicePixelRatio
ctx[i] = canvas.getContext('2d', {alpha: i>0})
ctx[i].translate(margin, margin)
ctx[i].scale(w/width * devicePixelRatio, w/width * devicePixelRatio)
})
back = ctx[0]; fore = ctx[1]
console.log('back', back, fore)
// ctx.scale(devicePixelRatio, devicePixelRatio) // For high dpi display support
back.fillStyle = '#333'
back.fillRect(-margin, -margin, width, height)
back.lineWidth = 2
colors.forEach((_, i) => {
back.strokeStyle = color(i, i)
back.beginPath()
back.arc((i+1.5) * gridsize, 0.5 * gridsize, gridsize*0.45, 0, Math.PI*2)
back.stroke()
back.beginPath()
back.arc(0.5 * gridsize, (i+1.5) * gridsize, gridsize*0.45, 0, Math.PI*2)
back.stroke()
})
tbase = t
last = null
}
window.onresize = resize
resize()
const render = () => {
t += 1
fore.clearRect(0, 0, width, height)
fore.fillStyle = 'white'
// fore.fillStyle = 'red'
// fore.fillRect(770, 0, 800, 800)
const pos = colors.map((c, i) => {
const [x, y] = [
(.45 * Math.sin(t * (i+1) / period) + .5) * gridsize,
(.45 * Math.cos(t * (i+1) / period) + .5) * gridsize
]
const x1 = (1+i) * gridsize + x
const y1 = y
const x2 = x
const y2 = (1+i) * gridsize + y
fore.beginPath()
fore.arc(x1, y1, whiterad, 0, Math.PI*2)
fore.arc(x2, y2, whiterad, 0, Math.PI*2)
fore.fill()
fore.strokeStyle = '#666'
fore.lineWidth = 0.4
fore.beginPath()
fore.moveTo(x1, y1)
fore.lineTo(x1, height)
fore.moveTo(x2, y2)
fore.lineTo(width, y2)
fore.stroke()
return [x1, y2]
// if (i === 6) console.log((1+i) * gridsize + x)
})
for (let x = 0; x < 7; x++) {
for (let y = 0; y < 7; y++) {
let [x1, y1] = [pos[x][0], pos[y][1]]
fore.beginPath()
fore.arc(x1, y1, whiterad, 0, Math.PI*2)
fore.fill()
if (t-2 < tbase + period * Math.PI*2 && last != null) {
let [x0, y0] = [last[x][0], last[y][1]]
back.beginPath()
back.moveTo(x0, y0)
back.lineTo(x1, y1)
back.strokeStyle = color(x, y)
back.stroke()
}
}
}
last = pos
}
render()
return Generators.observe(next => {
let running = true
const r = () => {
if (running) {
render()
requestAnimationFrame(r)
next(elem)
}
}
r()
// When the generator is disposed, detach the event listener.
return () => running = false
})
}