Files
grungnet/src/components/token/TokenDragOverlay.js

124 lines
3.6 KiB
JavaScript
Raw Normal View History

2020-05-25 13:12:30 +10:00
import React, { useContext, useEffect, useRef, useState } from "react";
2020-05-21 22:57:44 +10:00
import { Box, IconButton } from "theme-ui";
import RemoveTokenIcon from "../../icons/RemoveTokenIcon";
import AuthContext from "../../contexts/AuthContext";
2020-05-21 22:57:44 +10:00
import MapInteractionContext from "../../contexts/MapInteractionContext";
function TokenDragOverlay({
onTokenStateRemove,
onTokenStateChange,
token,
tokenState,
tokenGroup,
dragging,
mapState,
}) {
const { userId } = useContext(AuthContext);
const { setPreventMapInteraction, mapWidth, mapHeight } = useContext(
MapInteractionContext
);
2020-05-21 22:57:44 +10:00
2020-05-25 13:12:30 +10:00
const [isRemoveHovered, setIsRemoveHovered] = useState(false);
const removeTokenRef = useRef();
// Detect token hover on remove icon manually to support touch devices
useEffect(() => {
const map = document.querySelector(".map");
const mapRect = map.getBoundingClientRect();
function detectRemoveHover() {
const pointerPosition = tokenGroup.getStage().getPointerPosition();
2020-05-25 13:12:30 +10:00
const screenSpacePointerPosition = {
x: pointerPosition.x + mapRect.left,
y: pointerPosition.y + mapRect.top,
};
const removeIconPosition = removeTokenRef.current.getBoundingClientRect();
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);
}
}
let handler;
if (tokenState && tokenGroup && dragging) {
2020-05-25 13:12:30 +10:00
handler = setInterval(detectRemoveHover, 100);
}
return () => {
if (handler) {
clearInterval(handler);
}
};
}, [tokenState, tokenGroup, isRemoveHovered, dragging]);
2020-05-25 13:12:30 +10:00
// Detect drag end of token image and remove it if it is over the remove icon
useEffect(() => {
function handleTokenDragEnd() {
// Handle other tokens when a vehicle gets deleted
if (token && token.isVehicle) {
const layer = tokenGroup.getLayer();
const mountedTokens = tokenGroup.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,
lastModifiedBy: userId,
lastModified: Date.now(),
},
});
2020-05-25 13:12:30 +10:00
}
}
onTokenStateRemove(tokenState);
setPreventMapInteraction(false);
}
if (!dragging && tokenState && isRemoveHovered) {
handleTokenDragEnd();
}
});
2020-05-21 22:57:44 +10:00
return (
dragging && (
<Box
sx={{
position: "absolute",
bottom: "32px",
left: "50%",
borderRadius: "50%",
transform: isRemoveHovered
? "translateX(-50%) scale(2.0)"
: "translateX(-50%) scale(1.5)",
transition: "transform 250ms ease",
color: isRemoveHovered ? "primary" : "text",
pointerEvents: "none",
}}
bg="overlay"
ref={removeTokenRef}
>
<IconButton>
<RemoveTokenIcon />
</IconButton>
</Box>
)
2020-05-21 22:57:44 +10:00
);
}
export default TokenDragOverlay;