Files
grungnet/src/components/map/DragOverlay.tsx

104 lines
2.7 KiB
TypeScript
Raw Normal View History

2021-07-13 08:59:28 +10:00
import { useEffect, useRef, useState } from "react";
2020-11-05 14:41:33 +11:00
import { Box, IconButton } from "theme-ui";
2021-07-16 21:39:45 +10:00
import Konva from "konva";
2020-11-05 14:41:33 +11:00
2021-05-06 15:04:53 +10:00
import RemoveTokenIcon from "../../icons/RemoveTokenIcon";
2020-11-05 14:41:33 +11:00
2021-07-13 08:59:28 +10:00
type DragOverlayProps = {
dragging: boolean;
2021-07-16 21:39:45 +10:00
node: Konva.Node;
2021-07-13 08:59:28 +10:00
onRemove: () => void;
};
function DragOverlay({ dragging, node, onRemove }: DragOverlayProps) {
2020-11-05 14:41:33 +11:00
const [isRemoveHovered, setIsRemoveHovered] = useState(false);
2021-07-13 08:59:28 +10:00
const removeTokenRef = useRef<HTMLDivElement>(null);
2020-11-05 14:41:33 +11:00
// Detect token hover on remove icon manually to support touch devices
useEffect(() => {
function detectRemoveHover() {
if (!node || !dragging || !removeTokenRef.current) {
return;
}
2021-07-13 08:59:28 +10:00
const map = document.querySelector(".map");
if (!map) {
return;
}
const mapRect = map.getBoundingClientRect();
2021-01-04 12:22:09 +11:00
const stage = node.getStage();
if (!stage) {
return;
}
const pointerPosition = stage.getPointerPosition();
2021-07-13 08:59:28 +10:00
if (!pointerPosition) {
return;
}
2020-11-05 14:41:33 +11: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);
}
}
2021-07-13 08:59:28 +10:00
let handler: NodeJS.Timeout;
2020-11-05 14:41:33 +11:00
if (node && dragging) {
handler = setInterval(detectRemoveHover, 100);
}
return () => {
if (handler) {
clearInterval(handler);
}
};
}, [isRemoveHovered, dragging, node]);
// Detect drag end of token image and remove it if it is over the remove icon
useEffect(() => {
if (!dragging && node && isRemoveHovered) {
onRemove();
}
});
2021-07-17 12:48:04 +10:00
if (!dragging) {
return null;
}
2020-11-05 14:41:33 +11:00
return (
2021-07-17 12:48:04 +10:00
<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-11-05 14:41:33 +11:00
);
}
export default DragOverlay;