UNPKG

ldx-widgets

Version:

widgets

117 lines (84 loc) 4.06 kB
Animation = require 'ainojs-animation' easing = require 'ainojs-easing' _ = require 'lodash' ### Purpose: Easily add Enter and Leave animations to a React Component (that is a child of React's TransitionGroup) The react component must have these properties for an Enter Animation initialState: object - Only required when there are additional states to those being animated The initial state of the component, which will have animated properties mixed in Note: getInitialState on your component is overwritten by this mixin ENTER ANIMATION PROPS enterDuration: number (millisecoinds), defaults to 300 enterStateStart: object, required, no default enterStateEnd: object, required, no default enterEasing: string, defaults to 'linear' (ainojs-easing function name: https://github.com/aino/ainojs-easing) LEAVE ANIMATION PROPS leaveDuration: number (millisecoinds), defaults to 300 leaveStateStart: object, required, no default leaveStateEnd: object, required, no default leaveEasing: string, defaults to 'linear' (ainojs-easing function name: https://github.com/aino/ainojs-easing) finaally, the @state properties must be applied as inline styles in the component's render method ### module.exports = getInitialState: -> enterStateStart = @enterStateStart?() or @enterStateStart leaveStateStart = @leaveStateStart?() or @leaveStateStart _.extend(@initialState or {}, enterStateStart or leaveStateStart or {}) componentWillEnter: (done) -> unless @enterStateStart? and @enterStateEnd? done() return @animation = new Animation { duration: @enterDuration or 300 easing: easing(@enterEasing or 'linear') } enterStateStart = @enterStateStart?() or @enterStateStart enterStateEnd = @enterStateEnd?() or @enterStateEnd # Note: need to clone here so animate class does not alter initial values stateStart = _.clone(enterStateStart) # Note: Not feeding init @state directly, because that will clobber @state properties not being animated @animation.init stateStart @animation.on('frame', @onFrame) @animation.on('complete', done) @animation.animateTo enterStateEnd componentWillLeave: (done) -> unless @leaveStateEnd? done() return @animation = new Animation { duration: @leaveDuration or 300 easing: easing(@leaveEasing or 'linear') } leaveStateStart = @leaveStateStart?() or @leaveStateStart leaveStateEnd = @leaveStateEnd?() or @leaveStateEnd if not leaveStateStart? leaveStateStart = {} leaveStateStart[k] = @state[k] for k,v of leaveStateEnd # Note: need to clone here so animate class does not alter initial values stateStart = _.clone(leaveStateStart) # Note: Not feeding init method @state directly because that will clobber @state properties not being animated @animation.init stateStart @animation.on('frame', @onFrame) @animation.on('complete', done) @animation.animateTo leaveStateEnd componentWillUnmount: -> if @animation?.isAnimating() then @animation.destroy() # For us with the transition_out mixin, allows for navigation to be delyated until animation completes #componentDidLeave: -> # @props.completeNavigation?() # @completeNavigation?() onFrame: (e) -> if @isMounted() then @setState e.values animateStateTo: (options) -> {newState, duration, easingType, cb} = options @animation = new Animation duration: duration or @enterDuration or 300 easing: easing(easingType or @enterEasing or 'linear') # Pull the values to animate out of state to get the starting position stateStart = {} for k,v of newState return console?.warn "State: #{k} must be in component state to be animated" unless @state[k]? stateStart[k] = @state[k] @animation.init stateStart @animation.on 'frame', @onFrame @animation.on 'complete', -> cb?() @animation.animateTo newState