3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have 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

.tsx
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)だけ横スクロールします。
縦のスクロール量を絶対値で割ることで、+/-を取得しています。

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

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

.tsx
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
}
3
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
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?