2020-05-21 16:46:50 +10:00
|
|
|
import React, { useContext, useState, useEffect, useRef } from "react";
|
2020-05-21 20:57:52 +10:00
|
|
|
import { Image as KonvaImage, Group } from "react-konva";
|
2020-05-21 16:46:50 +10:00
|
|
|
import useImage from "use-image";
|
2020-04-13 00:24:03 +10:00
|
|
|
|
2020-04-24 15:50:05 +10:00
|
|
|
import useDataSource from "../../helpers/useDataSource";
|
2020-05-21 16:46:50 +10:00
|
|
|
import useDebounce from "../../helpers/useDebounce";
|
2020-04-24 15:50:05 +10:00
|
|
|
|
2020-05-18 19:21:29 +10:00
|
|
|
import AuthContext from "../../contexts/AuthContext";
|
2020-05-21 16:46:50 +10:00
|
|
|
import MapInteractionContext from "../../contexts/MapInteractionContext";
|
2020-05-18 19:21:29 +10:00
|
|
|
|
2020-05-21 20:57:52 +10:00
|
|
|
import TokenStatus from "../token/TokenStatus";
|
|
|
|
|
import TokenLabel from "../token/TokenLabel";
|
|
|
|
|
|
2020-05-20 11:35:14 +10:00
|
|
|
import { tokenSources, unknownSource } from "../../tokens";
|
2020-04-13 00:24:03 +10:00
|
|
|
|
2020-05-21 16:46:50 +10:00
|
|
|
function MapToken({
|
|
|
|
|
token,
|
|
|
|
|
tokenState,
|
|
|
|
|
tokenSizePercent,
|
|
|
|
|
onTokenStateChange,
|
|
|
|
|
onTokenMenuOpen,
|
|
|
|
|
}) {
|
2020-05-18 19:21:29 +10:00
|
|
|
const { userId } = useContext(AuthContext);
|
2020-05-21 16:46:50 +10:00
|
|
|
const {
|
|
|
|
|
setPreventMapInteraction,
|
|
|
|
|
mapWidth,
|
|
|
|
|
mapHeight,
|
|
|
|
|
stageScale,
|
|
|
|
|
} = useContext(MapInteractionContext);
|
|
|
|
|
|
|
|
|
|
const tokenSource = useDataSource(token, tokenSources, unknownSource);
|
|
|
|
|
const [tokenSourceImage, tokenSourceStatus] = useImage(tokenSource);
|
|
|
|
|
const [tokenAspectRatio, setTokenAspectRatio] = useState(1);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (tokenSourceImage) {
|
|
|
|
|
setTokenAspectRatio(tokenSourceImage.width / tokenSourceImage.height);
|
|
|
|
|
}
|
|
|
|
|
}, [tokenSourceImage]);
|
|
|
|
|
|
|
|
|
|
function handleDragEnd(event) {
|
|
|
|
|
onTokenStateChange({
|
|
|
|
|
...tokenState,
|
|
|
|
|
x: event.target.x() / mapWidth,
|
|
|
|
|
y: event.target.y() / mapHeight,
|
|
|
|
|
lastEditedBy: userId,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleClick(event) {
|
|
|
|
|
const tokenImage = event.target;
|
|
|
|
|
onTokenMenuOpen(tokenState.id, tokenImage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const tokenWidth = tokenSizePercent * mapWidth * tokenState.size;
|
|
|
|
|
const tokenHeight =
|
|
|
|
|
tokenSizePercent * (mapWidth / tokenAspectRatio) * tokenState.size;
|
2020-04-24 15:50:05 +10:00
|
|
|
|
2020-05-21 16:46:50 +10:00
|
|
|
const debouncedStageScale = useDebounce(stageScale, 50);
|
2020-04-13 00:24:03 +10:00
|
|
|
const imageRef = useRef();
|
2020-05-21 16:46:50 +10:00
|
|
|
useEffect(() => {
|
|
|
|
|
const image = imageRef.current;
|
2020-05-21 20:57:52 +10:00
|
|
|
if (image && tokenSourceStatus === "loaded") {
|
2020-05-21 16:46:50 +10:00
|
|
|
image.cache({
|
|
|
|
|
pixelRatio: debouncedStageScale,
|
|
|
|
|
});
|
|
|
|
|
image.drawHitFromCache();
|
|
|
|
|
// Force redraw
|
2020-05-21 20:57:52 +10:00
|
|
|
image.getLayer().draw();
|
2020-05-21 16:46:50 +10:00
|
|
|
}
|
|
|
|
|
}, [debouncedStageScale, tokenWidth, tokenHeight, tokenSourceStatus]);
|
2020-04-13 00:24:03 +10:00
|
|
|
|
|
|
|
|
return (
|
2020-05-21 20:57:52 +10:00
|
|
|
<Group
|
2020-05-21 16:46:50 +10:00
|
|
|
width={tokenWidth}
|
|
|
|
|
height={tokenHeight}
|
|
|
|
|
x={tokenState.x * mapWidth}
|
|
|
|
|
y={tokenState.y * mapHeight}
|
|
|
|
|
draggable
|
|
|
|
|
onMouseDown={() => setPreventMapInteraction(true)}
|
|
|
|
|
onMouseUp={() => setPreventMapInteraction(false)}
|
|
|
|
|
onTouchStart={() => setPreventMapInteraction(true)}
|
|
|
|
|
onTouchEnd={() => setPreventMapInteraction(false)}
|
2020-05-21 20:57:52 +10:00
|
|
|
onClick={handleClick}
|
|
|
|
|
onDragEnd={handleDragEnd}
|
|
|
|
|
>
|
|
|
|
|
<KonvaImage
|
|
|
|
|
ref={imageRef}
|
|
|
|
|
width={tokenWidth}
|
|
|
|
|
height={tokenHeight}
|
|
|
|
|
x={0}
|
|
|
|
|
y={0}
|
|
|
|
|
image={tokenSourceImage}
|
|
|
|
|
/>
|
|
|
|
|
<TokenStatus
|
|
|
|
|
tokenState={tokenState}
|
|
|
|
|
width={tokenWidth}
|
|
|
|
|
height={tokenHeight}
|
|
|
|
|
/>
|
|
|
|
|
<TokenLabel
|
|
|
|
|
tokenState={tokenState}
|
|
|
|
|
width={tokenWidth}
|
|
|
|
|
height={tokenHeight}
|
|
|
|
|
/>
|
|
|
|
|
</Group>
|
2020-04-13 00:24:03 +10:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default MapToken;
|