I'm trying to learn react and i creating a chess game.
I've to simulate a drag and click system to make the pieces move.
The function setActivePiece is called on mousedown, and it set the variable activePiece to the piece being clicked (only if it's a piece and not if it's the board being clicked), movePiece is only called on mouseup ( end of a click or end of a drag).
The drag system works, but i want to be able to click a piece and then click the position where i want the piece to move.
After a click, the activePiece is set to the piece clicked (using e.target) and the function movePiece is called (cause a click call both setActivePiece and movePiece), but during the second click the value of the Variable activePiece is null, in fact the piece wont move.
Any suggestions?
Here's the code.
function Board(){
const [pieces, setPieces] = useState([]);
const boardRef = useRef();
let activePiece = null;
function movePiece(e) {
if (activePiece === null)
return;
//determinate the position in the board (from cordinate to index of the board)
setPieces(prevState => {
const updatePieces = prevState.map(p => {
//finding the right piece
if (p.id === activePiece.id){
let lenghtmovingPiece = boardRef.current.offsetWidth / 8;
//aggiorno la posizione (int(posmovingPiece - posBoard / lenghtmovingPiece))
p.x = parseInt((e.clientX - boardRef.current.getBoundingClientRect().x) / lenghtmovingPiece);
p.y = parseInt((e.clientY - boardRef.current.getBoundingClientRect().y) / lenghtmovingPiece);
}
return p;
})
//reset hte active piece
activePiece = null
return updatePieces;
})
}
function setActivePiece(e) {
//no preview image
e.preventDefault();
//click of the board
if (e.target.id === "boardImg")
return;
activePiece = e.target
}
function dragPiece(e){
//nothing selected
if (activePiece === null)
return;
//set the element new position when dragged
//newPos = mousePos - spazio tra la finestra e la scacchiera (perche' i piece sono absolute alla scacchiera) - meta' della grandezza del piece (= larghezzaBoard / 4)
activePiece.style.left = e.clientX - boardRef.current.getBoundingClientRect().x - boardRef.current.getBoundingClientRect().x/4 + "px";
activePiece.style.top = e.clientY - boardRef.current.getBoundingClientRect().y - boardRef.current.getBoundingClientRect().x/4 + "px";
}
useEffect(() => {
// createMatch("matches", "match0/logs/log1", {})
// createMatch("matches", "match0", objBoard)
setPieces(generateBoard())
}, [activePiece]);
return(
<div id="board" onMouseDown={setActivePiece} onMouseUp={movePiece} onMouseMove={dragPiece} >
<img ref={boardRef} id="boardImg" src={boardImg} alt="board" draggable="false"/>
{
//pieces of the board
pieces.map(piece => return <Piece key={uuidv4()} piece={piece}/>)
}
</div>
)
}
Also tried to use an useState but i dont know if it's the right path.
Yes, useState
is the right path. Consider this slight revision:
export default function Board() {
const [activePiece, setActivePiece] = useState(null);
const [pieces, setPieces] = useState([]);
const boardRef = useRef();
function movePiece(e) {
if (activePiece === null) return;
//determinate the position in the board (from cordinate to index of the board)
setPieces((prevState) => {
const updatePieces = prevState.map((p) => {
//finding the right piece
if (p.id === activePiece.id) {
let lenghtmovingPiece = boardRef.current.offsetWidth / 8;
//aggiorno la posizione (int(posmovingPiece - posBoard / lenghtmovingPiece))
p.x = parseInt(
(e.clientX - boardRef.current.getBoundingClientRect().x) /
lenghtmovingPiece
);
p.y = parseInt(
(e.clientY - boardRef.current.getBoundingClientRect().y) /
lenghtmovingPiece
);
}
return p;
});
//reset the active piece
setActivePiece(null);
return updatePieces;
});
}
function onMouseDown(e) {
//no preview image
e.preventDefault();
//click of the board
if (e.target.id === "boardImg") return;
setActivePiece(e.target);
}
function dragPiece(e) {
//nothing selected
if (activePiece === null) return;
const updatedActivePiece = { ...activePiece };
//set the element new position when dragged
//newPos = mousePos - spazio tra la finestra e la scacchiera (perche' i piece sono absolute alla scacchiera) - meta' della grandezza del piece (= larghezzaBoard / 4)
updatedActivePiece.style.left =
e.clientX -
boardRef.current.getBoundingClientRect().x -
boardRef.current.getBoundingClientRect().x / 4 +
"px";
updatedActivePiece.style.top =
e.clientY -
boardRef.current.getBoundingClientRect().y -
boardRef.current.getBoundingClientRect().x / 4 +
"px";
setActivePiece(updatedActivePiece);
}
useEffect(() => {
// createMatch("matches", "match0/logs/log1", {})
// createMatch("matches", "match0", objBoard)
setPieces(generateBoard());
}, [activePiece]);
return (
<div
id="board"
onMouseDown={onMouseDown}
onMouseUp={movePiece}
onMouseMove={dragPiece}
>
<img
ref={boardRef}
id="boardImg"
src={boardImg}
alt="board"
draggable="false"
/>
{
//pieces of the board
pieces.map((piece) => (
<Piece key={uuidv4()} piece={piece} />
))
}
</div>
);
}