web-dev-qa-db-fra.com

React.js: animations non-CSS

Documentation React n’a rien à voir avec la gestion des animations qui ne sont pas des transitions CSS, telles que l’animation de la position de défilement et les attributs SVG.

En ce qui concerne les transitions CSS, il y a un add-on .

Voici un exemple simple en SVG :

 Animated SVG circle

/**
 * @jsx React.DOM
 */


function animate(duration, onStep) {
    var start = Date.now();
    var timer = {id: 0};
    (function loop() {
        timer.id = requestAnimationFrame(function() {
            var diff = Date.now() - start;
            var fraction = diff / duration;
            onStep(fraction);
            if (diff < duration) {
                loop();
            }
        });
    })();
    return timer;
}

function lerp(low, high, fraction) {
    return low + (high - low) * fraction;
}


var App = React.createClass({
    getInitialState: function() {
        return {x: 0}
    },

    move: function(i) {
        this.setState({x: this.state.x + i * 100});
    },

    render: function() {
        return <div className="ShowerItem">
            <p>
                <button onClick={this.move.bind(this, -1)}>Left</button>
                <button onClick={this.move.bind(this, 1)}>Right</button>
            </p>
            <svg><Dot x={this.state.x}/></svg>
        </div>;
    }
});



var Dot = React.createClass({

    getInitialState: function() {
        return {
            x: 0,
            final: 0
        };
    },

    timer: null,

    render: function() {
        var from = this.state.x;
        var to = this.props.x;
        if (to !== this.state.final) {
            this.state.final = to;
            if (this.timer) {
                cancelAnimationFrame(this.timer.id);
            }

            this.timer = animate(500, function(fraction) {
                var x = lerp(from, to, fraction);
                if (fraction >= 1) {
                    this.setState({
                        value: to
                    });
                    this.timer = null;
                } else {
                    this.setState({x: x});
                }
            }.bind(this))
        }

        return <circle r="10" cy="10" cx={this.state.x + 10}/>
    }
});


React.renderComponent(
    <App/>,
    document.body
);

Existe-t-il un moyen plus efficace de réaliser des animations?
C’est bien l’architecture du code?

Module complémentaire Transitions CSS ne m'aide pas car je n'utilise pas de CSS.

19
NVI

J'ai utilisé avec succès ce projet dans mon intégration de réaction-marteau projet il existe quelques exemples d'événements marteau et d'animation de réaction.

Voici le code d'animation "BlinkingThing": 

var BlinkingThing = React.createClass({
    mixins: [React.Animate],
    blink: function () {
        var that = this;
        var animateAfter = function () {
            that.animate({
                color: 'green'
            }, that.props.blinkBack);
        };
        this.animate({
            color: 'yellow'
        }, this.props.blinkTo, animateAfter);
    },
    componentDidReceiveProps: function () {
        this.setState({color: this.props.color})
    },
    componentDidMount: function () {
        this.setState({color: this.props.color})
    },
    receiveHammerEvent: function (ev) {
        if (ev) {
            var value = ev.type;

            switch (value) {
                case 'tap':
                    this.blink();
                    break;
            }
        }
    },
    getInitialState: function () {
        return {};
    },
    render: function () {
        var style = {
            display: 'inline-block',
            backgroundColor: this.state.color
        };

        return (<div style={style}>{this.props.children}</div>);
    }
});

Vous avez besoin d’un composant parent qui propage des effets secondaires (événements tactiles, par exemple) pour déclencher des changements d’état dans le composant BlinkingThing (l’animation dépend du changement d’état lorsque vous appelez this.animate func), j’ai créé un composant HitArea pour le faire. Il appelle receiveHammerEvent func de ses enfants qui passent un événement marteau quand il se produit.

2
Sergey Lapin

Ayant moi-même rencontré exactement les mêmes problèmes, j'ai découvert récemment Rekapi. Cette bibliothèque fournit des outils d'animation basés sur les états. Découvrez le tutoriel https://github.com/jeremyckahn/rekapi/blob/master/docs/getting_started.md

Le truc, c'est que le contexte ne doit pas nécessairement être un canevas ou un élément DOM, il peut s'agir d'un objet simple, c'est-à-dire d'une occurrence de composant ou d'un mixeur, ce qui ouvre la possibilité d'effectuer une logique dans la méthode de rendu de votre acteur et puis setState sur votre composant (contexte), ou écrivez simplement un "acteur unique" qui transmet toujours son état au composant à chaque image.

1
user3089094

Il semble que react.animate est une bibliothèque d’animation React maintenue activement et souvent utilisée.

(il a déjà été mentionné ci-dessus, mais il serait facile de rater tous les liens)

Remarque: il est livré avec/requiert underscore.js.

0
Flion