Created
January 9, 2012 16:46
-
-
Save lucjan/1583806 to your computer and use it in GitHub Desktop.
impress.coffee
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
((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