Fix token remove for touch devices
This commit is contained in:
parent
be7d6c5277
commit
73c7ca91fa
@ -1,4 +1,4 @@
|
|||||||
import React, { useContext } from "react";
|
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||||
import { Box, IconButton } from "theme-ui";
|
import { Box, IconButton } from "theme-ui";
|
||||||
|
|
||||||
import RemoveTokenIcon from "../../icons/RemoveTokenIcon";
|
import RemoveTokenIcon from "../../icons/RemoveTokenIcon";
|
||||||
@ -19,29 +19,92 @@ function TokenDragOverlay({
|
|||||||
MapInteractionContext
|
MapInteractionContext
|
||||||
);
|
);
|
||||||
|
|
||||||
function handleTokenRemove() {
|
const [isRemoveHovered, setIsRemoveHovered] = useState(false);
|
||||||
// Handle other tokens when a vehicle gets deleted
|
const removeTokenRef = useRef();
|
||||||
if (token.isVehicle) {
|
|
||||||
const layer = tokenImage.getLayer();
|
// Detect token hover on remove icon manually to support touch devices
|
||||||
const mountedTokens = tokenImage.find(".token");
|
useEffect(() => {
|
||||||
for (let mountedToken of mountedTokens) {
|
const map = document.querySelector(".map");
|
||||||
// Save and restore token position after moving layer
|
const mapRect = map.getBoundingClientRect();
|
||||||
const position = mountedToken.absolutePosition();
|
|
||||||
mountedToken.moveTo(layer);
|
function detectRemoveHover() {
|
||||||
mountedToken.absolutePosition(position);
|
const pointerPosition = tokenImage.getStage().getPointerPosition();
|
||||||
onTokenStateChange({
|
const screenSpacePointerPosition = {
|
||||||
[mountedToken.id()]: {
|
x: pointerPosition.x + mapRect.left,
|
||||||
...mapState.tokens[mountedToken.id()],
|
y: pointerPosition.y + mapRect.top,
|
||||||
x: mountedToken.x() / mapWidth,
|
};
|
||||||
y: mountedToken.y() / mapHeight,
|
const removeIconPosition = removeTokenRef.current.getBoundingClientRect();
|
||||||
lastEditedBy: userId,
|
|
||||||
},
|
if (
|
||||||
});
|
screenSpacePointerPosition.x > removeIconPosition.left &&
|
||||||
|
screenSpacePointerPosition.y > removeIconPosition.top &&
|
||||||
|
screenSpacePointerPosition.x < removeIconPosition.right &&
|
||||||
|
screenSpacePointerPosition.y < removeIconPosition.bottom
|
||||||
|
) {
|
||||||
|
if (!isRemoveHovered) {
|
||||||
|
setIsRemoveHovered(true);
|
||||||
|
}
|
||||||
|
} else if (isRemoveHovered) {
|
||||||
|
setIsRemoveHovered(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onTokenStateRemove(tokenState);
|
|
||||||
setPreventMapInteraction(false);
|
let handler;
|
||||||
}
|
if (tokenState && tokenImage) {
|
||||||
|
handler = setInterval(detectRemoveHover, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (handler) {
|
||||||
|
clearInterval(handler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [tokenState, tokenImage, isRemoveHovered]);
|
||||||
|
|
||||||
|
// Detect drag end of token image and remove it if it is over the remove icon
|
||||||
|
useEffect(() => {
|
||||||
|
function handleTokenDragEnd() {
|
||||||
|
if (isRemoveHovered) {
|
||||||
|
// Handle other tokens when a vehicle gets deleted
|
||||||
|
if (token.isVehicle) {
|
||||||
|
const layer = tokenImage.getLayer();
|
||||||
|
const mountedTokens = tokenImage.find(".token");
|
||||||
|
for (let mountedToken of mountedTokens) {
|
||||||
|
// Save and restore token position after moving layer
|
||||||
|
const position = mountedToken.absolutePosition();
|
||||||
|
mountedToken.moveTo(layer);
|
||||||
|
mountedToken.absolutePosition(position);
|
||||||
|
onTokenStateChange({
|
||||||
|
[mountedToken.id()]: {
|
||||||
|
...mapState.tokens[mountedToken.id()],
|
||||||
|
x: mountedToken.x() / mapWidth,
|
||||||
|
y: mountedToken.y() / mapHeight,
|
||||||
|
lastEditedBy: userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onTokenStateRemove(tokenState);
|
||||||
|
setPreventMapInteraction(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tokenImage.on("dragend", handleTokenDragEnd);
|
||||||
|
return () => {
|
||||||
|
tokenImage.off("dragend", handleTokenDragEnd);
|
||||||
|
};
|
||||||
|
}, [
|
||||||
|
tokenImage,
|
||||||
|
token,
|
||||||
|
tokenState,
|
||||||
|
isRemoveHovered,
|
||||||
|
mapWidth,
|
||||||
|
mapHeight,
|
||||||
|
userId,
|
||||||
|
onTokenStateChange,
|
||||||
|
onTokenStateRemove,
|
||||||
|
setPreventMapInteraction,
|
||||||
|
mapState.tokens,
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -50,15 +113,15 @@ function TokenDragOverlay({
|
|||||||
bottom: "24px",
|
bottom: "24px",
|
||||||
left: "50%",
|
left: "50%",
|
||||||
borderRadius: "50%",
|
borderRadius: "50%",
|
||||||
transform: "translateX(-50%) scale(1.5)",
|
transform: isRemoveHovered
|
||||||
|
? "translateX(-50%) scale(2.0)"
|
||||||
|
: "translateX(-50%) scale(1.5)",
|
||||||
transition: "transform 250ms ease",
|
transition: "transform 250ms ease",
|
||||||
":hover": {
|
color: isRemoveHovered ? "primary" : "text",
|
||||||
transform: "translateX(-50%) scale(2.0)",
|
pointerEvents: "none",
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
bg="overlay"
|
bg="overlay"
|
||||||
onMouseUp={handleTokenRemove}
|
ref={removeTokenRef}
|
||||||
onTouchEnd={handleTokenRemove}
|
|
||||||
>
|
>
|
||||||
<IconButton>
|
<IconButton>
|
||||||
<RemoveTokenIcon />
|
<RemoveTokenIcon />
|
||||||
|
Loading…
Reference in New Issue
Block a user