LoginSignup
1
5

More than 1 year has passed since last update.

【React】縦スクロールをすると横にスライドするページを実装する

Posted at

概要

縦スクロールする(マウスホイールする)と、ページが横に切り替わるコンポーネントを実装します。

output(video-cutter-js.com) (6).gif

スタイリングには、emotion/css(CSS in JS)を使用しています。

実装

実装のイメージ図です。主要なCSSプロパティを記述しています。

スクリーンショット 2021-10-03 163643.png

import React, { useEffect, useRef, VFC } from 'react';
import { css } from '@emotion/css';

export const ParallaxHorizontalScrollPage: VFC = () => {
    const screenRef = useRef<HTMLDivElement>(null)

    useEffect(() => {
        screenRef.current!.onwheel = ev => {
            ev.preventDefault()

            let delta = (ev.deltaY / Math.abs(ev.deltaY)) * window.innerWidth
            if (delta > 0) {
                delta += screenRef.current!.scrollLeft
                delta = Math.floor(delta / window.innerWidth) * window.innerWidth
            } else {
                delta += screenRef.current!.scrollLeft
                delta = Math.ceil(delta / window.innerWidth) * window.innerWidth
            }
            screenRef.current!.scrollLeft = delta
        }
    }, [])

    return (
        <div ref={screenRef} className={styles.screen}>
            <div className={styles.container}>
                <div className={styles.page('#0085d1')}>
                    <div className={styles.text}>Page 1</div>
                </div>
                <div className={styles.page('#db0063')}>
                    <div className={styles.text}>Page 2</div>
                </div>
                <div className={styles.page('#ffcd43')}>
                    <div className={styles.text}>Page 3</div>
                </div>
            </div>
        </div>
    )
}

const styles = {
    screen: css`
        position: relative;
        width: 100vw;
        height: 100vh;
        overflow: auto;
        scroll-behavior: smooth;
    `,
    container: css`
        width: 300vw;
        height: 100%;
        display: flex;
    `,
    page: (bgColor: string) => css`
        position: relative;
        width: 100vw;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        background-color: ${bgColor};
    `,
    text: css`
        font-size: 3rem;
        color: white;
    `
}

useEffectの中で、screen(CSS名のdiv要素)に対してスクロール量を調整しています。

deltaは横のスクロール量で、1回の縦スクロールで画面幅(innerWidth)だけ横スクロールします。
縦のスクロール量を絶対値で割ることで、+/-を取得しています。

let delta = (ev.deltaY / Math.abs(ev.deltaY)) * window.innerWidth

以下のコードでは、ページを途中まで手動で横スクロールしているときに、縦スクロールをしたときの横のスクロール量を決めています。
これによって、デモ(記事上部のGIF)のような動作になります。

if (delta > 0) {
    delta += screenRef.current!.scrollLeft
    delta = Math.floor(delta / window.innerWidth) * window.innerWidth
} else {
    delta += screenRef.current!.scrollLeft
    delta = Math.ceil(delta / window.innerWidth) * window.innerWidth
}
1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5