Added token moving and removing on map
This commit is contained in:
parent
1133fe2d2b
commit
82d750eca7
@ -2,37 +2,60 @@ import React from "react";
|
|||||||
import { Image, Flex, Box } from "theme-ui";
|
import { Image, Flex, Box } from "theme-ui";
|
||||||
|
|
||||||
import Token from "../components/Token";
|
import Token from "../components/Token";
|
||||||
|
import ProxyToken from "../components/ProxyToken";
|
||||||
|
|
||||||
|
const mapTokenClassName = "map-token";
|
||||||
|
|
||||||
|
function Map({ imageSource, tokens, onMapTokenMove, onMapTokenRemove }) {
|
||||||
|
function handleProxyDragEnd(isOnMap, token) {
|
||||||
|
if (isOnMap && onMapTokenMove) {
|
||||||
|
onMapTokenMove(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isOnMap && onMapTokenRemove) {
|
||||||
|
onMapTokenRemove(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Map({ imageSource, tokens }) {
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<>
|
||||||
className="map"
|
<Flex
|
||||||
sx={{ justifyContent: "center", flexGrow: 1 }}
|
className="map"
|
||||||
bg="background"
|
sx={{ justifyContent: "center", flexGrow: 1 }}
|
||||||
>
|
bg="background"
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
position: "absolute",
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
userSelect: "none"
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{Object.values(tokens).map(token => (
|
<Box
|
||||||
<Box
|
sx={{
|
||||||
key={token.id}
|
position: "absolute",
|
||||||
sx={{
|
top: 0,
|
||||||
position: "absolute",
|
left: 0,
|
||||||
transform: `translate(${token.x}px, ${token.y}px)`
|
right: 0,
|
||||||
}}
|
userSelect: "none"
|
||||||
>
|
}}
|
||||||
<Token image={token.image} className="map-token" />
|
>
|
||||||
</Box>
|
{Object.values(tokens).map(token => (
|
||||||
))}
|
<Box
|
||||||
</Box>
|
key={token.id}
|
||||||
<Image src={imageSource} sx={{ objectFit: "contain" }} />
|
sx={{
|
||||||
</Flex>
|
position: "absolute",
|
||||||
|
transform: `translate(${token.x}px, ${token.y}px)`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Token
|
||||||
|
tokenId={token.id}
|
||||||
|
image={token.image}
|
||||||
|
className={mapTokenClassName}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
<Image src={imageSource} sx={{ objectFit: "contain" }} />
|
||||||
|
</Flex>
|
||||||
|
<ProxyToken
|
||||||
|
tokenClassName={mapTokenClassName}
|
||||||
|
onProxyDragEnd={handleProxyDragEnd}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,12 +67,14 @@ function ProxyToken({ tokenClassName, onProxyDragEnd }) {
|
|||||||
let proxy = imageRef.current;
|
let proxy = imageRef.current;
|
||||||
if (proxy) {
|
if (proxy) {
|
||||||
if (onProxyDragEnd) {
|
if (onProxyDragEnd) {
|
||||||
const endX = parseFloat(proxy.getAttribute("data-x")) || 0;
|
const x = parseFloat(proxy.getAttribute("data-x")) || 0;
|
||||||
const endY = parseFloat(proxy.getAttribute("data-y")) || 0;
|
const y = parseFloat(proxy.getAttribute("data-y")) || 0;
|
||||||
|
const id = target.getAttribute("data-token-id");
|
||||||
onProxyDragEnd(proxyOnMap.current, {
|
onProxyDragEnd(proxyOnMap.current, {
|
||||||
image: imageSource,
|
image: imageSource,
|
||||||
x: endX,
|
x,
|
||||||
y: endY
|
y,
|
||||||
|
id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Image } from "theme-ui";
|
import { Image } from "theme-ui";
|
||||||
|
|
||||||
function Token({ image, className }) {
|
function Token({ image, className, tokenId }) {
|
||||||
|
// Store the token id in the html element for the drag code to pick it up
|
||||||
|
const idProp = tokenId ? { "data-token-id": tokenId } : {};
|
||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
p={2}
|
p={2}
|
||||||
@ -11,6 +13,7 @@ function Token({ image, className }) {
|
|||||||
width: "64px",
|
width: "64px",
|
||||||
height: "64px"
|
height: "64px"
|
||||||
}}
|
}}
|
||||||
|
{...idProp}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,13 @@ import * as tokens from "../tokens";
|
|||||||
import Token from "./Token";
|
import Token from "./Token";
|
||||||
import ProxyToken from "./ProxyToken";
|
import ProxyToken from "./ProxyToken";
|
||||||
|
|
||||||
function Tokens({ onCreateMapToken }) {
|
const listTokenClassName = "list-token";
|
||||||
const tokenClassName = "list-token";
|
|
||||||
|
|
||||||
|
function Tokens({ onCreateMapToken }) {
|
||||||
function handleProxyDragEnd(isOnMap, token) {
|
function handleProxyDragEnd(isOnMap, token) {
|
||||||
if (isOnMap && onCreateMapToken) {
|
if (isOnMap && onCreateMapToken) {
|
||||||
// Give the token an id
|
// Give the token an id
|
||||||
onCreateMapToken({ id: shortid.generate(), ...token });
|
onCreateMapToken({ ...token, id: shortid.generate() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,11 +30,11 @@ function Tokens({ onCreateMapToken }) {
|
|||||||
px={2}
|
px={2}
|
||||||
>
|
>
|
||||||
{Object.entries(tokens).map(([id, image]) => (
|
{Object.entries(tokens).map(([id, image]) => (
|
||||||
<Token key={id} image={image} className={tokenClassName} />
|
<Token key={id} image={image} className={listTokenClassName} />
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
<ProxyToken
|
<ProxyToken
|
||||||
tokenClassName={tokenClassName}
|
tokenClassName={listTokenClassName}
|
||||||
onProxyDragEnd={handleProxyDragEnd}
|
onProxyDragEnd={handleProxyDragEnd}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
10
src/helpers/shared.js
Normal file
10
src/helpers/shared.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export function omit(obj, keys) {
|
||||||
|
let tmp = {};
|
||||||
|
for (let [key, value] of Object.entries(obj)) {
|
||||||
|
if (keys.includes(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tmp[key] = value;
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
@ -7,6 +7,8 @@ import React, {
|
|||||||
} from "react";
|
} from "react";
|
||||||
import { Box, Flex } from "theme-ui";
|
import { Box, Flex } from "theme-ui";
|
||||||
|
|
||||||
|
import { omit } from "../helpers/shared";
|
||||||
|
|
||||||
import GameContext from "../contexts/GameContext";
|
import GameContext from "../contexts/GameContext";
|
||||||
import useSession from "../helpers/useSession";
|
import useSession from "../helpers/useSession";
|
||||||
|
|
||||||
@ -43,14 +45,25 @@ function Game() {
|
|||||||
|
|
||||||
const [mapTokens, setMapTokens] = useState({});
|
const [mapTokens, setMapTokens] = useState({});
|
||||||
|
|
||||||
function handleCreateMapToken(token) {
|
function handleEditMapToken(token) {
|
||||||
setMapTokens(prevMapTokens => ({
|
setMapTokens(prevMapTokens => ({
|
||||||
...prevMapTokens,
|
...prevMapTokens,
|
||||||
[token.id]: token
|
[token.id]: token
|
||||||
}));
|
}));
|
||||||
for (let connection of Object.values(connections)) {
|
for (let connection of Object.values(connections)) {
|
||||||
const data = { [token.id]: token };
|
const data = { [token.id]: token };
|
||||||
connection.send({ id: "token", data });
|
connection.send({ id: "tokenEdit", data });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRemoveMapToken(token) {
|
||||||
|
setMapTokens(prevMapTokens => {
|
||||||
|
const { [token.id]: old, ...rest } = prevMapTokens;
|
||||||
|
return rest;
|
||||||
|
});
|
||||||
|
for (let connection of Object.values(connections)) {
|
||||||
|
const data = { [token.id]: token };
|
||||||
|
connection.send({ id: "tokenRemove", data });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,12 +74,17 @@ function Game() {
|
|||||||
imageDataRef.current = blob;
|
imageDataRef.current = blob;
|
||||||
setImageSource(URL.createObjectURL(imageDataRef.current));
|
setImageSource(URL.createObjectURL(imageDataRef.current));
|
||||||
}
|
}
|
||||||
if (data.id === "token") {
|
if (data.id === "tokenEdit") {
|
||||||
setMapTokens(prevMapTokens => ({
|
setMapTokens(prevMapTokens => ({
|
||||||
...prevMapTokens,
|
...prevMapTokens,
|
||||||
...data.data
|
...data.data
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
if (data.id === "tokenRemove") {
|
||||||
|
setMapTokens(prevMapTokens =>
|
||||||
|
omit(prevMapTokens, Object.keys(data.data))
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +92,7 @@ function Game() {
|
|||||||
if (imageSource) {
|
if (imageSource) {
|
||||||
connection.send({ id: "image", data: imageDataRef.current });
|
connection.send({ id: "image", data: imageDataRef.current });
|
||||||
}
|
}
|
||||||
connection.send({ id: "token", data: mapTokens });
|
connection.send({ id: "tokenEdit", data: mapTokens });
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -94,8 +112,13 @@ function Game() {
|
|||||||
sx={{ justifyContent: "space-between", flexGrow: 1, height: "100%" }}
|
sx={{ justifyContent: "space-between", flexGrow: 1, height: "100%" }}
|
||||||
>
|
>
|
||||||
<Party streams={streams} localStreamId={peerId} />
|
<Party streams={streams} localStreamId={peerId} />
|
||||||
<Map imageSource={imageSource} tokens={mapTokens} />
|
<Map
|
||||||
<Tokens onCreateMapToken={handleCreateMapToken} />
|
imageSource={imageSource}
|
||||||
|
tokens={mapTokens}
|
||||||
|
onMapTokenMove={handleEditMapToken}
|
||||||
|
onMapTokenRemove={handleRemoveMapToken}
|
||||||
|
/>
|
||||||
|
<Tokens onCreateMapToken={handleEditMapToken} />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user