[TIL] 211001

Lee SyongΒ·2021λ…„ 10μ›” 1일
0

TIL

λͺ©λ‘ 보기
44/204
post-thumbnail

πŸ“ 였늘 ν•œ 것

  1. λ―Έλ‹ˆ κ²Œμž„ κ΅¬ν˜„ 쀑

πŸ“š 배운 것

λ‹Ήκ·Όλ§Œ 클릭해야 ν•˜λŠ” κ²Œμž„

μ–΄μ œ ν’€μ΄μ—μ„œ μ΄μ–΄μ„œ


πŸ“Œ 직접 κ΅¬ν˜„

8. μž¬μ‹œμž‘ λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄

  1. μž¬μ‹œμž‘ λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄

1) 이전 κ²Œμž„μ˜ λ‹Ήκ·Όκ³Ό λ²Œλ ˆκ°€ μ—†μ–΄μ Έμ•Ό ν•œλ‹€.
2) replay ❓ 창이 μ—†μ–΄μ Έμ•Ό ν•œλ‹€.
3) λ‹€μ‹œ 2.κ°€ μΌμ–΄λ‚˜μ•Ό ν•œλ‹€. - (1), (3)만
4) 타이머가 'λ‹€μ‹œ μ²˜μŒλΆ€ν„°' μž‘λ™ν•΄μ•Ό ν•œλ‹€.
5) bg.mp3 배경음이 'λ‹€μ‹œ μ²˜μŒλΆ€ν„°' μž¬μƒλ˜μ–΄μ•Ό ν•œλ‹€.
6) κ²Œμž„ μ‹œμž‘ λ²„νŠΌμ΄ λ‹€μ‹œ 보여야 ν•œλ‹€.

πŸ’‘ λ™μ μœΌλ‘œ μƒμ„±ν•œ μš”μ†Œμ— 이벀트 바인딩 ν•˜λŠ” 방법

  • 이벀트 μœ„μž„ μ‘μš©

πŸ’‘ μ˜€λ””μ˜€ μ²˜μŒλΆ€ν„° λ‹€μ‹œ μž¬μƒν•˜λŠ” 방법

Audio.pause();

Audio.currentTime = 0;
Audio.play();

πŸ“Œ 8번째 μš”κ΅¬ 사항 - μ½”λ“œ λͺ¨μŒ

// field μ•ˆμ„ ν΄λ¦­ν–ˆμ„ λ•Œ
field.addEventListener('click', function (event) {
  // 8. 클릭된 게 μž¬μ‹œμž‘ λ²„νŠΌμ΄λ©΄
  if (event.target.className === 'fas fa-redo') {
    // πŸ”Ž 1) 이전 κ²Œμž„μ˜ λ‹Ήκ·Όκ³Ό λ²Œλ ˆκ°€ μ—†μ–΄μ Έμ•Ό ν•œλ‹€.
    const carrots = document.querySelectorAll('img[alt="carrot"]');
    const bugs = document.querySelectorAll('img[alt="bug"]');

    for (let i = 0; i < carrots.length; i++) {
      carrots[i].remove();
    }

    for (let i = 0; i < bugs.length; i++) {
      bugs[i].remove();
    }

    // πŸ”Ž 2) replay ❓ 창이 μ—†μ–΄μ Έμ•Ό ν•œλ‹€.
    const result = document.querySelector('.result');
    result.remove();

    // πŸ”Ž 3) λ‹€μ‹œ 2.κ°€ μΌμ–΄λ‚˜μ•Ό ν•œλ‹€. - (1), (3), (4)만
    // (1) field μ•ˆμ— λ‹Ήκ·Ό 10κ°œμ™€ 벌레 7λ§ˆλ¦¬κ°€ λžœλ€ν•œ μœ„μΉ˜μ— λ°°μΉ˜λ˜μ–΄μ•Ό ν•œλ‹€.
    const rect = field.getBoundingClientRect();

    for (let i = 0; i < 10; i++) {
      const carrot = document.createElement('img');
      carrot.setAttribute('src', 'img/carrot.png');
      carrot.setAttribute('alt', 'carrot');

      carrot.style.left = (rect.width - 120) * Math.random() + 'px';
      carrot.style.top = (rect.height - 120) * Math.random() + 'px';

      carrot.style.width = '120px';
      field.appendChild(carrot);
    }

    for (let i = 0; i < 7; i++) {
      const bug = document.createElement('img');
      bug.setAttribute('src', 'img/bug.png');
      bug.setAttribute('alt', 'bug');

      bug.style.left = (rect.width - 80) * Math.random() + 'px';
      bug.style.top = (rect.height - 80) * Math.random() + 'px';

      bug.style.width = '80px';
      field.appendChild(bug);
    }

    // (3) 클릭 κ°€λŠ₯ νšŸμˆ˜κ°€ 10으둜 λ°”λ€Œμ–΄μ•Ό ν•œλ‹€.
    clickLimit.innerHTML = 10;

    // (4) bg.mp3 배경음이 μž¬μƒλ˜μ–΄μ•Ό ν•œλ‹€.
    bg_mp3.currentTime = 0;
    bg_mp3.play();

    // πŸ”Ž 4) κ²Œμž„ μ‹œμž‘ λ²„νŠΌμ΄ λ‹€μ‹œ 보여야 ν•œλ‹€.
    startBtn.style.visibility = 'visible';

    // πŸ”Ž 5) 타이머가 'λ‹€μ‹œ μ²˜μŒλΆ€ν„°' μž‘λ™ν•΄μ•Ό ν•œλ‹€.
    timer.innerHTML = `0:10`;
    time = 9;
    startWorkingTimer();
  }
});

9. ν…ŒμŠ€νŠΈ 및 점검

πŸ’‘ setting에 μœ„, μ•„λž˜ margin 값을 μΆ”κ°€ν•˜λ‹ˆκΉŒ 의미 μ—†λŠ” scrollbarκ°€ 생긴닀.
β†’ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ margin λŒ€μ‹  top을 μ΄μš©ν•΄ setting의 μœ„μΉ˜λ₯Ό μ‘°μ ˆν–ˆλ‹€.


πŸ“Œ 쀑간 μ™„μ„± μ½”λ“œ

일단 λͺ¨λ“  λ‚΄μš©μ„ κ΅¬ν˜„ μ™„λ£Œν–ˆκ³ , λͺ¨λ‘ 였λ₯˜ 없이 정상 μž‘λ™μ€ λœλ‹€

πŸ”Ž HTML

<html>
  <body>
    <div class="setting">
      <div class="setting-box">
        <button class="setting-startBtn" type="button"><i class="fas fa-play"></i></button>
        <div class="setting-timer">00:00</div>
        <div class="setting-limit">0</div>
      </div>
    </div>
    <div class="field"></div>
  </body>
</html>

πŸ”Ž CSS

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

button {
  border: 5px solid black;
  border-radius: 20px;
  background-color: wheat;
  width: 100px;
  height: 100px;
  cursor: pointer;
  display: block;
  margin: 0 auto;
}

button:hover {
  transform: scale(1.1);
  transition: all 200ms ease;
}

img {
  position: absolute;
}

img:hover {
  transform: scale(1.2);
  transition: all 200ms ease;
}

/* μ‹œμž‘ */

body {
  background: url("img/background.png") no-repeat center / cover;
  font-family: "Gowun Batang", serif;
}

.setting {
  height: 450px;
  position: relative;
}

.setting-box {
  position: absolute;
  top: 30px;
  left: 50%;
  transform: translate(-50%);
}

.setting-timer {
  border: 5px solid black;
  border-radius: 20px;
  background-color: white;
  width: 260px;
  height: 80px;
  margin: 15px auto;
  text-align: center;
  font-size: 2.5em;
  line-height: 1.3;
}

.fas {
  font-size: 40px;
}

.setting-limit {
  border: 4px solid black;
  border-radius: 50%;
  background-color: orange;
  color: white;
  width: 100px;
  height: 100px;
  margin: 0 auto;
  text-align: center;
  line-height: 1.5;
  font-size: 3em;
  font-weight: bold;
}

.field {
  height: calc(100vh - 450px);
  position: relative;
}

.result {
  width: 50%;
  margin: 0 auto;
  padding: 10px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-radius: 20px;
  background-color: rgba(0, 0, 0, 0.5);
  text-align: center;
  font-size: 3em;
  color: white;
}

πŸ”Ž JavaScript

field에 등둝해쀀 클릭 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό 정리해야 ν•˜λŠ”λ° μ–΄μ°¨ν”Ό λ¦¬νŒ©ν† λ§ ν•˜λ©΄μ„œ λ‹€μ‹œ λŒ€λŒ€μ μœΌλ‘œ ν’€μ–΄μ•Ό 될 κ±° κ°™μ•„μ„œ κ·Έλƒ₯ κ·ΈλŒ€λ‘œ λ‘ . μž‘λ™μ€ λ˜λŠ”λ° 정말 μž‘λ™λ§Œ λ˜λŠ” μ½”λ“œλ‹€. λ¦¬νŒ©ν† λ§ ν•„μˆ˜..

'use strict';

// htmlμ—μ„œ λ°›μ•„μ˜¨ μš”μ†Œλ“€
const startBtn = document.querySelector('.setting-startBtn');
const timer = document.querySelector('.setting-timer');
const clickLimit = document.querySelector('.setting-limit');
const field = document.querySelector('.field');

// μ˜€λ””μ˜€ νŒŒμΌμ„ λ³€μˆ˜μ— ν• λ‹Ή
const bg_mp3 = new Audio('sound/bg.mp3');
const win_mp3 = new Audio('sound/game_win.mp3');

// λ‹Ήκ·Ό, 벌레 랜덀 배치
function placeImgRandomly () {
  const rect = field.getBoundingClientRect();

  for (let i = 0; i < 10; i++) {
    const carrot = document.createElement('img');
    carrot.setAttribute('src', 'img/carrot.png');
    carrot.setAttribute('alt', 'carrot');

    carrot.style.left = (rect.width - 120) * Math.random() + 'px';
    carrot.style.top = (rect.height - 120) * Math.random() + 'px';

    carrot.style.width = '120px';
    field.appendChild(carrot);
  }

  for (let i = 0; i < 7; i++) {
    const bug = document.createElement('img');
    bug.setAttribute('src', 'img/bug.png');
    bug.setAttribute('alt', 'bug');

    bug.style.left = (rect.width - 80) * Math.random() + 'px';
    bug.style.top = (rect.height - 80) * Math.random() + 'px';

    bug.style.width = '80px';
    field.appendChild(bug);
  }
}

// λ‹Ήκ·Ό, 벌레 제거 & replay μ°½ 제거
function init ()  {
  const carrots = document.querySelectorAll('img[alt="carrot"]');
  const bugs = document.querySelectorAll('img[alt="bug"]');

  for (let i = 0; i < carrots.length; i++) {
    carrots[i].remove();
  }

  for (let i = 0; i < bugs.length; i++) {
    bugs[i].remove();
  }

  const result = document.querySelector('.result');
  result.remove();
}

// 타이머 κ΄€λ ¨
let time = 9;
let decreNum;

function startWorkingTimer () {
  decreNum = setInterval(function () {
    const second = time % 60;
    timer.innerHTML = `0:${second}`;
    time--;

    if (time < 0) {
      clearInterval(decreNum);

      bg_mp3.pause();

      startBtn.style.visibility = 'hidden';

      displayResult('YOU LOST πŸ’©');
    }
  }, 1000);
}

// 문ꡬ & μž¬μ‹œμž‘ λ²„νŠΌ κ΄€λ ¨
function displayResult (text) {
  const gameResult = document.createElement('div');
  gameResult.classList.add('result');
  gameResult.innerHTML = `
    <button class="replayBtn" type="button"><i class="fas fa-redo"></i></button>
    <p>${text}</p>
  `;
  field.appendChild(gameResult);
}



// 2. κ²Œμž„ μ‹œμž‘ λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄
startBtn.addEventListener('click', function startTimer () {
  if (document.querySelector('i[class$="stop"]') === null) {

    placeImgRandomly();

    timer.innerHTML = `0:10`;
    startWorkingTimer();

    clickLimit.innerHTML = 10;

    bg_mp3.play();

    startBtn.innerHTML = '<i class="fas fa-stop"></i>';

  } else {
    bg_mp3.pause();

    const alert_wav = new Audio('sound/alert.wav');
    alert_wav.play();

    clearInterval(decreNum);

    startBtn.style.visibility = 'hidden';

    displayResult('REPLAY ❓');
  }
});



// field μ•ˆμ„ ν΄λ¦­ν–ˆμ„ λ•Œ
field.addEventListener('click', function (event) {
  // 3. 클릭된 게 당근이면
  if (event.target.alt === 'carrot') {

    const carrot_mp3 = new Audio('sound/carrot_pull.mp3');
    carrot_mp3.play();

    clickLimit.innerHTML = clickLimit.innerHTML - 1;

    event.target.remove();

    // 5. μ œν•œ μ‹œκ°„ 내에 λͺ¨λ“  당근을 ν΄λ¦­ν•˜λ©΄
    if (time > 0) {
      if (document.querySelectorAll('img[alt="carrot"]').length === 0) {

        bg_mp3.pause();

        win_mp3.play();

        clearInterval(decreNum);

        startBtn.style.visibility = 'hidden';

        displayResult('YOU WON πŸŽ‰');
      }
    }
  }
});



// field μ•ˆμ„ ν΄λ¦­ν–ˆμ„ λ•Œ
field.addEventListener('click', function (event) {
  // 4. 클릭된 게 벌레라면
  if (event.target.alt === 'bug') {

    bg_mp3.pause();

    const bug_mp3 = new Audio('sound/bug_pull.mp3');
    bug_mp3.play();

    clearInterval(decreNum);

    startBtn.style.visibility = 'hidden';

    displayResult('YOU LOST πŸ’©');
  }
});



// field μ•ˆμ„ ν΄λ¦­ν–ˆμ„ λ•Œ
field.addEventListener('click', function (event) {
  // 8. 클릭된 게 μž¬μ‹œμž‘ λ²„νŠΌμ΄λ©΄
  if (event.target.className === 'fas fa-redo') {

    init();

    placeImgRandomly();

    clickLimit.innerHTML = 10;

    timer.innerHTML = `0:10`;
    time = 9;
    startWorkingTimer();

    bg_mp3.currentTime = 0;
    bg_mp3.play();

    startBtn.style.visibility = 'visible';
  }
});

πŸ“Œ κ°•μ˜ μ°Έκ³ ν•΄μ„œ μ½”λ“œ μˆ˜μ •

κ°•μ˜λ₯Ό μ°Έκ³ ν•΄ λ‚΄ μ½”λ“œλ₯Ό λ¦¬νŒ©ν† λ§ ν•œ ν›„, μ‹€ν–‰λ˜μ§€ μ•Šμ„ 경우 였λ₯˜ νŒŒμ•… 및 원인 뢄석


1. HTML λ§ˆν¬μ—… & CSS μŠ€νƒ€μΌλ§

  • HTML λ§ˆν¬μ—…μ„ ν•˜λ©΄μ„œ μ•„μ˜ˆ replay 창을 λ§Œλ“€μ–΄μ€€ ν›„ CSSμ—μ„œ display: none 을 μ μš©ν•¨. (κ·Έ ν›„ λ²„νŠΌμ— classλ₯Ό 'pop-up pop-up-hide'라고 μ§€μ •ν•΄μ€Œ.)

2. λ‹Ήκ·Όκ³Ό 벌레 랜덀 배치

1) λ‚΄κ°€ 처음 μž‘μ„±ν•œ μ½”λ“œ

// λ‹Ήκ·Ό, 벌레 랜덀 배치
function placeImgRandomly () {
  const rect = field.getBoundingClientRect();

  for (let i = 0; i < 10; i++) {
    const carrot = document.createElement('img');
    carrot.setAttribute('src', 'img/carrot.png');
    carrot.setAttribute('alt', 'carrot');

    carrot.style.left = (rect.width - 120) * Math.random() + 'px';
    carrot.style.top = (rect.height - 120) * Math.random() + 'px';

    carrot.style.width = '120px';
    field.appendChild(carrot);
  }

  for (let i = 0; i < 7; i++) {
    const bug = document.createElement('img');
    bug.setAttribute('src', 'img/bug.png');
    bug.setAttribute('alt', 'bug');

    bug.style.left = (rect.width - 80) * Math.random() + 'px';
    bug.style.top = (rect.height - 80) * Math.random() + 'px';

    bug.style.width = '80px';
    field.appendChild(bug);
  }
}

2) 1μ°¨ μˆ˜μ •

μ•„λž˜μ™€ 같이 ν–ˆμœΌλ‚˜
coordArray is not defined 였λ₯˜ λ°œμƒ

// λ‹Ήκ·Ό, 벌레 랜덀 배치
function placeImgRandomly () {
  makeImg('carrot', 10, 120);
  makeImg('bug', 7, 80);
}

// λ‹Ήκ·Ό, 벌레 이미지 생성
function makeImg (name, num, size) {
  for (let i = 0; i < num; i++) {
    randomCoord(size);

    const item = document.createElement('img');
    item.setAttribute('src', `img/${name}.png`);
    item.setAttribute('alt', `${name}`);

    item.style.left = coordArray[0] + 'px';
    item.style.top = coordArray[1] + 'px';

    item.style.width = `${size}px`;

    field.appendChild(item);
  }
}

// λžœλ€ν•œ μ’Œν‘œ 생성
function randomCoord (size) {
  const rect = field.getBoundingClientRect();

  const x = (rect.width - size) * Math.random();
  const y = (rect.height - size) * Math.random();

  const coordArray = [x, y];
  return coordArray;
}

3) 였λ₯˜ 원인 뢄석 πŸ’‘

  • makeImg ν•¨μˆ˜μ—μ„œ coordArray[0]κ³Ό coordArray[1]의 값을 μ“°κΈ° μœ„ν•΄μ„œλŠ”, randomCoord ν•¨μˆ˜λ₯Ό makeImg ν•¨μˆ˜μ—μ„œ 'λ³€μˆ˜μ— ν• λ‹Ή'ν•΄μ€˜μ•Ό ν•œλ‹€.

  • 즉, randomCoord(size); β†’ const coord = randomCoord(size);

  • randomCoord ν•¨μˆ˜μ˜ return 값을 받은 λ³€μˆ˜ coordλ₯Ό λ°”νƒ•μœΌλ‘œ makeImg ν•¨μˆ˜ λ‚΄μ—μ„œ randomCoord ν•¨μˆ˜μ˜ coordArray 값을 μ“Έ 수 μžˆλ‹€.

  • coordArray[0] / coordArray[1] β†’ coord[0] / coord[1]

  • randomCoord(size) 라고만 μ“°λ©΄, makeImg ν•¨μˆ˜μ™€ randomCoord ν•¨μˆ˜κ°€ 연결이 μ•ˆ λΌμ„œ randomCoord ν•¨μˆ˜λ‘œλΆ€ν„° coordArray κ°’, 즉 return 값을 λ°›μ•„μ˜¬ 수 μ—†λ‹€!

4) 2μ°¨ μˆ˜μ •

  • 정상 μž‘λ™ 확인

  • μˆ«μžλŠ” κ·Έλƒ₯ 쓰지 말고, λ³€μˆ˜μ— ν• λ‹Ήν•΄μ„œ λ³€μˆ˜λ₯Ό 쓰도둝 ν•œλ‹€

// λ‹Ήκ·Ό, 벌레 이미지 개수 & 크기
const CARROT_COUNT = 10;
const BUG_COUNT = 7;
const CARROT_SIZE = 120;
const BUG_SIZE = 80;

// λ‹Ήκ·Ό, 벌레 이미지 랜덀 배치
function placeImgRandomly () {
  makeImg('carrot', CARROT_COUNT, CARROT_SIZE);
  makeImg('bug', BUG_COUNT, BUG_SIZE);
}

// λ‹Ήκ·Ό, 벌레 이미지 생성
function makeImg (name, num, size) {
  for (let i = 0; i < num; i++) {
    const coord = randomCoord(size);

    const item = document.createElement('img');
    item.setAttribute('src', `img/${name}.png`);
    item.setAttribute('alt', `${name}`);

    item.style.left = coord[0] + 'px';
    item.style.top = coord[1] + 'px';

    item.style.width = `${size}px`;

    field.appendChild(item);
  }
}

// λžœλ€ν•œ μ’Œν‘œ 생성
function randomCoord (size) {
  const fieldRect = field.getBoundingClientRect();

  return [(fieldRect.width - size) * Math.random(), (fieldRect.height - size) * Math.random()];
}

✨ 내일 ν•  것

  1. μ΄λ²ˆμ—” λ¦¬νŒ©ν† λ§ ν•¨μˆ˜ν™”λ₯Ό 염두에 두고, μ²˜μŒλΆ€ν„° λ‹€μ‹œ κ΅¬ν˜„ν•΄λ³Ό 것 ❕
profile
λŠ₯λ™μ μœΌλ‘œ μ‚΄μž, ν–‰λ³΅ν•˜κ²ŒπŸ˜

0개의 λŒ“κΈ€