
WIL 12주차 (실전프로젝트 5주차)
📖 WIL 12주차 (실전프로젝트 5주차)
🌞 회고
정말 바쁜 한주였다. 디자인 이슈 때문에 레이아웃을 고민하고 필요한 이미지들을 찾아가며 코딩을 해야했기에 우리의 계획보다 모든게 늦어졌지만 30시간 코딩 6시간 수면법으로 일주일을 보낸 것 같다. 디자이너가 있을 때 초기 기획은 사이드바가 4개 였지만 디자이너가 나가고 사이드바를 한개로 줄였으나 이것도 디자인을 하나라도 줄이기 위해 제거했다. 레이아웃 디자인도 계속해서 수정해나가고 디자인통일을 위해 같은 프론트엔드 팀원과 상의하며 개발했다. 백엔드 팀원들도 코딩만 할수있도록 정말 많은 것들을 서포트해주었기에 팀원들이 아니였다면 디자이너 없이 여기까지 못해냈을 것 같다.
⛅ 물고기 인벤토리
학습한 시간에 따라 물고기를 획득할 수 있으며 획득한 물고기는 파란물방울로 표시된다.
드래그앤드랍으로 바탕화면을 꾸밀 수 있으며 이 데이터는 서버에 저장하고 렌더링시에 데이터를 가져와 새로고침시에도 유지된다.
처음써보는 드래그앤드랍 기능구현을 위해 많은 구글링을 해봤는데 정보가 많지 않았다. 그 중 DnD 또는 React-beautiful-dnd 등 라이브러리가 있었는데 내가 원하는 자유로운 드래그와 그 좌표값을 취득하는 것에 적합하지 않다고 판단하여 HTML 드래그 앤 드롭 API 로 함수들을 직접 구현하였다.
계속되는 에러로 정말 포기하고 싶었지만 핵심 기능이였기에 포기할 수 없었고 끝내 완성했다는 기쁨과 함께 좋아해주는 팀원들 덕분에 뿌듯했다.
⛅ 통계페이지
우선 통계페이지에 넣을 여러가지 데이터를 정하고 이것들을 미리 백엔드에 api를 요청해놓은 상태였다. 그리고 캘린더를 제작할때 사용하진 않았지만 눈여겨 봤던 그래프라이브러리인 nivo라이브러리를 이용해 빠르게 총 3가지의 그래프를 넣었고 유저의 공부시간 데이터를 활용해 다음 물고기 해제까지 달성율을 물결치는 어항을 CSS로 제작하여 표현하였다. 퍼센트%에 따라 물결의 높이가 달라진다.
🌞 트러블 슈팅
- 물고기 이미지는 map을 이용해 그리고 있다. 당연하게도 물고기 한마리씩 드래그 되지 않고 모두 한번에 움직였다. 이것을 해결하기 위해 지난 주 사용했던 index 파라미터를 이용해야겠다 생각했다. 25개의 초기값 0,0 (물고기의 위치가 될 좌표 left,top)배열을 가진 state를 만들어주었고 이곳에 물고기 하나씩 데이터를 저장해주며 인라인스타일로 물고기의 position left,top에 그대로 넣어준다.
- 25마리의 물고기 left,top 좌표를 넣을 state생성
undefined
const [fishPos, setFishPos] = useState( Array.from({ length: 25 }, (v, i) => { return [0, 0]; }) );
- 드래그가 도중에 실행되는 함수
undefined
function dragHandler (e: any, i: number) { let tempData = [...fishPos]; tempData[i][0] = e.target.offsetLeft + e.clientX - clientPos.x; tempData[i][1] = e.target.offsetTop + e.clientY - clientPos.y; setFishPos(tempData); const clientPosTemp = { ...clientPos }; clientPosTemp["x"] = e.clientX; clientPosTemp["y"] = e.clientY; setClientPos(clientPosTemp); };
- dragEndHandler 즉 드래그가 종료되는 시점에 서버에 해당 물고기의 index값과 left,top 좌표를 저장한다.
undefined
function dragEndHandler (e: any, i: number) { let tempData = [...fishPos]; tempData[i][0] = e.target.offsetLeft + e.clientX - clientPos.x; tempData[i][1] = e.target.offsetTop + e.clientY - clientPos.y; setFishPos(tempData); dispatch( __postFishPosition({ fishNum: i, left: fishPos[i][0], top: fishPos[i][1], }) ); // 캔버스 제거 const canvases = document.getElementsByClassName("canvas"); for (let i = 0; i < canvases.length; i++) { let canvas = canvases[i]; canvas.parentNode?.removeChild(canvas); } // 캔버스로 인해 발생한 스크롤 방지 어트리뷰트 제거 document.body.removeAttribute("style"); document.body.style.overflow = "hidden"; };
- 서버에 저장해둔 물고기 좌표의 배열(positionData)을 index와 비교하여 inline스타일로 left와 top에 넣어준다.
<InvenLayout ref={containerRef}> {fishImages.map((data: any, i: number) => { return ( <Label key={i}> <FishImg draggable={userPoint >= data.point ? true : false} onDragStart={(e) => dragStartHandler(e)} onDrag={(e) => dragHandler(e, i)} onDragOver={(e) => dragOverHandler(e)} onDragEnd={(e) => { dragEndHandler(e, i); }} style={{ left: positionData.find((x) => x.fishNum === i)?.left === 0 ? "0.5em" : positionData.find((x) => x.fishNum === i)?.left, top: positionData.find((x) => x.fishNum === i)?.top === 0 ? "0.5em" : positionData.find((x) => x.fishNum === i)?.top, }} src={data.image} alt="" />undefined
- 물고기 좌표(positionData)를 그대로 서버에 저장하고 받아와서 받아온 데이터를 그대로 물고기 position에 넣어주었지만 넣는 순간 내가 서버로 보내는 물고기 좌표값 자체가 이상하게 틀어진다. 이를 해결하기 위해 서버에서 받아온 데이터를 다시한번 State에 저장해 해결했다.
undefined
useEffect(() => { let tempData = [...fishPos]; positionData.map((v) => { tempData[v.fishNum] = [v.left, v.top]; }); setFishPos([...tempData]); }, [positionData]);
undefined
<Label key={i}>
<FishImg
draggable={userPoint >= data.point ? true : false}
onDragStart={(e) => dragStartHandler(e)}
onDrag={(e) => dragHandler(e, i)}
onDragOver={(e) => dragOverHandler(e)}
onDragEnd={(e) =>dragEndHandler(e, i)}
style={{
left: fishPos[i][0] === 0 ? "0.5em" : fishPos[i][0],
top: fishPos[i][1] === 0 ? "0.85em" : fishPos[i][1],
}}
src={data.image}
alt=""
onContextMenu={(e) => FishDeleteHandler(e, i)}
/>
🌳 HTML Drag and Drop API
https://velog.io/@leejpsd/HTML-Drag-and-Drop-API
HTML Drag and Drop API을 사용하며 공부했던 내용을 포스팅하였다.