以下のおもちゃ React component が有って、右に swipe したら右に fade out、左に swipe したら左に fade out したいとしよう。
import React, { useState } from "react"; const items = [ {id: 1, content: "item 1"}, {id: 2, content: "item 2"}, ]; export function Example() { const [currentItemId, setCurrentItemId] = useState(1); const currentItem = items[currentItemId]; return ( <div className="Example"> {currentItem.content} </div> ); }
先づ swipe event を設定しよう。react-swipeable を入れる。
npm install --save react-swipeable
import React, { useCallback, useState } from "react"; import { useSwipeable } from "react-swipeable"; // 讀み込む const items = [ {id: 0, content: "item 1"}, {id: 1, content: "item 2"}, ]; export function Example() { const [currentItemId, setCurrentItemId] = useState(0); const handlers = useSwipable({ // swipe event 用の handler を作る onSwipedLeft: useCallback( (event) => { setCurrentItemId(currentItemId + 1); } ), onSwipedRight: useCallback( (event) => { setCurrentItemId(currentItemId - 1); } ), }); const currentItem = items[currentItemId]; return ( <div className="Example" {...handlers}> // event handler を設定する {currentItem.content} </div> ); }
これで .exemple
要素を左に swipe したら次の、右に swipe したら前の item に切り替へられる。(item が無い時の error を處理してゐないので盛大に bug ってはゐるが!)
次に swipe animation を設定しよう。react-transition-group を入れる。
npm install --save react-transition-group npm install --save-dev @types/react-transition-group
SwitchTransaction が目的に適ふ。
import React, { useCallback, useState } from "react"; import { useSwipeable } from "react-swipeable"; import { CSSTransition, SwitchTransition } from "react-transition-group"; // 讀み込む import "./Example.css"; // CSS を讀み込む const items = [ {id: 0, content: "item 1"}, {id: 1, content: "item 2"}, ]; export function Example() { const [currentItemId, setCurrentItemId] = useState(0); const [swipeoutDirection, setSwipeoutDirection] = useState<string | undefined>(undefined); // swipe animation の方向に依ってどっちの CSS を當てるか決める const handlers = useSwipable({ onSwipedLeft: useCallback( (event) => { setCurrentItemId(currentItemId + 1); setSwipeoutDirection("left"); // 左へ swipeout } ), onSwipedRight: useCallback( (event) => { setCurrentItemId(currentItemId - 1); setSwipeoutDirection("right"); // 右へ swipeout } ), }); const currentItem = items[currentItemId]; return ( <SwitchTransition mode="out-in"> // swipe animation する要素を SwitchTransition > CSSTransition で圍む。out してから次の要素が見えて欲しいので out-in <CSSTransition className="{`swipeout-${swipeoutDirection}`}" // この名に -exit だとか -exit-active だとか postfix の附いた class 名が對象の要素に着け外される key={currentItem.id} // 子に對して一意な値。React で loop する時に附ける key と同じ意味 timeout={300} // transition の時間に合はせた > <div className="Example" {...handlers}> {currentItem.content} </div> </CSSTransition> </SwitchTransition> ); }
讀み込ませる CSS を作る。
.Example.swipeout-left-exit { /* -exit や -exit-active の部分が react-transition-group の仕樣。後は普通の CSS animation */ transform: translateX(0); } .Example.swipeout-left-exit-active { transform: translateX(-800px); transition: transform 0.3s ease-in-out; } .Example.swipeout-right-exit { transform: translateX(0); } .Example.swipeout-right-exit-active { transform: translateX(800px); transition: transform 0.3s ease-in-out; }
これで完成。