包详细信息

react-gsap-enhancer

azazdeaz582MIT0.3.0

Use the full power of React and GSAP together

animation, greensock, gsap, react

自述文件

react-gsap-enhancer Build Status Coveralls branch npm maintainance

Join the chat at https://gitter.im/azazdeaz/react-gsap-enhancer

Demos Why? How it works? Usage API

A React component enhancer for applying GSAP animations on components without side effects.

For simple use cases you might not need this tool. See this egghead.io tutorial.

Developed as part of the Animachine project.

Requirements:

Demos

Why?

We have great tools (like react-motion, or Animated) to animate the state and props of our React components but if you ever needed to create a longer animation sequence with React you can still feel the desire to reach out for a tool like GSAP which makes it easy to compose your animation and apply it on the DOM with its super performance and bulit in polyfills. Unfortunately, if you let anything to mutate the DOM of a component, React can break on the next update because is suppose that the DOM looks exacly the same like after the last update. This tool is a work around for this problem.

How it works?

It's pretty simple: in every render cycle:

  • after each render save the attributes of the rendered DOM elements than start/restart the added animations.
  • before each render stop the animations and restore the saved attributes (so React will find the DOM as it was after the update)

In this way you can even update a style of an element (like transform: 'translateX(${mouse.x})') while you animating the same style relative to its original value (like: .to(node, 1, {x: '+=300', yoyo: true})

Check it out!

Usage

First you have to enhance the component with react-gsap-enhancer:

ES5

var GSAP = require('react-gsap-enhancer')
var MyComponent = GSAP()(React.createClass({
  render: function() {/*...*/}
}))

ES6

import GSAP from 'react-gsap-enhancer'

class MyComponent extends Component {
  render() {/*...*/}
}

export default GSAP()(MyComponent)

ES7

import GSAP from 'react-gsap-enhancer'

@GSAP()
export default class MyComponent extends Component {
  render() {/*...*/}
}

Now you can attach animations to the component with addAnimation(animationSource). The animationsSource is a function that returns a GSAP Animation (ex. TweenLite, or TimelineMax) like this:

function moveAnimation(utils) {
  return TweenMax.to(utils.target, 1, {x: '+=123'})
}

the utils.target refers to the root node of the component but you can select any of it's children by they props in the good old jQuery style:

function moveAnimation({target}) {//just ES6 syntax sugar
  var footer = target.find({type: 'footer'})
  var buttons = footer.findAll({type: 'button'})
  ...
}

and later in a component you can use it like:

...
handleClick() {
  var controller = this.addAnimation(moveAnimation)
...

the addAnimation() returns a controller object that has the same API like the original GSAP Animation so you are free to control it like:

...
handleStartLoad() {
  this.progressAnim = this.addAnimation(progressAnim)
  this.otherAnim.timeScale(3.4).reverse()
}
handleProgress(progress) {
  this.progressAnim.tweenTo(progress)
}
...

API

addAnimation()
  • enhancedComponent.addAnimation(animationSource[, options]) -> controller: Add an animation to the component with the given source and returns a Controller for it. The options will be passed to the animationSource.
controller

Wraps the GSAP Animation returned from the animationSource. It's exposing the following GSAP API methods:
For TweenMax and TweenLite:

delay*, duration*, eventCallback, invalidate, isActive, pause, paused, play, progress, restart, resume, reverse, reversed, seek, startTime*, time, timeScale, totalDuration*, totalProgress*, totalTime*,

For TimelineMax and TimelineLite:

currentLabel, duration*, endTime*, eventCallback, from, fromTo, getLabelAfter, getLabelBefore, getLabelArray, getLabelTime, invalidate, isActive, pause, paused, play, progress, restart, resume, reverse, reversed, seek, startTime*, time, timeScale, totalDuration*, totalProgress*, totalTime*, tweenFromTo, tweenTo,

Notes:

  • Some of the methods above doesn't available for TweenLite and TimelineLite. Please check the GSAP docs for more detailes.
  • controller.kill() will also remove all the effects the animation made on your component.
  • As you can see the editor methods (like .to() or .add()) aren't exposed by the controller so you can only use them inside the animationSource function while you construct the animation.

* Trough the controller you can only get values with these methods.

var controller = this.addAnimation(animationSource)
controller.timeScale(2).play()
animationSource
  • ({target, options}) -> GSAP Animation

A function that returns a GSAP Animation.

function animationSource(utils) {
  return TweenMax.to(utils.target, 1, {x: 100})
}
this.addAnimation(animationSource)
target

jQuery like object that refers to the root component and lets select its children with chainable find methods and selectors.

  • target.find(selector): returns with the first match
  • target.findAll(selector): returns with all the matches
  • target.findInChildren(selector): returns with the first match in the direct children
  • target.findAllInChildren(selector): returns with all the matches in the direct children
    function animationSource(utils) {
    var button = utils.target.findAll({type: 'button'}).find({role: 'submit'})
    return TweenMax.to(button, 1, {x: 100})
    }
options

Arbitrary object. Passed to the addAnimation call as the second argument and and will be passed to the animationSource

this.addAnimation(animationSource, {offset: this.props.offset})

...

function animationSource(utils) {
  return TweenMax.to(utils.target, 1, {x: utils.options.offset})
}
selector

Selectors are usually simple objects and the "find" functions are using it to select the elements with matching props. Ie. {key: 'head'}, {color: 'red'}, and {key: 'head', color: 'red} are all matches to <div key='head' color='red'/>.

I'm looking forward for your feedback!

更新日志

HEAD

Unreleased

  • Bugfix: Don't throw in memory history when out of history entries (#170)
  • Bugfix: Fix the deprecation warnings on createPath and createHref (#189)

v1.16.0

  • Bugfix: Silence all warnings that were introduced since 1.13 (see rackt/react-router#2682)
  • Deprecation: Deprecate the createLocation method in the top-level exports
  • Deprecation: Deprecate the state arg to history.createLocation

v1.15.0

Dec 7, 2015

  • Feature: Accept location descriptors in createPath and createHref (#173)
  • Deprecation: Deprecate the query arg to createPath and createHref in favor of using location descriptor objects (#173)

v1.14.0

Dec 6, 2015

  • Feature: Accept objects in history.push and history.replace (#141)
  • Deprecation: Deprecate history.pushState and history.replaceState in favor of passing objects to history.push and history.replace (#168)
  • Bugfix: Disable browser history on Chrome iOS (#146)
  • Bugfix: Do not convert same-path PUSH to REPLACE if the hash has changed (#167)
  • Add ES2015 module build (#152)
  • Use query-string module instead of qs to save on bytes (#121)

v1.13.1

Nov 13, 2015

  • Fail gracefully when Safari security settings prevent access to window.sessionStorage
  • Pushing the currently active path will result in a replace to not create additional browser history entries (#43)
  • Strip the protocol and domain from <base href> (#139)

v1.13.0

Oct 28, 2015

  • useBasename transparently handles trailing slashes (#108)
  • useBasename automatically uses the value of <base href> when no basename option is provided (#94)

v1.12.6

Oct 25, 2015

  • Add forceRefresh option to createBrowserHistory that forces full page refreshes even when the browser supports pushState (#95)

v1.12.5

Oct 11, 2015

  • Un-deprecate top-level createLocation method
  • Add ability to use { pathname, search, hash } object anywhere a path can be used
  • Fix useQueries handling of hashes (#93)

v1.12.4

Oct 9, 2015

  • Fix npm postinstall hook on Windows (#62)

v1.12.3

Oct 7, 2015

  • Fix listenBefore hooks not being called unless a listen hook was also registered (#71)
  • Add a warning when we cannot save state in Safari private mode (#42)

v1.12.2

Oct 6, 2015

v1.12.1

Oct 5, 2015

  • Give location objects a key by default
  • Deprecate history.setState

v1.12.0

Oct 4, 2015

  • Add history.createLocation instance method. This allows history enhancers such as useQueries to modify location objects when creating them directly
  • Deprecate createLocation method on top-level exports

v1.11.1

Sep 26, 2015

  • Fix location.basename when location matches exactly (#68)
  • Allow transitions to be interrupted by another

v1.11.0

Sep 24, 2015

  • Add useBasename history enhancer
  • Add history.listenBefore
  • Add history.listenBeforeUnload to useBeforeUnload history enhancer
  • Deprecate (un)registerTransitionHook
  • Deprecate (un)registerBeforeUnloadHook
  • Fix installing directly from git repo