(翻譯)用react-spring以react hook元件的形式編寫動畫

tpfmryjty發表於2019-11-06

原文:alligator.io/react/intro… 在本文中,我們將探索React的最佳動畫框架之一:React Spring。 您將學習將元件樣式更改為平滑的,基於物理的過渡的一些基礎知識。

提前需要了解的

React Spring具有基於鉤子和基於元件的API,這裡將專門針對所有動畫使用具有基本狀態的鉤子,建議先學習React Hooks相關知識。

環境安裝和配置

這裡使用Create React App來作為腳手架,另外需要安裝react-spring

$ npx create-react-app react-spring-example
$ cd react-spring-example
$ npm i react-spring 
複製程式碼

from and to的概念

在下面App.js檔案中,使用了react-spring庫中的UseSpring和animated,UseSpring是一個可以設定樣式的自定義鉤子,它接受一個物件,該物件具有from和to值作為開始和結束狀態,react-spring正是用這兩個狀態來處理過渡的動畫效果。from和to幾乎可以設定所有的CSS屬性物件:顏色,大小,transform,甚至滾動條。只需要在HTML標籤上增加animated就可以應用spring動畫。預設情況下,動畫會在元件掛載的時候立即執行。

從一個值過渡到另外一個值可能有點單調,但react-spring可以使用陣列來渲染具有多個階段的動畫。只需記住始終將起始狀態包含在要新增的任何屬性裡面即可。

多說無益,下面上程式碼:

// App.js:
import React, { useState } from 'react';
import { useSpring, animated } from 'react-spring';


const App = () => {
  const animation = useSpring({
    from: { opacity: 0 },
    to: { opacity: 1 }
  });

  const colorAnimation = useSpring({
    from: { color: 'blue' },
    to: { color: `rgb(255,0,0)` }
  });

  const multiAnimation = useSpring({
    from: { opacity: 0, color: 'red' },
    to: [
        { opacity: 1, color: '#ffaaee' },
        { opacity: 1, color: 'red' },
        { opacity: .5, color: '#008000' },
        { opacity: .8, color: 'black' }
    ]
  });
  return (
    <div>
      <animated.h1 style={animation}>Hello World</animated.h1>
      <animated.h1 style={colorAnimation}>Hello World</animated.h1>
      <animated.h1 style={multiAnimation}>Hello World</animated.h1>
    </div>
  )
};

export default App;
複製程式碼

State的概念

繫結一些本地狀態能夠向動畫中新增一些實時的效果,而不是在掛載時進行動畫效果過渡。 對於單步動畫,我們可以使用三元運算子來代替from and to屬性。

import React, { useState } from 'react';

const App = () => {
  const [on, toggle] = useState(false);

  const animation = useSpring({
    color: on ? 'blue' : 'red'
  });
  return (
    <div>
      <animated.h1 style={animation}>{!on ? "I'm red" : "Now I'm blue" }</animated.h1>
      <button onClick={() => toggle(!on)}>Change</button>
    </div>
  )
};
複製程式碼

Interpolates屬性

除了僅對元素和元件新增靜態樣式更改之外,我們還可以使用Interpolate建立更有趣和可重用的動畫。 由於它也是一個物件,因此可以在spring中新增變數,並使用Interpolate獲取樣式。

我們只需要從spring中取值,並使用Interpolate對其進行更多分解,將其放入模板中。 這將使我們能夠自由設定更多的動態值,例如基於x位置的顏色值。

const App = () => {
  const [on, toggle] = useState(false);

  const { xy } = useSpring({
    from: { xy: [0, 0], color: 'green' },
    xy: on ? [800, 200] : [0, 0],
    c: 'red'
  });
  return (
    <div>
      <animated.h1
        style={{ 
            transform: xy.interpolate((x, y) => `translate(${x}px, ${y}px)`), 
            color: c.interpolate(c => c)}}>
        {!on ? "I'm here" : "Now I'm over here"}</animated.h1>
      <button onClick={() => toggle(!on)}>Change</button>
    </div>
  )
};
複製程式碼

Mimicking Keyframes

Interpolate更有用的方面之一是我們可以模擬CSS關鍵幀。與其將值傳遞到spring中,不如將其設定為1或0。像以前一樣Interpolate之前,我們需要傳遞一個具有範圍和輸出的物件。 範圍可以是0到1之間的任何值,並且可以像使用CSS關鍵幀設定斷點那樣工作,相應的輸出是將要預渲染的值。

然後,第二次插值將在每次輸出更改時重置我們的樣式。

const App = () => {
  const [on, toggle] = useState(false)

  const { x, c } = useSpring({
    from: { xy: [0, 0], c: 0 },
    x: on ? 1 : 0,
    c: on ? 1 : 0
  })

  return ( 
    <div>
      <animated.h1
        style={{
          transform: x.interpolate({
            range: [0, .25, .5, .75, 1],
            output: [0, 500, 200, 800, 500]
          }).interpolate(x => `translateX(${x}px)`),

          color: c.interpolate({
            range: [0, .5, 1],
            output: ['red', 'blue', 'green']
          }).interpolate(c => c)
        }}>
        {!on ? "I'm here" : "Now don't know where I'm going"}</animated.h1>
      <button onClick={() => toggle(!on)}>Change</button>
    </div>
  )
}
複製程式碼

Config

就其本身而言,前面的示例比較直接和讓人驚訝。 這是因為react-spring的預設配置。 我們可以在spring中操作的動畫屬性如下:

mass:影響速度以及過渡的效果。 tension:影響整體速度。 friction:控制阻力及其減速的速度。 clamp:是否應該瞬間過渡。

const animation = useSpring({
    {/* ... */}
    config: {
      mass: 5,
      tension: 50,
      friction: 25,
      clamp: true
    }
  });
複製程式碼

官方提供的一些有用的預設值搭配:

config.default { mass: 1, tension: 170, friction: 26 }
config.gentle { mass: 1, tension: 120, friction: 14 }
config.wobbly { mass: 1, tension: 180, friction: 12 }
config.stiff { mass: 1, tension: 210, friction: 20 }
config.slow { mass: 1, tension: 280, friction: 60 }
config.molasses { mass: 1, tension: 280, friction: 120 }
複製程式碼
import { useSpring, animated, config } from 'react-spring';

const animation = useSpring({
    {/* ... */}
    config: config.wobbly
  });
  
// Or you can just destructure it if you want to change other options 
const animation = useSpring({
    {/* ... */}
    config: {
        ...config.molasses, 
        clamp: true
    }
  });
複製程式碼

相關文章