$ -> # globals canvas = $('#eyeball')[0] return unless canvas?.getContext? g = canvas.getContext('2d') m = new MouseListener(canvas) # defined in util.js mx = 280 my = 100 TAU = 2*Math.PI # helper functions plotCircle = (x, y, r) -> g.beginPath() g.arc(x, y, r, 0, TAU) fillWith = (style) -> g.fillStyle = style g.fill() expovariate = (x) -> -Math.log(1.0 - Math.random()) * x seconds = -> new Date().getTime() / 1000.0 time = seconds() dt = 0 class Eyeball constructor: (@x, @y, @r, @fill) -> @blink = expovariate(2.5) @blinking = no draw: -> # background plotCircle(@x, @y, @r) fillWith @fill plotCircle(@x, @y, @r-10) fillWith '#ffffff' #iris dx = mx - @x dy = my - @y distSq= dx*dx + dy*dy maxDist = @r-10-20 if distSq > maxDist*maxDist k = maxDist/Math.sqrt(distSq) dx *= k dy *= k plotCircle(@x+dx, @y+dy, 20) fillWith '#aaaaff' plotCircle(@x+dx, @y+dy, 12) fillWith '#161616' plotCircle(@x+dx-8, @y+dy-8, 8) fillWith 'rgba(255, 255, 255, 0.9)' # eyelids if @blinking @blink -= 5.0*dt if @blink < -1.0 @blinking = no @blink = expovariate(2.5) else u = 0.5 * (1 - Math.abs(@blink)) g.beginPath() g.arc(@x, @y, @r, 0.5*Math.PI - u * Math.PI, 0.5*Math.PI + u * Math.PI) fillWith @fill g.beginPath() g.arc(@x, @y, @r, 1.5*Math.PI - u * Math.PI, 1.5*Math.PI + u * Math.PI) g.fill() else @blink -= dt if @blink < 0 @blink = 1 @blinking = yes eyes = [ new Eyeball(680-400, 100, 64, '#e7c049') new Eyeball(726-400, 250, 40, '#92b35a') ] do -> # tick time nextTime = seconds() dt = nextTime - time time = nextTime # smooth mouse position mx += 0.25 * (m.x - mx) my += 0.25 * (m.y - my) # draw eye.draw() for eye in eyes # enqueue next frame requestAnimationFrame arguments.callee