javascript - 具有可滚动内容时无法在触摸设备上滚动(react-use-gesture)
问题描述
我正在使用 react-use-gesture 的 useDrag 钩子来实现以下动画(在章节之间切换),但它不适用于没有touch-action: none;
. 我有可滚动的内容,如果我设置touch-action:none
滚动在触摸设备上不起作用,并且如果我设置touch-action: unset
滚动有效但动画不起作用。
关于如何在触摸设备上获得以下动画的任何想法?目前,动画适用于非触摸设备。
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;
}
解决方案
推荐阅读
- appveyor - 仅当矩阵中的所有构建都成功时,如何从 Appveyor 构建推送 NuGet 包?
- r - 使用 sf 和 sp 在 R 中的投影差异
- git - 在 github 上拉远程 master 分支的问题
- android - 使用 INNER JOIN 删除 Room 中的数据?
- css - Wordpress / CSS 文件仅适用于后端的一个菜单页
- javascript - forEach 在 Microsoft Edge 中不起作用
- symfony - 在某些情况下防止教义 postLoad 事件
- iis - ActiveX 组件无法在 w3wp.exe 中创建对象
- python - Selenium WebDriver 写入 CSV 文件时出现意外结果
- android - 尽管应用程序被杀死,服务仍在运行