触摸支持 React 应用程序上的箭头点击
Touch support for arrow clicks on React app
我正在开发一个 React 网络应用程序,其中有一个 div
的 4x4
grid
,其中有 16 个 blocks
呈现在其中。我有右箭头、左箭头、上箭头和下箭头的箭头单击事件。当仅在移动设备上访问时,我需要为这些箭头点击添加移动触摸支持。我从未实施过这些 touch/swipe 移动功能,因此看起来很混乱。任何帮助将不胜感激。
分量:
const Grid = () => {
const [grid, setGrid] = useState(new Grid());
const arrowLeftKey = 37;
const arrowDownKey = 40;
const handleKeyDown = (event) => {
if (grid.hasWon()) {
return;
}
if (event.keyCode >= arrowLeftKey && event.keyCode <= arrowDownKey) {
let direction = event.keyCode - arrowLeftKey;
let gridClone = Object.assign(
Object.create(Object.getPrototypeOf(grid)),
grid
);
let newGrid = gridClone.move(direction);
setGrid(newGrid);
}
};
useArrowKeyEvent('keydown',handleKeyDown); //hook
const displayBlocks = grid.cells.map((row, rowIndex) => {
return (
<div key={rowIndex}>
{row.map((col, colIndex) => {
return <Block key={rowIndex + colIndex} />;
})}
</div>
);
});
return (
<div className="grid" id="gridId">
{displayBlocks}
</div>
);
我通过谷歌搜索得知我需要使用 Touch Events
,例如 touchStart
、touchMove
、touchEnd
。查看 touchevents documentation 我将以下代码添加到我的组件中。我将 MouseEvents
更改为“KeyBoardevent”。因为这是 arrow key
click
/keydown
事件。但这是行不通的。不知道我哪里做错了。
const onTouch = (evt) => {
evt.preventDefault();
if (evt.touches.length > 1 || (evt.type === "touchend" && evt.touches.length > 0))
return;
var newEvt = document.createEvent("KeyboardEvent");
var type = null;
var touch = null;
// eslint-disable-next-line default-case
switch (evt.type) {
case "touchstart":
type = "keydown";
touch = evt.changedTouches[0];
break;
case "touchmove":
type = "keydown";
touch = evt.changedTouches[0];
break;
case "touchend":
type = "keydown";
touch = evt.changedTouches[0];
break;
}
newEvt.initEvent(type, true, true, evt.originalTarget.ownerDocument.defaultView, 0,
touch.screenX, touch.screenY, touch.clientX, touch.clientY,
evt.keyCode('37'), evt.keyCode('39'), evt.keyCode('38'), evt.keyCode('40'), 0, null);
evt.originalTarget.dispatchEvent(newEvt);
}
document.addEventListener("touchstart", onTouch, true);
document.addEventListener("touchmove", onTouch, true);
document.addEventListener("touchend", onTouch, true);
当我向右滑动并期望点击右箭头时,我收到以下错误:
TypeError: Cannot read property 'ownerDocument' of undefined
在下面的代码行中:
newEvt.initEvent(type, true, true, evt.originalTarget.ownerDocument.defaultView, 0,
touch.screenX, touch.screenY, touch.clientX, touch.clientY,
evt.keyCode('37'), evt.keyCode('39'), evt.keyCode('38'), evt.keyCode('40'), 0, null);
版本 2
编辑::在@sschwei1 建议
后使用react-swipeable
我在组件中添加了以下部分:
const swipeHandlers = useSwipeable({
onSwipedLeft: useArrowKeyEvent('keydown',handleKeyDown),<<<<<problem
onSwipedRight: eventData => console.log("swiped right"),
onSwipedUp: eventData => console.log("swiped up"),
onSwipedDown: eventData => console.log("swiped down")
});
和 return 语句:
<div className="grid" {...swipeHandlers}>
{displayBlocks}
</div>
问题: 无法将钩子用作 callback
函数。
React-swipeable 是一个为您处理滑动的库,它使您能够为不同的滑动方向创建处理程序,例如 onSwipedLeft
或 onSwipedUp
以及几乎所有其他情况想想 onTap
、onSwiping
、onSwiped
等等。
在这些处理程序中,您可以重复使用箭头键的逻辑。
我想到的第一个解决方案(不是最漂亮的解决方案,但易于使用和理解)为滑动创建包装函数并调用相应的 keyHandler 函数
以下是这些函数的示例:
const handleTouch = (key) => {
handleKeyDown({keyCode:key});
}
并且在您的触摸处理程序中,您可以使用相应的键调用此函数
const swipeHandlers = useSwipeable({
onSwipedLeft: () => handleTouch('37'),
onSwipedUp: () => handleTouch('38'),
onSwipedRight: () => handleTouch('39'),
onSwipedDown: () => handleTouch('40')
});
由于您只在 handleKeyDown
函数中使用 keyCode
,因此您只需将带有 keyCode
属性 的对象传递给函数,然后 'simulate' 按键
我正在开发一个 React 网络应用程序,其中有一个 div
的 4x4
grid
,其中有 16 个 blocks
呈现在其中。我有右箭头、左箭头、上箭头和下箭头的箭头单击事件。当仅在移动设备上访问时,我需要为这些箭头点击添加移动触摸支持。我从未实施过这些 touch/swipe 移动功能,因此看起来很混乱。任何帮助将不胜感激。
分量:
const Grid = () => {
const [grid, setGrid] = useState(new Grid());
const arrowLeftKey = 37;
const arrowDownKey = 40;
const handleKeyDown = (event) => {
if (grid.hasWon()) {
return;
}
if (event.keyCode >= arrowLeftKey && event.keyCode <= arrowDownKey) {
let direction = event.keyCode - arrowLeftKey;
let gridClone = Object.assign(
Object.create(Object.getPrototypeOf(grid)),
grid
);
let newGrid = gridClone.move(direction);
setGrid(newGrid);
}
};
useArrowKeyEvent('keydown',handleKeyDown); //hook
const displayBlocks = grid.cells.map((row, rowIndex) => {
return (
<div key={rowIndex}>
{row.map((col, colIndex) => {
return <Block key={rowIndex + colIndex} />;
})}
</div>
);
});
return (
<div className="grid" id="gridId">
{displayBlocks}
</div>
);
我通过谷歌搜索得知我需要使用 Touch Events
,例如 touchStart
、touchMove
、touchEnd
。查看 touchevents documentation 我将以下代码添加到我的组件中。我将 MouseEvents
更改为“KeyBoardevent”。因为这是 arrow key
click
/keydown
事件。但这是行不通的。不知道我哪里做错了。
const onTouch = (evt) => {
evt.preventDefault();
if (evt.touches.length > 1 || (evt.type === "touchend" && evt.touches.length > 0))
return;
var newEvt = document.createEvent("KeyboardEvent");
var type = null;
var touch = null;
// eslint-disable-next-line default-case
switch (evt.type) {
case "touchstart":
type = "keydown";
touch = evt.changedTouches[0];
break;
case "touchmove":
type = "keydown";
touch = evt.changedTouches[0];
break;
case "touchend":
type = "keydown";
touch = evt.changedTouches[0];
break;
}
newEvt.initEvent(type, true, true, evt.originalTarget.ownerDocument.defaultView, 0,
touch.screenX, touch.screenY, touch.clientX, touch.clientY,
evt.keyCode('37'), evt.keyCode('39'), evt.keyCode('38'), evt.keyCode('40'), 0, null);
evt.originalTarget.dispatchEvent(newEvt);
}
document.addEventListener("touchstart", onTouch, true);
document.addEventListener("touchmove", onTouch, true);
document.addEventListener("touchend", onTouch, true);
当我向右滑动并期望点击右箭头时,我收到以下错误:
TypeError: Cannot read property 'ownerDocument' of undefined
在下面的代码行中:
newEvt.initEvent(type, true, true, evt.originalTarget.ownerDocument.defaultView, 0,
touch.screenX, touch.screenY, touch.clientX, touch.clientY,
evt.keyCode('37'), evt.keyCode('39'), evt.keyCode('38'), evt.keyCode('40'), 0, null);
版本 2 编辑::在@sschwei1 建议
后使用react-swipeable
我在组件中添加了以下部分:
const swipeHandlers = useSwipeable({
onSwipedLeft: useArrowKeyEvent('keydown',handleKeyDown),<<<<<problem
onSwipedRight: eventData => console.log("swiped right"),
onSwipedUp: eventData => console.log("swiped up"),
onSwipedDown: eventData => console.log("swiped down")
});
和 return 语句:
<div className="grid" {...swipeHandlers}>
{displayBlocks}
</div>
问题: 无法将钩子用作 callback
函数。
React-swipeable 是一个为您处理滑动的库,它使您能够为不同的滑动方向创建处理程序,例如 onSwipedLeft
或 onSwipedUp
以及几乎所有其他情况想想 onTap
、onSwiping
、onSwiped
等等。
在这些处理程序中,您可以重复使用箭头键的逻辑。
我想到的第一个解决方案(不是最漂亮的解决方案,但易于使用和理解)为滑动创建包装函数并调用相应的 keyHandler 函数
以下是这些函数的示例:
const handleTouch = (key) => {
handleKeyDown({keyCode:key});
}
并且在您的触摸处理程序中,您可以使用相应的键调用此函数
const swipeHandlers = useSwipeable({
onSwipedLeft: () => handleTouch('37'),
onSwipedUp: () => handleTouch('38'),
onSwipedRight: () => handleTouch('39'),
onSwipedDown: () => handleTouch('40')
});
由于您只在 handleKeyDown
函数中使用 keyCode
,因此您只需将带有 keyCode
属性 的对象传递给函数,然后 'simulate' 按键