reactjs 如何使用Framer Motion在具有滑动手势的React组件之间进行转换?

x6492ojm  于 2023-10-17  发布在  React
关注(0)|答案(1)|浏览(101)

bounty还有4天到期。回答此问题可获得+200声望奖励。ephramd正在寻找一个答案从一个有信誉的来源

我刚刚开始使用REACT,我想让它在页面(组件)之间切换,我不仅可以动画过渡,还可以用手指滑动。
换句话说,它显示第1页,我用手指向左滑动,它会加载并同时显示第2页的内容。我可以在两者之间导航,同时保持我的手指按下。当我松开手指时,只剩下一个页面。

在这个例子中,我或多或少用一个按钮来完成,我希望它在使用按钮和滑动时都能工作
我正在尝试Framer Motion,但我不太确定是否需要滑动,拖动...以及如何在组件之间应用它(最终,它们将成为路由)。

// test.jsx
import { motion, AnimatePresence } from 'framer-motion'
import { useState } from 'react'

import { Box } from './Box'

import { AnimeA } from '../framer/AnimeA'

export function Test() {

  const [value, setValue] = useState(1);
  const trans = value % 2 === 0 ? trans1 : trans2;

  return (
    <>
      <div style={{ display: "flex", height: "116px" }}>

            <AnimeA keya={value}  transi={trans}>
                {<Box n={value}/>}
            </AnimeA>

      </div>
      <br/><br/>
      <button type="button" onClick={() => { setValue(value + 1); }}>
        Toggle
      </button>
    </>
    )
  }

  const trans1 = {
    style: { position: "relative", width: "100%", background: "red" },
    initial: { x: -100, opacity: 0 },
    animate: { x: 0, opacity: 1 },
    exit: { x: -100, opacity: 0, transition: { duration: 0.5 } },
    transition: {duration: 0.5 }
  }

  const trans2 = {
    style: { position: "relative", width: "100%", background: "blue" },
    initial:{ x: 100, opacity: 0 },
    animate:{ x: 0, opacity: 1 },
    exit:{ x: 100, opacity: 0, transition: { duration: 0.5 } },
    transition:{ duration: 0.5 }
  }

// AnimeA.jsx
import { motion } from 'framer-motion'
import {  AnimatePresence } from 'framer-motion'

export function AnimeA({ keya, transi, children }) {
  return (
    <AnimatePresence initial={false} mode="popLayout">
        <motion.div key={keya} {...transi}>
            {children}
        </motion.div>
    </AnimatePresence>
  )
}

导出默认AnimeA
“页面(框)不应该被加载和隐藏,要滚动的元素。”

“仅在屏幕首次拖动到一侧时加载。"

kkbh8khc

kkbh8khc1#

解决方案:-
使用Framer Motion提供的useGesture钩子

import { motion, AnimatePresence, useGesture } from 'framer-motion'
import { useState } from 'react'
import { Box } from './Box'
import { AnimeA } from '../framer/AnimeA'

export function Test() {
  const [value, setValue] = useState(1)
  const trans = value % 2 === 0 ? trans1 : trans2
  const bind = useGesture({
    onDragEnd: (event, info) => {
      if (info.offset.x < -100) {
        setValue(value + 1)
      } else if (info.offset.x > 100) {
        setValue(value - 1)
      }
    },
  })

  return (
    <>
      <div style={{ display: 'flex', height: '116px' }}>
        <AnimeA keya={value} transi={trans} {...bind()}>
          {<Box n={value} />}
        </AnimeA>
      </div>
      <br/><br/>
      <button type="button" onClick={() => { setValue(value + 1); }}>
        Toggle
      </button>
    </>
  )
}

const trans1 = {
  style: { position: 'relative', width: '100%', background: 'red' },
  initial: { x: -100, opacity: 0 },
  animate: { x: 0, opacity: 1 },
  exit: { x: -100, opacity: 0, transition: { duration: 0.5 } },
  transition: { duration: 0.5 },
}

const trans2 = {
  style: { position: 'relative', width: '100%', background: 'blue' },
  initial: { x: 100, opacity: 0 },
  animate: { x: 0, opacity: 1 },
  exit: { x: 100, opacity: 0, transition: { duration: 0.5 } },
  transition: { duration: 0.5 },
}

// AnimeA.jsx
import { motion } from 'framer-motion'
import { AnimatePresence } from 'framer-motion'

export function AnimeA({ keya, transi, children }) {
  return (
    <AnimatePresence initial={false} mode="popLayout">
      <motion.div key={keya} {...transi}>
        {children}
      </motion.div>
    </AnimatePresence>
  )
}

相关问题