Skip to content

Instantly share code, notes, and snippets.

@lucjan
Created January 9, 2012 16:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucjan/1583806 to your computer and use it in GitHub Desktop.
Save lucjan/1583806 to your computer and use it in GitHub Desktop.
impress.coffee
((document, window) ->
pfx = (->
style = document.createElement("dummy").style
prefixes = "Webkit Moz O ms Khtml".split(" ")
memory = {}
(prop) ->
if typeof memory[prop] is "undefined"
ucProp = prop.charAt(0).toUpperCase() + prop.substr(1)
props = (prop + " " + prefixes.join(ucProp + " ") + ucProp).split(" ")
memory[prop] = null
for i of props
if style[props[i]] isnt `undefined`
memory[prop] = props[i]
break
memory[prop]
)()
arrayify = (a) ->
[].slice.call a
css = (el, props) ->
key = undefined
pkey = undefined
for key of props
if props.hasOwnProperty(key)
pkey = pfx(key)
el.style[pkey] = props[key] if pkey?
el
byId = (id) ->
document.getElementById id
$ = (selector, context) ->
context = context or document
context.querySelector selector
$$ = (selector, context) ->
context = context or document
arrayify context.querySelectorAll(selector)
translate = (t) ->
" translate3d(" + t.x + "px," + t.y + "px," + t.z + "px) "
rotate = (r, revert) ->
rX = " rotateX(" + r.x + "deg) "
rY = " rotateY(" + r.y + "deg) "
rZ = " rotateZ(" + r.z + "deg) "
(if revert then rZ + rY + rX else rX + rY + rZ)
scale = (s) ->
" scaleX(" + s.x + ") scaleY(" + s.y + ") scaleZ(" + s.z + ") "
ua = navigator.userAgent.toLowerCase()
impressSupported = (pfx("perspective")?) and (ua.search(/(iphone)|(ipod)|(ipad)|(android)/) is -1)
impress = byId("impress")
unless impressSupported
impress.className = "impress-not-supported"
return
else
impress.className = ""
canvas = document.createElement("div")
canvas.className = "canvas"
arrayify(impress.childNodes).forEach (el) ->
canvas.appendChild el
impress.appendChild canvas
steps = $$(".step", impress)
document.documentElement.style.height = "100%"
css document.body,
height: "100%"
overflow: "hidden"
props =
position: "absolute"
transformOrigin: "top left"
transition: "all 1s ease-in-out"
transformStyle: "preserve-3d"
css impress, props
css impress,
top: "50%"
left: "50%"
perspective: "1000px"
css canvas, props
current =
translate:
x: 0
y: 0
z: 0
rotate:
x: 0
y: 0
z: 0
scale:
x: 1
y: 1
z: 1
steps.forEach (el, idx) ->
data = el.dataset
step =
translate:
x: data.x or 0
y: data.y or 0
z: data.z or 0
rotate:
x: data.rotateX or 0
y: data.rotateY or 0
z: data.rotateZ or data.rotate or 0
scale:
x: data.scaleX or data.scale or 1
y: data.scaleY or data.scale or 1
z: data.scaleZ or 1
el.stepData = step
el.id = "step-" + (idx + 1) unless el.id
css el,
position: "absolute"
transform: "translate(-50%,-50%)" + translate(step.translate) + rotate(step.rotate) + scale(step.scale)
transformStyle: "preserve-3d"
active = null
select = (el) ->
return false if not el or not el.stepData
window.scrollTo 0, 0
step = el.stepData
active.classList.remove "active" if active
el.classList.add "active"
impress.className = "step-" + el.id
window.location.hash = "#/" + el.id
target =
rotate:
x: -parseInt(step.rotate.x, 10)
y: -parseInt(step.rotate.y, 10)
z: -parseInt(step.rotate.z, 10)
scale:
x: 1 / parseFloat(step.scale.x)
y: 1 / parseFloat(step.scale.y)
z: 1 / parseFloat(step.scale.z)
translate:
x: -step.translate.x
y: -step.translate.y
z: -step.translate.z
zoomin = target.scale.x >= current.scale.x
css impress,
perspective: step.scale.x * 1000 + "px"
transform: scale(target.scale)
transitionDelay: (if zoomin then "500ms" else "0ms")
css canvas,
transform: rotate(target.rotate, true) + translate(target.translate)
transitionDelay: (if zoomin then "0ms" else "500ms")
current = target
active = el
el
document.addEventListener "keydown", ((event) ->
if event.keyCode is 9 or (event.keyCode >= 32 and event.keyCode <= 34) or (event.keyCode >= 37 and event.keyCode <= 40)
next = active
switch event.keyCode
when 33, 37
, 38
next = steps.indexOf(active) - 1
next = (if next >= 0 then steps[next] else steps[steps.length - 1])
when 9, 32
, 34
, 39
, 40
next = steps.indexOf(active) + 1
next = (if next < steps.length then steps[next] else steps[0])
select next
event.preventDefault()
), false
document.addEventListener "click", (event) ->
target = event.target
target = target.parentNode while (target.tagName isnt "A") and (not target.stepData) and (target isnt document.body)
if target.tagName is "A"
href = target.getAttribute("href")
target = byId(href.slice(1)) if href and href[0] is "#"
event.preventDefault() if select(target)
getElementFromUrl = ->
byId window.location.hash.replace(/^#\/?/, "")
window.addEventListener "hashchange", (->
select getElementFromUrl()
), false
select getElementFromUrl() or steps[0]
) document, window
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment