開発者ドキュメント

Reactとstyled-componentsを使用したページスクロールのプログレスバー

これを含む多くの人気のあるブログで見たかもしれないページスクロール効果のプログレスバーを再実装しましょう。

どうやってやるの?

これを実装するには、 React styled-components 、および DocumentonScrollイベントを使用します。 それで、それ以上の苦労なしに、始めましょう。

インストール

前述のように、Reactstyled-componentsを使用して、進行状況のスクロール効果を実装します。 時間を節約するために、 Create React App を使用して、クイックReactアプリケーションをブートストラップします。

したがって、ターミナルを開いて、次のコマンドを実行します。

$ create-react-app app-name
$ cd app-name

`create-react-app`がインストールされていませんか? 次に、このコマンドを使用できます$ npx create-react-app app-name

次は、新しく作成したプロジェクトにstyled-componentsもインストールする必要があります。 したがって、プロジェクトディレクトリにいる間に、

$ npm install styled-components -S

ここで、ターミナルでnpm startを実行すると、次のように表示されます。


レイアウトの設計

アプリケーションがセットアップされたので、実際のコードを書き始めましょう。 まず、ページレイアウトを作成し、CSSを記述してレイアウトのスタイルを設定します。

src/App.jsファイルに移動し、ファイル内のすべてを削除して、次のコード行を追加します。

src / App.js
import React, { Component } from 'react';
import './App.css';

export default class App extends Component {
  render() {
    return (
      <div className="App">
        <header></header>
        <main>
          <h1>Lorem Ipsum</h1>
          <p>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
          </p>
          <p>...more paragraphs of text, enough so that the page gets a scrollbar</p>
        </main>
      </div>
    );
  }
}

基本的に、私たちが行ったのは、create-react-appが生成したステートレス機能コンポーネントをクラスベースのコンポーネントに変換することです。 また、ページを埋めるためにダミーのテキストコンテンツを追加しました。

ここでクールにして、レイアウトに簡単なスタイルを追加します。 src/App.cssを開き、その中のすべてを削除してから、次のCSS行を追加します。

header {
  background: linear-gradient(to right, #302E24, #28313E);
  height: 60px;
  width: 100%;
  box-shadow: 0 2px 20px 0 rgba(0, 0, 0, .1);
  margin-bottom: 70px;
}

.App p, .App h1 {
  margin: 30px auto;
  width: 800px;
}

npm startを実行すると、次のようなものが表示されます。


プログレスバーを設計する

さて、私たちの議題の次のことは、プログレスバーを設計することです。 これを実装するために、インストールしたstyled-componentsライブラリを利用します。

srcフォルダにProgress.jsという名前のファイルを作成しましょう。 それが完了したら、次のコード行をファイルに追加します。

src / Progress.js
import styled from 'styled-components';

const  Progress  =  styled.div`
  position:  fixed;
  background:  linear-gradient(
    to right,
    rgba(250, 224, 66, .8) ${props => props.scroll},
    transparent  0);
  width:  100%;
  height:  4px;
  z-index:  3;
`;

export  default  Progress;

それでは、App.jsファイルに戻り、新しく作成されたProgressコンポーネントを利用してみましょう。

src / App.js
import React, { Component } from 'react';
import './App.css';
import Progress from './Progress';

export default class App extends Component {
  render() {
    return (
      <div className="App">
        <Progress scroll="70%" />
        {/* ... */}
      </div>
    );
  }
}

了解しました。これまでの状況を確認する良い機会だと思います。 それでは、npm startをもう一度実行して、アプリケーションを確認してみましょう。 すべてがうまくいけば、次のようなものが必要です。


スクロールロジックの追加

ここに、スクロールロジックを実装する楽しい部分があります。 実際のコードを書き始める前に、これを達成するために必要な手順の概要を説明しましょう。

さて、擬似コードを実際のコードに変換しましょう


ドキュメントオブジェクトのスクロールイベントをリッスンします

では、App.jsファイルで、DOMのスクロールイベントをリッスンするlistenToScrollEventというメソッドを作成しましょう。 このメソッドは次のようになります。

src / App.js
listenToScrollEvent = () => {
  document.addEventListener("scroll", () => {
    requestAnimationFrame(() => {
      // Calculates the scroll distance
      this.calculateScrollDistance();
    });
  });
};

このメソッドは、Documentオブジェクトで発生するスクロールイベントをリッスンし、 requestAnimationFrame を呼び出します。これにより、アニメーションが実行されようとしていることがブラウザに通知されます。 次に、ブラウザはrequestAnimationFrameで指定されたcalculateScrollDistanceメソッドを呼び出します。

最後に、Appコンポーネントがマウントされるたびにこのメソッドを呼び出す必要があります。 そのため、Reactのライフサイクルメソッドの1つであるcomponentDidMountを利用して、listenToScrollEventメソッドを呼び出します。

src / App.js
componentDidMount()  {
  this.listenToScrollEvent();
}

それでは、calculateScrollDistanceメソッドの定義に取り掛かりましょう。


ユーザーの現在のスクロール距離を決定する

ユーザーの現在のスクロール距離を計算するには、いくつかのことを行う必要があります。

ユーザーがスクロールした量を取得する

現在のユーザーのスクロール距離を計算するために、windowsオブジェクトで使用可能なpageYOffset値を利用できます。

それでは、calculateScrollDistanceメソッドを作成し、メソッドに次の行を追加しましょう。

src / App.js
calculateScrollDistance = () => {
  const scrollTop = window.pageYOffset;
}

古いIEブラウザの場合、以下も機能するはずですdocument.body.scrollTop

ブラウザの高さを取得する

次に、ブラウザの高さを取得する必要があります。そのために、windowオブジェクトを介してアクセスできるinnerHeight値を利用できます。

ブラウザの高さは、単に表示可能なブラウザ(ChromeまたはFirefox)領域の高さを指します。

calculateScrollDistanceに戻り、ブラウザウィンドウの高さを取得する行を追加しましょう。

src / App.js
calculateScrollDistance = () => {
  const scrollTop = window.pageYOffset;
  const windowHeight = window.innerHeight;
}

古いIEブラウザの場合、以下も機能するはずですdocument.body.clientHeight

ドキュメントの高さを取得する

現在、ドキュメントの高さを取得するのは難しいです。この背後にある理由は、さまざまなブラウザがドキュメントの高さを解釈または計算する方法が異なるためです。

これを回避するには、さまざまなブラウザがドキュメントの高さを取得するために使用するさまざまなプロパティを確認し、Math.max()を使用して最大値を取得する必要があります。

それでは、getDocHeightというメソッドを作成し、次のコード行を追加して、これをすばやく実装しましょう。

src / App.js
getDocHeight  =  ()  =>  {
  return Math.max(
    document.body.scrollHeight,  document.documentElement.scrollHeight,
    document.body.offsetHeight,  document.documentElement.offsetHeight,
    document.body.clientHeight,  document.documentElement.clientHeight
  );
}

次に、calculateScrollDistanceメソッドのメソッドを次のように呼び出します。

src / App.js
calculateScrollDistance = () => {
  const scrollTop = window.pageYOffset;
  const windowHeight = window.innerHeight;
  const docHeight = this.getDocHeight();
}

必要な値がすべて揃ったので、ドキュメントの利用可能なスクロール長の合計(docHeight-winHeight)からscrollTopを除算し、結果に100を掛けて、ユーザーがスクロールしたパーセンテージを計算できます。結果はパーセンテージで表示されます。

したがって、次の行をコードに追加します。

src / App.js
calculateScrollDistance = () => {
  const scrollTop = window.pageYOffset;
  const windowHeight = window.innerHeight;
  const docHeight = this.getDocHeight();

  const  totalDocScrollLength  =  docHeight  -  winHeight;
  const  scrollPostion  =  Math.floor(scrollTop  /  totalDocScrollLength  *  100)
}

スクロール位置ができたので、state変数を追加する必要があります。この変数は、ユーザーの現在のスクロール位置で更新できます。 これを行うには、src/App.jsファイルに状態オブジェクトを作成し、scrollPositionを追加してから、初期状態を0に設定する必要があります。

src / App.js
// ...
state = {
  scrollPosition: 0
}

calculateScrollDistanceメソッドに戻り、Reactが提供するsetStateメソッドを使用する必要があります。これは、scrollPositionの状態を更新するのに役立ちます。

src / App.js
calculateScrollDistance = () => {
  // ...
  this.setState({
    scrollPosition,
  });
}

したがって、最終的なコードは次のようになります。-

src / App.js
// ...

state = {
  scrollPosition: 0
}

calculateScrollDistance  =  ()  =>  {
  const  scrollTop  =  window.pageYOffset;
  const  winHeight  =  window.innerHeight;
  const  docHeight  =  this.getDocHeight();

  const  totalDocScrollLength = docHeight  -  winHeight;
  const  scrollPostion  =  Math.floor(scrollTop  /  totalDocScrollLength  *  100);

  this.setState({
    scrollPostion,
  });
}

// ...

scrollPosition状態でプログレスバーを更新します

最後に、scrollPosition状態をProgressバーコンポーネントに渡すだけです。

{/* ... */}
<Progress  scroll={ this.state.scrollPostion  +  '%' }  />

したがって、最終的な完全なコードは次のようになります。-

import React, { Component } from 'react';
import Progress from './Progress';
import './App.css';

export default class App extends Component {
  state = {
    scrollPostion: 0
  }

  listenToScrollEvent = () => {
    document.addEventListener("scroll", () => {
      requestAnimationFrame(() => {
        this.calculateScrollDistance();
      });
    });
  }

  calculateScrollDistance = () => {
    const scrollTop = window.pageYOffset; // how much the user has scrolled by
    const winHeight = window.innerHeight;
    const docHeight = this.getDocHeight();

    const totalDocScrollLength = docHeight - winHeight;
    const scrollPostion = Math.floor(scrollTop / totalDocScrollLength * 100)

    this.setState({
      scrollPostion,
    });
  }

  getDocHeight = () => {
    return Math.max(
      document.body.scrollHeight, document.documentElement.scrollHeight,
      document.body.offsetHeight, document.documentElement.offsetHeight,
      document.body.clientHeight, document.documentElement.clientHeight
    );
  }

  componentDidMount() {
    this.listenToScrollEvent();
  }

  render() {
    return (
      <div className="App">
        <Progress scroll={this.state.scrollPostion + '%'} />
        <header></header>
        <main>
          <h1>Lorem Ipsum</h1>
          <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
          </p>
          <p>
          ...
          </p>
        </main>
      </div>
    );
  }
}

そして、これらすべてが整ったので、ページスクロールに進行状況バーが表示されるはずです。


それはすべての人々です

ふぅ! 🤗皆さん、これで、進行状況のスクロール効果を正常に作成できました。 うまくいけば、あなたはそれが役に立つと思うでしょう!

モバイルバージョンを終了