web-dev-qa-db-fra.com

React Animations natives - translateX et translateY lors de la mise à l'échelle

Ma Animated.View a le style suivant:

    {
        transform: [
            {
                scale: this.animatedValue.interpolate({
                    inputRange: [0, 1],
                    outputRange: [initialScale, 1]
            })},
            {
                translateX: this.animatedValue.interpolate({
                    inputRange: [0, 1],
                    outputRange: [startX, endX]
            })},
            {
                translateY: this.animatedValue.interpolate({
                    inputRange: [0, 1],
                    outputRange: [startY, endY]
            })},
        ]
    }

Lorsque initialScale vaut 1 et que l'animation démarre, je vois le comportement attendu: Animated.View commence à (startX, startY) et se déplace linéairement vers (endX, endY).
Cependant, lorsque initialScale est de 0,5 par exemple, le point de départ de la vue n'est pas (startX, startY), le mouvement n'est pas linéaire (un peu sphérique) et le point final est toujours comme prévu - (endX, endY).

Comment mettre à l'échelle ma vue tout en conservant un mouvement linéaire et une position de départ attendue?

13
nirsky

Comme l'utilisateur @ArneHugo l'a souligné dans les commentaires, le mouvement non linéaire peut être résolu en positionnant l'élément conteneur pleine taille et en mettant à l'échelle un autre élément à l'intérieur.

La position de l'élément n'est pas celle attendue, car l'origine de la transformation d'échelle est le point central de l'élément. React Native ne prend pas (encore) en charge la spécification de l'origine de la transformation, mais si la largeur et la hauteur de l'élément mis à l'échelle sont connues à l'avance, il est facile de calculer le décalage comme suit:

const width = 100;
const height = 20;
const scale = {
  transform: [
    {
      scale: this.animatedValue.interpolate({
        inputRange: [0, 1],
        outputRange: [initialScale, 1]
      })
    }
  ]
};

const position= {
  transform: [
    {
      translateX: this.animatedValue.interpolate({
        inputRange: [0, 1],
        outputRange: [startX - (width / 2) - (width * initialScale / 2), endX]
      })
    },
    {
      translateY: this.animatedValue.interpolate({
        inputRange: [0, 1],
        outputRange: [startY - (height / 2) - (height * initialScale / 2), endY]
      })
    }
  ]
};

return (
  <Animated.View style={position}>
    <Animated.View style={[styles.thing, scale]} />
  </Animated.View>
);
14
jevakallio