LoginSignup
2
1

More than 1 year has passed since last update.

【React】Mapのようにスワイプ移動できるページを実装する

Last updated at Posted at 2021-10-13

概要

Google Mapのようにドラッグ操作でスワイプできるページを実装します。

https://vw5z8.csb.app/
output(video-cutter-js.com).gif

ドラッグ操作には、Framer Motionを使用します。

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

実装

下図は実装のイメージです。

screenが移動するのではなく、paperだけが移動すると考えてください。

  • screenは、ブラウザの表示領域(1vw・1vhの範囲)です。
  • 今回は縦横がscreenの2倍を領域をもつマップを作成したので、paperは2vw・2vhになっています。
  • containerは、paperの可動域です。screenに表示されるのが、#44B3C2パネルの左上から、#5D4C46パネルの右下までにしたいので、3vw・3vhとなっています。
import { motion } from 'framer-motion';
import React, { useRef, VFC } from 'react';
import { css } from '@emotion/css';

export const MapPage: VFC = () => {
    const containerRef = useRef<HTMLDivElement>(null)

    return (
        <motion.div ref={containerRef} className={styles.container}>
            <motion.div className={styles.paper} drag dragPropagation dragConstraints={containerRef}>
                <div className={styles.panel('#44B3C2')}>
                    <div className={styles.text}>Panel 1</div>
                </div>
                <div className={styles.panel('#F1A94E')}>
                    <div className={styles.text}>Panel 2</div>
                </div>
                <div className={styles.panel('#E45641')}>
                    <div className={styles.text}>Panel 3</div>
                </div>
                <div className={styles.panel('#5D4C46')}>
                    <div className={styles.text}>Panel 4</div>
                </div>
            </motion.div>
        </motion.div>
    )
}

const styles = {
    container: css`
        position: relative;
        width: 300vw;
        height: 300vh;
        /* (300 - 100) / 2 */
        transform: translate(-100vw, -100vh);
        display: flex;
        justify-content: center;
        align-items: center;
    `,
    paper: css`
        position: absolute;
        width: 200vw;
        height: 200vh;
        display: flex;
        flex-wrap: wrap;
        /* start page1 */
        top: 100vh;
        left: 100vw;
    `,
    panel: (bgColor: string) => css`
        width: 50%;
        height: 50%;
        background-color: ${bgColor};
        display: flex;
        justify-content: center;
        align-items: center;
    `,
    text: css`
        color: white;
        font-size: 3rem;
    `
}

paper(styles.paperを割り当ててるdiv)要素をスワイプさせたいので、ドラッグに関するプロパティを割り当てます。

  • drag:要素をドラッグできるようにする
  • dragPropagation:親要素をドラッグしたときに子要素も移動するようにする
  • dragConstraints:ドラッグできる領域を決める。今回はcontainer要素を可動域にしたいので、containerRefを割り当てています。

Framer MotionのDragについて詳しく知りたい方は、以下を参照してください。

成果物

2
1
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
2
1