Files
dss/static/js/app/lib/panningRegion.coffee
2013-07-02 21:24:13 +01:00

107 lines
4.7 KiB
CoffeeScript
Executable File

define ['marionette'],
(Marionette) ->
getPrefixedCssProp = (baseProp) ->
str = Modernizr.prefixed(baseProp)
str = str.replace(/([A-Z])/g, (str, m1) ->
"-" + m1.toLowerCase()
).replace(/^ms-/, "-ms-")
str
class PanningRegion extends Marionette.Region
el: "#content"
initialize: ->
transEndEventNames =
WebkitTransition: "webkitTransitionEnd"
MozTransition: "transitionend"
OTransition: "oTransitionEnd"
msTransition: "MSTransitionEnd"
transition: "transitionend"
@transEndEventName = transEndEventNames[Modernizr.prefixed("transition")]
@transformPropName = getPrefixedCssProp("transform")
console.log @transEndEventName, @transformPropName
true
# Very similar to show(), but uses css transition class between views
transitionToView: (newView, type) ->
self = this
# Do we have a view currently?
view = @currentView
if not view or view.isClosed
@show newView
return
Marionette.triggerMethod.call this, "willTransition", view
# Wait for the new view to render, then initialize a transition to
# show the new view while hiding the old.
newView.on "render", ->
# clean up the old listeners, just to ensure we only have 1 active.
self.$el.off self.transEndEventName
# Move the new view to an off-screen position using transformation matrix
translation = undefined
# Determine the type of transition and build the css transformation.
if type is "slide"
translation = "translateX(100%)"
else if type is "rotate"
translation = "translateX(100%) translateY(100%) rotate(" +
["20", "40", "60", "80", "90"][_.random(0, 4)] + "deg)"
else translation = "translateY(100%)" if type is "drop"
newView.$el.css self.transformPropName, translation
# Add the new view to the dom
self.$el.append newView.el
# Translate the container to show the new element
$background = jQuery("#world-bg")
# Find the transformation matrix of each element.
worldContentMatrix = Matrix.initWithElem(self.$el)
worldBgMatrix = Matrix.initWithElem($background)
newViewMatrix = Matrix.initWithElem(newView.$el)
# Turn on the css animations to enable the transition. We do this here,
# before the tranision instead of after the transition is complete
# because it causes less of a visual 'snap' as the pattern moves.
self.$el.addClass "animated"
$background.addClass "animated"
# Given than we know the container has an identity matrix we can transition
# by simply inverting the matrix of the new view and appyling it to the parent.
self.$el.css self.transformPropName, newViewMatrix.clone().invert().toMatrixString()
# Let's make sure the background moves to the same place.
$background.css self.transformPropName, newViewMatrix.clone().invert().toMatrixString()
# after transition, clean up by removing the old view, then
# re-position everything back to a zero-point. There might be a problem
# relying on the transitionEnd event because there are cases where it
# does not fire.
self.$el.on self.transEndEventName, ->
self.$el.off self.transEndEventName
# clean up the old view
self.close()
self.currentView = newView
# clean up new view and place everything back
# to a sane starting position, ready for next transition.
self.$el.removeClass "animated"
$background.removeClass "animated"
self.$el.css self.transformPropName, (new Matrix()).toMatrixString()
newView.$el.css self.transformPropName, (new Matrix()).toMatrixString()
$background.css "webkit-transform", (new Matrix()).toMatrixString()
# do the things show would normally do after showing a new view
Marionette.triggerMethod.call newView, "show"
Marionette.triggerMethod.call self, "show", newView
newView.render()
true
PanningRegion