Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
293 views
in Technique[技术] by (71.8m points)

javascript - Can't scroll on touch devices when having scrollable content (react-use-gesture)

I am using useDrag hook of react-use-gesture to achieve the following animation (switching between chapters) but it does not work on touch devices without touch-action: none;. I have scrollable content, if I set touch-action:none the scroll doesn't work on touch device and if I set touch-action: unset the scroll works but the animation doesn't work.

Any idea on how can I get the following animation working on touch devices? Currently the animation works on non-touch devices.

import clamp from "lodash-es/clamp";
import React, { useRef, useState } from "react";
import { animated, useSprings } from "react-spring";
import { useDrag } from "react-use-gesture";
import chapters from "./chapters";
import "./styles.css";

export default function App() {
  const index = useRef(0);
  const [chapterScrollState, setChapterScrollState] = useState(
    chapters.map(() => -1)
  ); // -1 => top, 0 => between, 1 => bottom
  const [props, set] = useSprings(chapters.length, (i) => ({
    y: i * window.innerHeight,
    scale: 1,
    display: "block"
  }));
  const bind = useDrag(
    ({
      active,
      movement: [mx, my],
      direction: [xDir, yDir],
      distance,
      cancel
    }) => {
      if (chapterScrollState[index.current] === yDir) {
        cancel();
      }

      if (active && distance > window.innerHeight / 2)
        cancel(
          (index.current = clamp(
            index.current + (yDir > 0 ? -1 : 1),
            0,
            chapters.length - 1
          ))
        );
      set((i) => {
        if (i < index.current - 1 || i > index.current + 1)
          return { display: "none" };
        const y = (i - index.current) * window.innerHeight + (active ? my : 0);
        const scale = active ? 1 - distance / window.innerHeight / 2 : 1;
        return { y, scale, display: "block" };
      });
    }
  );

  const onScroll = (e, i) => {
    let scrollState = 0;
    if (
      Math.round(e.target.scrollTop) ===
      e.target.scrollHeight - e.target.offsetHeight
    ) {
      // bottom
      scrollState = 1;
    } else if (e.target.scrollTop === 0) {
      // top
      scrollState = -1;
    }
    setChapterScrollState((prev) => {
      let newArr = [...prev];
      newArr[i] = scrollState;
      return newArr;
    });
  };

  return props.map(({ y, display, scale }, i) => {
    return (
      <animated.div {...bind()} key={i} style={{ display, y }}>
        <animated.div
          className="animatedChapter"
          onScroll={(e) => onScroll(e, i)}
          style={{
            scale
          }}
        >
          <div className="chapter">{chapters[i].content}</div>
        </animated.div>
      </animated.div>
    );
  });
}

* {
  box-sizing: border-box;
}

html,
body {
  overscroll-behavior-y: contain;
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
  user-select: none;
  font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir,
    helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif;
  position: fixed;
  overflow: hidden;
}

#root {
  position: fixed;
  overflow: hidden;
  width: 100%;
  height: 100%;
}

#root > div {
  position: absolute;
  width: 100vw;
  height: 100vh;
  will-change: transform;
}

#root > div > div {
  overflow-y: auto;
  touch-action: none;
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center center;
  width: 100%;
  height: 100%;
  will-change: transform;
  box-shadow: 0 62.5px 125px -25px rgba(50, 50, 73, 0.5),
    0 37.5px 75px -37.5px rgba(0, 0, 0, 0.6);
}

.chapter {
  padding: 30px;
}

CodeSandbox Link

Animation GIF

question from:https://stackoverflow.com/questions/65868378/cant-scroll-on-touch-devices-when-having-scrollable-content-react-use-gesture

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...