Reactとstyled-componentsを使用したページスクロールのプログレスバー
これを含む多くの人気のあるブログで見たかもしれないページスクロール効果のプログレスバーを再実装しましょう。
どうやってやるの?
これを実装するには、 React 、 styled-components 、および DocumentonScrollイベントを使用します。 それで、それ以上の苦労なしに、始めましょう。
インストール
前述のように、React
とstyled-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
ファイルに移動し、ファイル内のすべてを削除して、次のコード行を追加します。
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
という名前のファイルを作成しましょう。 それが完了したら、次のコード行をファイルに追加します。
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
コンポーネントを利用してみましょう。
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
をもう一度実行して、アプリケーションを確認してみましょう。 すべてがうまくいけば、次のようなものが必要です。
スクロールロジックの追加
ここに、スクロールロジックを実装する楽しい部分があります。 実際のコードを書き始める前に、これを達成するために必要な手順の概要を説明しましょう。
document
オブジェクトのスクロールイベントをリッスンします- ユーザーの現在のスクロール距離を決定する
- 現在のスクロールパーセンテージを保持する状態変数があります
- 最後に、進行状況のスクロールを新しい状態のパーセンテージで更新します
さて、擬似コードを実際のコードに変換しましょう
ドキュメントオブジェクトのスクロールイベントをリッスンします
では、App.js
ファイルで、DOMのスクロールイベントをリッスンするlistenToScrollEvent
というメソッドを作成しましょう。 このメソッドは次のようになります。
listenToScrollEvent = () => {
document.addEventListener("scroll", () => {
requestAnimationFrame(() => {
// Calculates the scroll distance
this.calculateScrollDistance();
});
});
};
このメソッドは、Document
オブジェクトで発生するスクロールイベントをリッスンし、 requestAnimationFrame を呼び出します。これにより、アニメーションが実行されようとしていることがブラウザに通知されます。 次に、ブラウザはrequestAnimationFrame
で指定されたcalculateScrollDistance
メソッドを呼び出します。
最後に、App
コンポーネントがマウントされるたびにこのメソッドを呼び出す必要があります。 そのため、Reactのライフサイクルメソッドの1つであるcomponentDidMount
を利用して、listenToScrollEvent
メソッドを呼び出します。
componentDidMount() {
this.listenToScrollEvent();
}
それでは、calculateScrollDistance
メソッドの定義に取り掛かりましょう。
ユーザーの現在のスクロール距離を決定する
ユーザーの現在のスクロール距離を計算するには、いくつかのことを行う必要があります。
- ユーザーがスクロールした量を取得する必要があります
- ブラウザの高さを取得する必要があります
- ドキュメントの高さを取得する必要があります
ユーザーがスクロールした量を取得する
現在のユーザーのスクロール距離を計算するために、windows
オブジェクトで使用可能なpageYOffset
値を利用できます。
それでは、calculateScrollDistance
メソッドを作成し、メソッドに次の行を追加しましょう。
calculateScrollDistance = () => {
const scrollTop = window.pageYOffset;
}
古いIEブラウザの場合、以下も機能するはずですdocument.body.scrollTop
ブラウザの高さを取得する
次に、ブラウザの高さを取得する必要があります。そのために、window
オブジェクトを介してアクセスできるinnerHeight
値を利用できます。
ブラウザの高さは、単に表示可能なブラウザ(ChromeまたはFirefox)領域の高さを指します。
calculateScrollDistance
に戻り、ブラウザウィンドウの高さを取得する行を追加しましょう。
calculateScrollDistance = () => {
const scrollTop = window.pageYOffset;
const windowHeight = window.innerHeight;
}
古いIEブラウザの場合、以下も機能するはずですdocument.body.clientHeight
ドキュメントの高さを取得する
現在、ドキュメントの高さを取得するのは難しいです。この背後にある理由は、さまざまなブラウザがドキュメントの高さを解釈または計算する方法が異なるためです。
これを回避するには、さまざまなブラウザがドキュメントの高さを取得するために使用するさまざまなプロパティを確認し、Math.max()
を使用して最大値を取得する必要があります。
それでは、getDocHeight
というメソッドを作成し、次のコード行を追加して、これをすばやく実装しましょう。
getDocHeight = () => {
return Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight
);
}
次に、calculateScrollDistance
メソッドのメソッドを次のように呼び出します。
calculateScrollDistance = () => {
const scrollTop = window.pageYOffset;
const windowHeight = window.innerHeight;
const docHeight = this.getDocHeight();
}
必要な値がすべて揃ったので、ドキュメントの利用可能なスクロール長の合計(docHeight-winHeight)からscrollTop
を除算し、結果に100を掛けて、ユーザーがスクロールしたパーセンテージを計算できます。結果はパーセンテージで表示されます。
したがって、次の行をコードに追加します。
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に設定する必要があります。
// ...
state = {
scrollPosition: 0
}
calculateScrollDistance
メソッドに戻り、Reactが提供するsetState
メソッドを使用する必要があります。これは、scrollPosition
の状態を更新するのに役立ちます。
calculateScrollDistance = () => {
// ...
this.setState({
scrollPosition,
});
}
したがって、最終的なコードは次のようになります。-
// ...
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>
);
}
}
そして、これらすべてが整ったので、ページスクロールに進行状況バーが表示されるはずです。
それはすべての人々です
ふぅ! 🤗皆さん、これで、進行状況のスクロール効果を正常に作成できました。 うまくいけば、あなたはそれが役に立つと思うでしょう!