Skip to content

Commit

Permalink
show below piece on drag; organize files
Browse files Browse the repository at this point in the history
  • Loading branch information
jwyce committed Feb 14, 2021
1 parent 93d66ef commit ce654e9
Show file tree
Hide file tree
Showing 26 changed files with 208 additions and 181 deletions.
2 changes: 1 addition & 1 deletion client/.eslintcache

Large diffs are not rendered by default.

8 changes: 3 additions & 5 deletions client/src/components/gameboard/Board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,17 @@ const Wrapper = styled.div`
interface BoardProps {}

export const Board: React.FC<BoardProps> = () => {
// const bounds = useRef<any>(null); //TODO: maybe use with coordinate for drag boundary
const squares: any[] = [];

squares.push(
<Square key={0} highlight={false} hint={false} hasPiece={false}>
<Piece></Piece>
{/* <></> */}
<Piece icon="b2帥.svg" belowIcon="w1帥.svg" />
</Square>
);
for (let i = 1; i < 81; i++) {
squares.push(
<Square key={i} highlight={true} hint={true} hasPiece={false}>
<Empty></Empty>
<Square key={i} highlight={false} hint={false} hasPiece={false}>
<Empty />
</Square>
);
}
Expand Down
220 changes: 118 additions & 102 deletions client/src/components/gameboard/Piece.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,112 +22,128 @@ function importAll(r: any) {
const pieces = importAll(require.context('../../assets/pieces', false, /.svg/));
const position = { x: 0, y: 0 };

interface PieceProps {}

export const Piece: React.FC<PieceProps> = observer(() => {
const [state, setState] = useState({
isDragging: false,
origin: position,
translation: position,
});
const gungiStore = useContext(GungiStoreContext);

const pieceEl = useRef<HTMLImageElement>(null);

const handleMouseDown = useCallback(
({ button, clientX, clientY }) => {
if (button === 2) {
return;
}

const rect = pieceEl.current!.getBoundingClientRect();
const translation = {
x: clientX - rect.x + 10 - rect.width / 2,
y: clientY - rect.y - rect.height / 2,
};
interface PieceProps {
icon: string;
variant?: 'normal' | 'small';
belowIcon?: string;
}

export const Piece: React.FC<PieceProps> = observer(
({ icon, variant = 'normal', belowIcon }) => {
const [state, setState] = useState({
isDragging: false,
origin: position,
translation: position,
});
const gungiStore = useContext(GungiStoreContext);

const pieceEl = useRef<HTMLImageElement>(null);

const handleMouseDown = useCallback(
({ button, clientX, clientY }) => {
if (button === 2) {
return;
}

const rect = pieceEl.current!.getBoundingClientRect();
const offset = variant === 'normal' ? 10 : 0;
const translation = {
x: clientX - rect.x + offset - rect.width / 2,
y: clientY - rect.y - rect.height / 2,
};

setState((state) => ({
...state,
isDragging: true,
origin: {
x: rect.x - offset + rect.width / 2,
y: rect.y + rect.height / 2,
},
translation,
}));

gungiStore.isDragging = true;
},
[gungiStore, variant]
);

const handleMouseMove = useCallback(
({ clientX, clientY }) => {
const translation = {
x: clientX - state.origin.x,
y: clientY - state.origin.y,
};

setState((state) => ({
...state,
translation,
}));
},
[state.origin]
);

const handleMouseUp = useCallback(() => {
setState((state) => ({
...state,
isDragging: true,
origin: {
x: rect.x - 10 + rect.width / 2,
y: rect.y + rect.height / 2,
},
translation,
isDragging: false,
}));

gungiStore.isDragging = true;
},
[gungiStore]
);
gungiStore.isDragging = false;
}, [gungiStore]);

const handleMouseMove = useCallback(
({ clientX, clientY }) => {
const translation = {
x: clientX - state.origin.x,
y: clientY - state.origin.y,
};
useEffect(() => {
if (state.isDragging) {
window.addEventListener('mousemove', handleMouseMove);
window.addEventListener('mouseup', handleMouseUp);
} else {
window.removeEventListener('mousemove', handleMouseMove);
window.removeEventListener('mouseup', handleMouseUp);

setState((state) => ({
...state,
translation,
}));
},
[state.origin]
);

const handleMouseUp = useCallback(() => {
setState((state) => ({
...state,
isDragging: false,
}));

gungiStore.isDragging = false;
}, [gungiStore]);

useEffect(() => {
if (state.isDragging) {
window.addEventListener('mousemove', handleMouseMove);
window.addEventListener('mouseup', handleMouseUp);
window.addEventListener('touchmove', handleMouseMove);
window.addEventListener('touchend', handleMouseUp);
} else {
window.removeEventListener('mousemove', handleMouseMove);
window.removeEventListener('mouseup', handleMouseUp);
window.removeEventListener('touchmove', handleMouseMove);
window.removeEventListener('touchend', handleMouseUp);

setState((state) => ({ ...state, translation: { x: 0, y: 0 } }));
}
}, [state.isDragging, handleMouseMove, handleMouseUp]);

const styles: DetailedHTMLProps<
ImgHTMLAttributes<HTMLImageElement>,
HTMLImageElement
> = useMemo(
() => ({
cursor: state.isDragging ? '-webkit-grabbing' : '-webkit-grab',
transform: `translate(${state.translation.x}px, ${state.translation.y}px)`,
zIndex: state.isDragging ? 900 : 4,
position: state.isDragging ? 'absolute' : 'relative',
pointerEvents: state.isDragging ? 'none' : '',
width: '80%',
display: 'block',
margin: '10.02% auto',
}),
[state.isDragging, state.translation]
);

return (
<>
<img
src={pieces['b2帥.svg'].default}
alt="piece"
draggable={false}
ref={pieceEl}
onMouseDown={handleMouseDown}
style={styles}
/>
</>
);
});
setState((state) => ({ ...state, translation: { x: 0, y: 0 } }));
}
}, [state.isDragging, handleMouseMove, handleMouseUp]);

const styles: DetailedHTMLProps<
ImgHTMLAttributes<HTMLImageElement>,
HTMLImageElement
> = useMemo(
() => ({
cursor: state.isDragging ? '-webkit-grabbing' : '-webkit-grab',
transform: `translate(${state.translation.x}px, ${state.translation.y}px)`,
zIndex: state.isDragging ? 900 : 4,
position: state.isDragging ? 'absolute' : 'relative',
pointerEvents: state.isDragging ? 'none' : '',
width: variant === 'normal' ? '80%' : '48px',
display: 'block',
margin: variant === 'normal' ? '10.02% auto' : '0',
}),
[state.isDragging, state.translation, variant]
);

return (
<>
<img
src={pieces[icon].default}
alt="piece"
draggable={false}
ref={pieceEl}
onMouseDown={handleMouseDown}
style={styles}
/>
{belowIcon && (
<img
src={pieces[belowIcon].default}
alt="piece_below"
draggable={false}
style={{
width: '80%',
display:
variant === 'normal' && state.isDragging ? 'block' : 'none',
margin: variant === 'normal' ? '10.02% auto' : '0',
}}
/>
)}
</>
);
}
);
1 change: 1 addition & 0 deletions client/src/components/gameboard/Square.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const Wrapper = styled.div<{ highlight: boolean; hover: boolean }>`
position: relative;
outline: ${(props) => (props.hover ? '5px solid #b683ca' : 'none')};
outline-offset: ${(props) => (props.hover ? '-4.5px' : '0')};
cursor: ${(props) => (props.hover ? '-webkit-grabbing' : '0')};
`;

const Hint = styled.div<{ show: boolean; capture: boolean }>`
Expand Down
50 changes: 11 additions & 39 deletions client/src/components/ui/StockpilePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,8 @@
import React from 'react';
import { Badge, Icon, makeStyles } from '@material-ui/core';
import Panel from './Panel';
import styled from 'styled-components';

function importAll(r: any) {
let images = {};
r.keys().forEach((item: string, index: any) => {
images[item.replace('./', '')] = r(item);
});
return images;
}

const pieces = importAll(require.context('../../assets/pieces', false, /.svg/));

const PieceIcon = styled.img`
cursor: grab;
&:active {
cursor: grabbing;
}
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+/Edge */
user-select: none; /* Standard */
width: 48px;
`;
interface Piece {
type: string;
color: string;
}

interface StockPiece {
piece: Piece;
amount: number;
}
import Panel from './styles/Panel';
import { StockPiece } from 'src/typings/types';
import { Piece } from '../gameboard/Piece';

interface StockpilePanelProps {
player: string;
Expand All @@ -50,6 +20,7 @@ export const StockpilePanel: React.FC<StockpilePanelProps> = (props) => {
color: 'white',
fontFamily: 'Montserrat',
transform: 'scale(1) translate(35%, -35%)',
zIndex: 5,
},
}));

Expand All @@ -76,12 +47,13 @@ export const StockpilePanel: React.FC<StockpilePanelProps> = (props) => {
className={classes.margin}
>
<Icon style={{ fontSize: '48px' }}>
<PieceIcon
src={
pieces[`${props.player}1${stock_piece.piece.type}.svg`].default
}
draggable={false}
alt={`${props.player}1${stock_piece.piece.type}`}
<Piece
icon={`${props.player}1${stock_piece.piece.type}.svg`}
variant="small"
/>
<Piece
icon={`${props.player}1${stock_piece.piece.type}.svg`}
variant="small"
/>
</Icon>
</Badge>
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/ui/TowerDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import Panel from './Panel';
import Panel from './styles/Panel';

interface TowerDetailsProps {}

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions client/src/pages/About.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import { Footer } from '../components/ui/Footer';
import GlobalStyle from '../components/ui/GlobalStyle';
import GlobalStyle from '../components/ui/styles/GlobalStyle';
import { Header } from '../components/ui/Header';
import Paragraph from '../components/ui/Paragraph';
import Panel from '../components/ui/Panel';
import Paragraph from '../components/ui/styles/Paragraph';
import Panel from '../components/ui/styles/Panel';
import { Mobility } from '../components/ui/Mobility';
import styled from 'styled-components';

Expand Down
8 changes: 4 additions & 4 deletions client/src/pages/Contact.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react';
import Button from '../components/ui/Button';
import Button from '../components/ui/styles/Button';
import { Footer } from '../components/ui/Footer';
import GlobalStyle from '../components/ui/GlobalStyle';
import GlobalStyle from '../components/ui/styles/GlobalStyle';
import { Header } from '../components/ui/Header';
import Panel from '../components/ui/Panel';
import Paragraph from '../components/ui/Paragraph';
import Panel from '../components/ui/styles/Panel';
import Paragraph from '../components/ui/styles/Paragraph';
import coffeeIcon from '../assets/icons/buymeacoffee.svg';
import gitIcon from '../assets/icons/github.svg';
import feedbackIcon from '../assets/icons/feedback.svg';
Expand Down
Loading

0 comments on commit ce654e9

Please sign in to comment.