😄

Lenisで慣性スクロールを作るメモ

2024/09/02に公開

Lenisで慣性スクロールを作るメモ

Lenis.jsを使用したら、慣性スクロールという挙動が簡単に実装できると聞いたので、お試しにページを作るメモ

初期設定

インストール

npm i lenis

CSSファイル

おすすめでCSSを書く。書いた場合は読み込むのを忘れないようにする

html.lenis, html.lenis body {
  height: auto;
}

.lenis.lenis-smooth {
  scroll-behavior: auto !important;
}

.lenis.lenis-smooth [data-lenis-prevent] {
  overscroll-behavior: contain;
}

.lenis.lenis-stopped {
  overflow: hidden;
}

.lenis.lenis-smooth iframe {
  pointer-events: none;
}

基本的な書き方

useLenisLenisインスタンスを返すらしい。
root属性はページ全体のスクロール制御を行うように示す
options

  • lerp: スクロール効果の線形補完値を示す。値が低いほどスクロールがスムーズになる。
  • duration: スクロール効果の継続時間
  • smoothTouch: スマホなどタッチデバイス対応

その他

import { ReactLenis, useLenis } from 'lenis/react'

function Layout() {
  const lenis = useLenis(({ scroll }) => {
    // called every scroll
  })

  return (
    <ReactLenis root>
      { /* content */ }
    </ReactLenis>
  )
}

お試しページを作る

スクロールすると、プログレスバーが表示されあとどのくらいページがスクロールできるかを示すページを作ってみる

前提条件

Reactで実装します。TailwindCSSもあらかじめインストールされているものとします。

必要パッケージ・ライブラリのインストール

  • lenis
  • react-markdown
  • @tailwindcss/typography(プラグインの設定は参考ページを見てください)

コード

useLenisの使い方がまだいまいち分からないので、ドキュメントを読まなければいけない

  • useEffect内でスクロールの進捗率を計算し、stateに保存
  • SSRで取得したマークダウンの文字列をreact-markdownで解析してHTMLとして表示する。@tailwindcss/typographyでさくっとスタイルを調整する。
import { cn } from '@/utils/cn';
import { ReactLenis, useLenis } from 'lenis/react'
import { useRef, useState } from 'react';
import { readFileSync } from 'fs';
import { join } from 'path';
import { cwd } from 'process';
import { getYamlHeaderFromString } from '@/utils/get-yaml-header';
import Markdown from "react-markdown"

interface Props {
  content: string;
}

const Code3 = (props: Props) => {
  const {
    content
  } = props;
  const [scrolled, setScrolled] = useState<number>(0);

  useLenis(({ scroll }) => {
    const scrollHeight =
      (document.documentElement && document.documentElement.scrollHeight) ||
      document.body.scrollHeight;
    const clientHeight =
      document.documentElement.clientHeight || window.innerHeight;

    setScrolled(scroll / (scrollHeight - clientHeight));
    
  });

  return (
    <main className="min-h-screen min-w-screen overflow-hidden relative">
      <ReactLenis
        root
        options={{ 
          lerp: 0.1, 
          duration: 3,
          smoothWheel: true
        }}
      >
        <div className={cn('w-full flex flex-col relative')}>
          <div
            className={cn('h-1 block bg-teal-500 fixed origin-[0%] top-0 left-0')}
            style={{  
              width: `calc(100%*${scrolled})`
            }}
            />
          <div className={cn(
            "m-auto py-16 flex flex-col justify-center [&>*]:mb-12 font-yumin prose",
            )} >
            <Markdown
              >
                {content}
              </Markdown>
          </div>
        </div>
      </ReactLenis>
    </main>
  )
}

export const getServerSideProps = () => {
  const fileContent = readFileSync(
    join(cwd(), "src", "contents", "demo.md"),
    "utf-8",
  );
  const { content } = getYamlHeaderFromString(fileContent);

  return {
    props: {
      content: content,
    },
  };
};
  

export default Code3;

実際の画面

あまり慣性スクロールになっているか映像ではわかりにくい
実際の画面

参考

最後に

間違っていることあればコメントに書いていただけると幸いです。
よろしくお願いいたします。

GitHubで編集を提案

Discussion