Skip to content

Instantly share code, notes, and snippets.

@harrislapiroff
Created January 20, 2012 17:58
Show Gist options
  • Save harrislapiroff/1648690 to your computer and use it in GitHub Desktop.
Save harrislapiroff/1648690 to your computer and use it in GitHub Desktop.
Oberlin College's Snow Script
KEYFRAME_RATE = 200
HORIZONTAL_DELTA = 2
VERTICAL_DELTA = 4
EASING_FUNCTION = "linear"
TOTAL_SNOWFLAKES = 50
EXCLUDE_MOBILE = true
CANVAS_WIDTH_FN = () -> $('#all').width()
CANVAS_HEIGHT_FN = () -> 125
# by_probability will return val1 prob% of the time, val2 otherwise
# prob should be a decimal b/w 0 and 1
by_probability = (val1, val2, prob) ->
rand = Math.random()
if rand < prob
return val1
else
return val2
class Snowflake
constructor: (@registry) ->
rand = Math.random()
radius = Math.max(2,10*rand)
opacity = 1+Math.log(1-rand)
@el = @registry.paper.circle(0, 0, radius)
@el.attr('opacity', opacity)
@el.attr('fill', '#FFF')
@el.attr('stroke', 'none')
@position(0, 0)
position: (x, y) =>
# place a snowflake instantly at x, y coords
@x = x
@y = y
@el.stop()
@el.attr({'cx': x, 'cy': y})
move: (x, y) =>
# animate a snowflake to a particular location
@x = x
@y = y
@el.animate({'cx': x, 'cy': y}, KEYFRAME_RATE, EASING_FUNCTION)
fall: () =>
# calculate the snowflake's next location and animate it to that location
ydelta = VERTICAL_DELTA
xdelta = by_probability(HORIZONTAL_DELTA, -HORIZONTAL_DELTA, .5) * Math.random()
maxY = @registry.height
maxX = @registry.width
if @y <= maxY
@move(@x + xdelta, @y + ydelta)
else if maxY > 0
@position(Math.floor(Math.random()*maxX), -40)
class Snowfield
constructor: () ->
# create the snowfield array
@snowflakes = []
# create the canvas
@paper = Raphael(0, 0, 0, 0)
# add some attributes to the actual HTML element
@paper.canvas.id = "snow"
if Modernizr.testProp "pointerEvents"
$('html').addClass('pointerEvents')
$(@paper.canvas).attr('pointer-events', 'none')
else
$('html').addClass('noPointerEvents')
# for some reason pointer events don't work quite right in this version of webkit, so here's how we deal, gross browser sniffing
if $.browser.webkit and parseInt($.browser.version) < 535
$('html').removeClass('pointerEvents').addClass('noPointerEvents')
# set the canvas size
@canvas_size_refresh()
# set an interval for making the snowflakes fall
@go()
# set an event listener to resize the canvas when the window resizes
$(window).resize(@canvas_resize_handler)
add: (snowflake) =>
# add a snowflake to the snowfield array
@snowflakes.push(snowflake)
remove: (snowflake) =>
# remove a snowflake from the snowfield array
for i in [0...@snowflakes.length]
do () =>
if @snowflakes[i] == snowflake
@snowflakes.splice(i, i)
create_snowflake: () =>
# create a single snowflake and place it randomly in the snowfield
snowflake = new Snowflake(this)
@add(snowflake)
x = Math.floor(Math.random()*@width)
y = Math.floor(Math.random()*@height)
snowflake.position(x, y)
create_batch: (count) =>
# create a batch of snowflakes
for num in [1..count]
do () =>
@create_snowflake()
batch_fall: () =>
# make every snowflake in the snowfield fall
for snowflake in @snowflakes
do (snowflake) =>
if snowflake
snowflake.fall()
pause: () =>
clearInterval(@animation_interval)
@paused = true
go: () =>
@animation_interval = setInterval(@batch_fall, KEYFRAME_RATE)
@paused = false
set_dimensions: (width, height) =>
# low-level method to set the dimensions of the canvas and cache those dimensions as properties on the Snowfield
@width = width
@height = height
@paper.setSize(@width, @height)
canvas_resize_handler: () =>
# this can safely be called on a window resize event and the canvas_size_refresh method will only fire when the window has stopped being resized.
unless @paused
@pause()
if @resize_timeout
clearTimeout(@resize_timeout)
@resize_timeout = setTimeout(@canvas_size_refresh, 100)
canvas_size_refresh: () =>
# refresh the canvas size based on the values of CANVAS_WIDTH_FN and CANVAS_HEIGHT_FN
@set_dimensions(CANVAS_WIDTH_FN(), CANVAS_HEIGHT_FN())
if @paused
@go()
create_batch = (snowfield) ->
# creates a batch of snowflakes in a snowfield
snowflake_count = TOTAL_SNOWFLAKES
snowfield.create_batch(snowflake_count)
init = ($) ->
# cut out here if this is a mobile device
if EXCLUDE_MOBILE and navigator.userAgent.match(/mobile|opera m(ob|in)/i)
return
# create and populate a new snowfield
snowfield = new Snowfield()
create_batch(snowfield)
$(window).load(init)
.noPointerEvents #hd, .noPointerEvents #glob{
position:relative;
z-index: 1337 !important;
}
.pointerEvents #snow{
z-index:1337;
}
#all::before{
content:" ";
display:block;
position:absolute;
top:0;
left:0;
height:126px;
width:100%;
background: url('left.png') left bottom no-repeat, url('center.png') left bottom repeat-x, url('right.png') right bottom no-repeat;
-webkit-box-reflect:below 0 -webkit-linear-gradient(bottom, rgba(0,0,0,.5), rgba(0,0,0,0) 20%);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment