c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開發中です。

react-swipeable と react-transition-group で swipe animation

以下のおもちゃ 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;
}

これで完成。