チームプロジェクト-アニメーションポップアップ選手リスト


チームプロジェクト-アニメーションポップアップ選手リスト


前回の整理


以前は各院の位置によって位置名を変えていました
今度選手リストを手に入れて、右クリックして、選手リストを載せます.
以降の名前を選択すると、名前が円に表示され、リストから消えます.

インプリメンテーション


まずフロント開発を一緒に行ったチームメンバーがTSを使って開発し、右クリックで選手リストを開くことも実現しました
목데이터 (Mock Data)

type Players = {
    id: number;
    //등번호
    name: string;
    already?: boolean;
    //들어가있는지 유무

    //주장 유무랑 포지션 추가 예정
}

export const playersList: Players[] = [
    {
        id: 1,
        name: "1번",
        already: true
    },
    {
        id: 2,
        name: "2번",
        already: true
    },
    {
        id: 3,
        name: "3번",
        already: true
    },
    {
        id: 4,
        name: "4번",
        already: true
    },
    {
        id: 5,
        name: "5번",
        already: true
    },
    {
        id: 6,
        name: "6번",
        already: true
    },
    {
        id: 7,
        name: "7번",
        already: true
    },
    {
        id: 8,
        name: "8번",
        already: true
    },
    {
        id: 9,
        name: "9번",
        already: true
    },
    {
        id: 10,
        name: "10번",
        already: true
    },
    {
        id: 11,
        name: "11번",
        already: true
    },
    {
        id: 12,
        name: "12번",
        already: false
    },
    {
        id: 13,
        name: "13번",
        already: false
    },
    {
        id: 14,
        name: "14번",
        already: false
    },
];
-----------------------------------------------------
CSS

.move {
  background-color:skyblue;
  width:80px;
  height:80px;
  border-radius:75px;
  text-align:center;
  margin:0 auto;
  font-size:30px;
  vertical-align:middle;
  line-height:50px;
  cursor: grab;
  position: absolute;
}
.move:hover {
  background-color: pink;
}
.formation {
  width: 600px;
  height: 950px;
  background-image: url(https://velog.velcdn.com/images%2Fqnrl3442%2Fpost%2F733d5e03-5531-4e99-98e6-6f9a05c26c15%2Fformation.png);
}
.GK {
  background-color:skyblue;
  width:80px;
  height:80px;
  border-radius:75px;
  text-align:center;
  margin:0 auto;
  font-size:30px;
  vertical-align:middle;
  line-height:50px;
  cursor: not-allowed;
  position: absolute;
}
.button {
  border-radius:50%;
  text-align:center;
  font-size:30px;
  vertical-align:middle;
  line-height:50px;
}
-------------------------------------------------------------------
import React, { useState } from 'react';
import "./Formation.css";
import Draggable, { DraggableData } from 'react-draggable';
import axios from 'axios';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import { Button } from '@mui/material';

import { playersList } from './data';
//s 조심
function Formation() {

  type PlayerType = {
    id: number;
    name: string;
    already: boolean;
  };
  const [playerList, setPlayerList] = useState(playersList);
  //s 조심
  const [Status, SetStatus] = useState(true)
  const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
  const open = Boolean(anchorEl);
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
    event.preventDefault();
    //event.preventDefault() 브라우저 우클릭을 막아준다.
  };
  const handleClose = () => {
    setAnchorEl(null);
  };

  const onStatusHandler = () => {
    SetStatus(!Status)
  }

  const readDB = () => {
    if (Status) {
      console.log("read")
      axios.get('/api/readUser') // res = axios 이런식으로 해서 res를 가지고 있어야됨 방법 찾아보자
        .then(res => {
          console.log(res.data)
          // const name = res.data.UserName
          // const x = res.data.x
          // const y = res.data.y
          // console.log(name,x,y)
        })
      console.log("포메이션 원에 위에서 받은 선수 데이터 넣어주기")
    } else {
      console.log("send")
      const body = {
        Status: Status,
        first_Position: Content1 //첫번째 요소 포지션 
      }
      axios.post('/api/sendUser', body)
        .then(res => {
          console.log(res.data)
        })
    }
  }
  // 포지션 위치 값 보내는 방법
  // const [Position1, SetPosition1] = useState({ x: 0, y: 0 });

  // const trackPos = (data) => {
  //   SetPosition1({ x: data.x, y: data.y }); 
  // };

  // let body = {
  //   first: Position1
  // }

  // axios.post('/api/position', body)
  // .then(res => {
  //     console.log(res.data)
  // })

  const [Content1, SetContent1] = useState("ST");
  ------------------------ Content2~9------------
  const [Content10, SetContent10] = useState("RB");

  const onContentHandler1 = (props: string) => {
    SetContent1(props)
  }
  const onDragHandler1 = (data: DraggableData) => {
    if (data.x > 80 && data.y < 120 && data.x < 450) {
      onContentHandler1("ST")
    } else if (data.x < 80 && data.y < 200) {
      onContentHandler1("LW")
    } else if (data.x > 450 && data.y < 200) {
      onContentHandler1("RW")
    } else if (data.x > 80 && data.y > 120 && data.y < 185 && data.x < 450) {
      onContentHandler1("CF")
    } else if (data.x > 80 && data.y > 185 && data.y < 275 && data.x < 450) {
      onContentHandler1("CAM")
    } else if (data.x < 80 && data.y > 200 && data.y < 440) {
      onContentHandler1("LM")
    } else if (data.x > 450 && data.y > 200 && data.y < 440) {
      onContentHandler1("RM")
    } else if (data.x > 80 && data.y > 275 && data.y < 460 && data.x < 450) {
      onContentHandler1("CM")
    } else if (data.x < 80 && data.y > 440) {
      onContentHandler1("LB")
    } else if (data.x > 450 && data.y > 440) {
      onContentHandler1("RB")
    } else if (data.x > 80 && data.y > 460 && data.y < 560 && data.x < 450) {
      onContentHandler1("CDM")
    } else if (data.x > 80 && data.y > 560 && data.x < 450) {
      onContentHandler1("CB")
    }
  }

  --------------------------- onDragHandler2~9--------------------------------

  const onContentHandler10 = (props: string) => {
    SetContent10(props)
  }
  const onDragHandler10 = (data: DraggableData) => {
    if (data.x > 80 && data.y < 120 && data.x < 450) {
      onContentHandler10("ST")
    } else if (data.x < 80 && data.y < 200) {
      onContentHandler10("LW")
    } else if (data.x > 450 && data.y < 200) {
      onContentHandler10("RW")
    } else if (data.x > 80 && data.y > 120 && data.y < 185 && data.x < 450) {
      onContentHandler10("CF")
    } else if (data.x > 80 && data.y > 185 && data.y < 275 && data.x < 450) {
      onContentHandler10("CAM")
    } else if (data.x < 80 && data.y > 200 && data.y < 440) {
      onContentHandler10("LM")
    } else if (data.x > 450 && data.y > 200 && data.y < 440) {
      onContentHandler10("RM")
    } else if (data.x > 80 && data.y > 275 && data.y < 460 && data.x < 450) {
      onContentHandler10("CM")
    } else if (data.x < 80 && data.y > 440) {
      onContentHandler10("LB")
    } else if (data.x > 450 && data.y > 440) {
      onContentHandler10("RB")
    } else if (data.x > 80 && data.y > 460 && data.y < 560 && data.x < 450) {
      onContentHandler10("CDM")
    } else if (data.x > 80 && data.y > 560 && data.x < 450) {
      onContentHandler10("CB")
    }
  }

  return (
    <div className="formation">

      <button onClick={() => {
        onStatusHandler()
        readDB()
      }}>
        {Status ? "편집" : "편집 완료"}
      </button>

      <Draggable
        disabled={Status}
        defaultPosition={{ x: 145, y: 80 }}
        onDrag={(e, data) => onDragHandler1(data)}
        bounds={{ top: 0, left: 0, right: 520, bottom: 740 }}
      // onStop={(e, data) => trackPos(data)}
      // 포지션 위치 값 보내는 방법
      >
        <div className="move">
          <Button className="button"
            disabled={Status}
            id="basic-button"
            aria-controls={open ? 'basic-menu' : undefined}
            aria-haspopup="true"
            aria-expanded={open ? 'true' : undefined}
            onContextMenu={handleClick}
          ><div>{Content1}</div>
          </Button>
        </div>
      </Draggable >

      <Menu
        id="basic-menu"
        anchorEl={anchorEl}
        open={open}
        onClose={handleClose}
        MenuListProps={{
          'aria-labelledby': 'basic-button',
        }}
        PaperProps={{
          style: {
            maxHeight: "200px",
            width: '20ch',
          },
        }}
      //스크롤 만드는것
      >
        {playerList.map((player): JSX.Element => {
          return (
            // player.already === false &&
            <MenuItem onClick={handleClose}>{player.name}</MenuItem>
          );
        })}
      </Menu>

      {/* <MenuItem onClick={handleClose}>My account</MenuItem>
      <MenuItem onClick={handleClose}>Logout</MenuItem> */}


      <Draggable
        disabled={Status}
        defaultPosition={{ x: 380, y: 80 }}
        onDrag={(e, data) => onDragHandler2(data)}
        bounds={{ top: 0, left: 0, right: 520, bottom: 740 }}
      >
        <div className="move">
          <div>{Content2}</div>
        </div>
      </Draggable>

--------- 3~10번 Draggable------------------

      <Draggable
        disabled={true}
        defaultPosition={{ x: 260, y: 790 }}
      >
        <div className="GK">
          <div>GK</div>
        </div>
      </Draggable>
    </div >
  )
}


export default Formation
重ね合わせたコードは――――ここではこれを短く表しています
コードを説明すると首のデータが得られます
次にplaylistにデフォルト値を入れてアンカーelとopenを作成します
私はMenuというものを作って、ドラッグ可能なボタンからmenuをロードさせたと思います.
私が書いたコードではないので、正しいかどうか分かりません.
まずリストに現れて、後で私が体現します
ディレクトリデータにはfalseという値があると聞きましたが、リストに表示するためにコードを生成する必要があります.
だからmenuでmenuitemを作成するときはifで一度フィルタします
        {playerList.map((player, idx) => {
          if(player.already === false){
            return (
              <MenuItem 
                onClick={() => {handleClose()}}
                key={idx}
              >
                {player.name}
              </MenuItem>
            )
          }
        })}
そしてidx値を与え、各リストにキー値を付けた.
その後首のデータを修正してテストしました

名簿がはっきりしている
後で選んだらもう値段を変えようと思った.
今から見ればMenuitemにはhandleClose()がかかっています
だからそれを使ってみたいと思って、HandleCloseにプレイヤーを道具として入れました.
では、選ばれると、その選ばれた選手が入ってきます.
  const handleClose = ({id, name, already}) => {
    setAnchorEl();

    setPlayerList(playerList.map((player) =>
      player.id === id ? { ...player, already: !already} : player)
    )
  }
Flopsを直接構造分解し、setPlayerListを使用して現在受信しているidと比較します.
3つの演算子で1つ書きました.同じidがあれば、既存のものを置き換えます.同じでなければ、自然に任せます.
これで変わり、選択した値がリストから消えてしまいます
しかし、1番を選んで2番を選ぶと、1番のものをfalseに変えるにはどうすればいいのでしょうか.
どう考えても仕方がない
最初は、同じように3つの演算子を使用してtrueをすべてfalseに変換し、選択した値をtrueに再変換できると思います.
一度行っても戻らないわけにはいかない
だからこれを後で実施することにしました.まず選ばれた選手の名前を円の上に置くことにしました.
だから私はまずあなたにconst [Name1, SetName1] = useState("")を作って、それからName Handlerを作りました.
メニューonClickに掛けて、propsで同じくその選手をゲットしました
そしてNameをDragableに入れると、名前が選ばれた選手に変わりました.
比較のために、2番目の円も同じようにして、Name Handler 2を作って掛けました.
でも1番の値は2番の円です
一人では難しいので、隊員と一緒にディスコで行いますが、二人とも原因が見つからず、次回やることにしました
次の文章につづく