wheatandcatの開発ブログ

React Nativeで開発しているペペロミア & memoirの技術系記事を投稿してます

Reactで作成したLPサイトにアニメーションを追加してみた

peperomia.app

↑のLPサイトにに以下みたいなアニメーションを追加してみたので実装方法を紹介

Pull Request

LPサイトにアニメーション追加 by wheatandcat · Pull Request #8 · wheatandcat/PeperomiaWebSite · GitHub

実装

まず、1つのコンポーネントで書いていたので、以下の画像のとおりにコンポーネントを分解

f:id:wheatandcat:20200722103819p:plain:w500

世の中的にはReactでアニメーションさせるにはreact-springを使用するのですが、自分的には難易度が高く挫折してので、

www.react-spring.io

アニメーションはreact-inview-monitorとcssを使って実装しました。

github.com

react-inview-monitorを使えばwindowにスクロールインしたタイミングをハンドリングできるので、それに合わせて実装する (といっても以下の記事をまるっとコピペしただけどが)

qiita.com

■ src/components/organisms/Animation.jsx

import React from 'react';
import styled from 'styled-components';
import InViewMonitor from 'react-inview-monitor';

export const Up = ({ children, delay, margin = '-20%' }) => (
  <InViewMonitor childPropsInView={{ isActive: true }} intoViewMargin={margin}>
    <FadeInUp isActive={false} delay={delay}>
      {children}
    </FadeInUp>
  </InViewMonitor>
);

export const Down = ({ children, delay, margin = '-20%' }) => (
  <InViewMonitor childPropsInView={{ isActive: true }} intoViewMargin={margin}>
    <FadeInDown isActive={false} delay={delay}>
      {children}
    </FadeInDown>
  </InViewMonitor>
);

export const Left = ({ children, delay, margin = '-20%' }) => (
  <InViewMonitor childPropsInView={{ isActive: true }} intoViewMargin={margin}>
    <FadeInLeft isActive={false} delay={delay}>
      {children}
    </FadeInLeft>
  </InViewMonitor>
);

export const Right = ({ children, delay, margin = '-20%' }) => (
  <InViewMonitor childPropsInView={{ isActive: true }} intoViewMargin={margin}>
    <FadeInRight isActive={false} delay={delay}>
      {children}
    </FadeInRight>
  </InViewMonitor>
);

const FadeIn = styled.div`
  opacity: 0;
  transition: opacity 1s ease, transform 1s ease;
  ${({ isActive }) => isActive && `opacity: 1;`}
  ${({ delay }) => delay && `transition-delay: ${delay}ms;`}
`;

const FadeInUp = styled(FadeIn)`
  transform: translateY(30px);
  ${({ isActive }) => isActive && `transform: translateY(0px);`}
`;

const FadeInDown = styled(FadeIn)`
  transform: translateY(-30px);
  ${({ isActive }) => isActive && `transform: translateY(0px);`}
`;

const FadeInLeft = styled(FadeIn)`
  transform: translateX(-30px);
  ${({ isActive }) => isActive && `transform: translateX(0px);`}
`;

const FadeInRight = styled(FadeIn)`
  transform: translateX(30px);
  ${({ isActive }) => isActive && `transform: translateX(0px);`}
`;

上記のコンポーネントでアニメーションしたいところをラップしていけばOKです

■ src/components/pages/Top.jsx

import React from 'react';
import Doujinshi from '../organisms/Doujinshi';
import AppTitle from '../organisms/AppTitle';
import AppInfo1 from '../organisms/AppInfo1';
import AppInfo2 from '../organisms/AppInfo2';
import GitHub from '../organisms/GitHub';
import Blog from '../organisms/Blog';
import AppFooter from '../organisms/AppFooter';
import { Up, Right, Left } from '../organisms/Animation';

// 上記の画像で分割したコンポーネントをAnimationのコンポーネントでラップ
export default () => {
  return (
    <div>
      <AppTitle />
      <Up>
        <Doujinshi /> 
      </Up>
      <Right>
        <AppInfo1 />
      </Right>
      <AppInfo2 />
      <Right>
        <GitHub />
      </Right>
      <Left>
        <Blog />
      </Left>
      <AppFooter />
    </div>
  );
};

これで実装するれば以下みたいな感じにアニメーションします

Jul-22-2020 01-20-20

割りかしLPサイトっぽくなったので満足