πŸ–±οΈ λ“œλž˜κ·Έ μ˜μ—­ - FRONTENDBOOTCAMP-13th/JS-07-7zzang-Arcade GitHub Wiki

ꡬ뢄

  • λ‚ μ§œ : 2025.05.15
  • μ’…λ₯˜ : 버그
  • μš°μ„ μˆœμœ„ : πŸ”΄

1. 문제 상황

λ“œλž˜κ·Έ λ°•μŠ€λ₯Ό κ·Έλ¦¬λŠ”λ° μ‹œμž‘μ  μœ„μΉ˜λ₯Ό λ§ˆμš°μŠ€κ°€ 인식은 μž˜ν•˜μ§€λ§Œ ν΄λ¦­ν•˜κ³  κ·Έλƒ₯ 마우슀λ₯Ό 움직여도 λ°•μŠ€κ°€ μƒμ„±λ˜λŠ” λ¬Έμ œκ°€ λ°œμƒλ˜μ—ˆλ‹€.

클릭 … ν•˜κ³  클릭해도 λ°•μŠ€κ°€ μƒκ²¨λ²„λ¦¬λŠ” 문제 뿐만 μ•„λ‹ˆλΌ, 이전 λ°•μŠ€ μ˜μ—­μ΄ λ‚¨μ•„μžˆμ–΄μ„œ 이 뢀뢄이 λ Œλ”λ§μ΄ 되고 ν˜„μž¬ λ°•μŠ€ μ˜μ—­μ΄ λ Œλ”λ§ λ˜λŠ” λ¬Έμ œλ„ λ°œμƒν–ˆλ‹€.

또, μΊ”λ²„μŠ€ μ˜μ—­ μ•ˆμ—μ„œ 첫 클릭을 ν•΄μ•Όλ§Œ λ°•μŠ€κ°€ μƒμ„±λ˜λŠ”λ°, κ·Έ 이후 λ°”κΉ₯ μ˜μ—­μ„ λ„˜μ–΄μ„œ λ“œλž˜κ·Έ 해도 μ˜μ—­μ΄ μƒμ„±λ˜λŠ” λ¬Έμ œκ°€ λ°œμƒν–ˆλ‹€.


2. 원인

canvas.addEventListener에 각각 mousedown, mousemove, mouseup, mouseleaveλ₯Ό λ“±λ‘ν–ˆλŠ”λ°, λ“œλž˜κ·Έ μƒνƒœμž„μ„ κ΅¬λ³„ν•˜κΈ° μœ„ν•œ λ³€μˆ˜κ°€ μ—†μ—ˆλ‹€.

λ”°λΌμ„œ λ‚΄κ°€ ν˜„μž¬ λ“œλž˜κ·Έ 쀑인지, λ“œλž˜κ·Έκ°€ κ°€λŠ₯ν•œμ§€ νŒλ‹¨μ΄ λΆˆκ°€λŠ₯ν•΄μ„œ 클릭 β†’ 클릭 ν–ˆμ„ λ•Œλ„, 클릭 β†’ 마우슀 이동해도 λ°•μŠ€κ°€ μƒμ„±λ˜λŠ” ν˜„μƒμ΄ λ°œμƒν–ˆλ˜ 것이닀.

λ˜ν•œ λ“œλž˜κ·Έ λ°•μŠ€λ„ μΊ”λ²„μŠ€λ₯Ό 톡해 κ·Έλ¦¬λŠ”λ°, 이 뢀뢄을 μ΄ˆκΈ°ν™” μ•ˆ ν–ˆλ˜ 점 λ•Œλ¬Έμ— 이전 μ˜μ—­μ΄ λ‚¨μ•„μžˆλ˜ 것이닀.


3. ν•΄κ²° κ³Όμ •

λ¨Όμ € λ“œλž˜κ·Έ μ‹œμž‘ μœ„μΉ˜μ™€ μƒνƒœλ₯Ό λ‹€μŒκ³Ό 같이 μ„€μ •ν–ˆλ‹€.

 // 마우슀 클릭 μœ μ§€ μƒνƒœ λ‚˜νƒ€λ‚΄κΈ°
  canvas.addEventListener('mousedown', e => {
    if (isGameOver) return;

    startX = e.offsetX;
    startY = e.offsetY;
    draggable = true; // μΆ”κ°€
    isDragging = false; // μΆ”κ°€
  });

μΆ”κ°€ν•œ 뢀뢄을 λ“œλž˜κ·ΈμΌ λ•Œ λ°˜μ˜ν•˜μ—¬μ„œ μˆ˜μ •ν–ˆλ‹€.

canvas.addEventListener('mousemove', e => {
    if (!draggable || isGameOver) return;

    endX = e.offsetX;
    endY = e.offsetY;

if (!isDragging && (Math.abs(endX - startX) > dragThreshold || Math.abs(endY - startY) > dragThreshold)) {
      isDragging = true;
    }

    if (!isDragging) return;
    
    ...
    });

쑰건문을 톡해 λ“œλž˜κ·Έ μƒνƒœλ₯Ό λ¦¬ν„΄ν•˜κ³ , λ“œλž˜κ·Έ 쀑이며, dragThresholdλ₯Ό 5둜 μ‘°μ •ν•΄, λ§ˆμ§€λ§‰ λ“œλž˜κ·Έ μœ„μΉ˜μ™€ μ‹œμž‘ μœ„μΉ˜κ°€ 5λ₯Ό λ„˜λŠ” 경우, λ˜λŠ” dragThreshold이 5λ₯Ό λ„˜λŠ” 경우면 λ“œλž˜κ·Έ 쀑이라고 νŒλ‹¨ν•˜κ²Œ μ„€μ •ν•˜μ—¬ μƒνƒœλ₯Ό λ°”κΏ”μ£Όμ—ˆλ‹€.

ν•΄λ‹Ή λΆ€λΆ„ 이후, mouseupμ—μ„œ ν† λ§ˆν†  선택 및 제거 λ‘œμ§μ„ μˆ˜ν–‰ν•˜κ³  λ‚˜λ©΄ λ“œλž˜κ·Έ μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ” λ³€μˆ˜λ“€μ˜ 값을 false둜 μ΄ˆκΈ°ν™”ν•˜λ„λ‘ μ„€μ •ν–ˆλ‹€.

canvas.addEventListener('mouseup', e => {
    if (isGameOver) return;

    endX = e.offsetX;
    endY = e.offsetY;
    
    ...선택 둜직
    
    draggable = false;
    isDragging = false;

    clearSelect();

    ctx.clearRect(0, 0, canvas.width, canvas.height);

    redrawGrid();
  });

그런 λ‹€μŒ, 선택을 μ΄ˆκΈ°ν™” ν•˜λŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κ³ , μΊ”λ²„μŠ€λ‘œ κ·Έλ¦° μ˜μ—­λ„ μ΄ˆκΈ°ν™”ν•œ λ‹€μŒ, 선택 둜직 이후 μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈ ν•˜κΈ° μœ„ν•΄ μΊ”λ²„μŠ€λ₯Ό λ‹€μ‹œ κ·Έλ¦¬λŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν–ˆλ‹€.

μΊ”λ²„μŠ€λ₯Ό 그릴 λ•Œ, μ΄μ–΄μ„œ 그릴 것이 μ•„λ‹ˆλΌλ©΄ κΌ­ μ΄ˆκΈ°ν™”λ₯Ό ν•΄μ£ΌκΈ°. 특히 λ“œλž˜κ·ΈμΌ λ•ŒλŠ” μƒνƒœλ₯Ό κΌ­ μ „λ‹¬ν•˜μ—¬ 계속 쑰건을 ν™•μΈν•˜λ„λ‘ μ„€μ •ν•΄μ•Ό 함을 μžŠμ§€ μ•Šλ„λ‘ ν•΄μ•Όν•œλ‹€λŠ” 것을 배우게 λ˜μ—ˆλ‹€.