Trouble Shooting

🛠 물고기 방향키 이동 예제 🛠 .style vs .getComputedStyle(), parseInt() vs Number()

깨구르르 2024. 3. 7. 19:08
728x90

자바스크립트를 이용해서 방향키를 눌렀을 때 해당 방향으로 물고기가 이동하게 하는 문제를 푸는 중이었다.

물고기의 방향을 각각 변수로 선언했는데, 물고기가 움직이지 않았다.

살.... 려.... 줘................

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #panel {
            width: 600px;
            height: 400px;
            border: 1px solid #999;
            position: relative;
            overflow: hidden;
        }

        #fish {
            position: absolute;
            left: 50px;
            top: 200px;
        }
    </style>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const fish = document.getElementById('fish');
            document.addEventListener('keydown', function (e) {
                let x = parseInt(fish.style.left.slice(0, -2));
                let y = parseInt(fish.style.top.slice(0, -2));
                switch (e.keyCode) {
                    case 37:
                        x -= 10;
                        fish.style.left = x + 'px';
                        break;
                    case 39:
                        x += 10;
                        fish.style.left = x + 'px';
                        break;
                    case 38:
                        y -= 10;
                        fish.style.top = y + 'px';
                        break;
                    case 40:
                        y += 10;
                        fish.style.top = y + 'px';
                        break;
                }
            });
        });
    </script>
</head>

<body>
    <div id="panel">
        <img src="../../images2/fish.png" id="fish">
    </div>
</body>

</html>

 

위와 같이 parseInt()를 사용하여 fish의 left와 top 값을 바꾸려고 했는데 작동이 되지 않았다.

 

문제점
  1. 콘솔에 fish.style을 콘솔에 찍었을 때 공란이 떴다.
  2. parseInt()를 수행한 후에 fish.style.left를 콘솔에 찍어보았을 때, NaN이 찍혔다.

 

이유?

  1. fish.style을 통해 스타일을 확인하는 것은 인라인 스타일을 확인하는 것이다.
    내가 작성한 코드는 인라인 스타일이 아니라 CSS 스타일 시트에 정의된 스타일이기 때문에 해당 방법으로는 스타일 정보를 얻을 수 없다.
  2. parseInt()는 문자열의 시작이 숫자가 아니면 NaN이 저장된다. 첫 번째 문제로 인해 fish.style이 공란이라 숫자가 아니기 때문에 NaN이라고 콘솔에 찍힌 것이다.

 

해결방법?
  1. .getComputedStyle() 메서드를 활용하여 스타일 정보를 얻는다.
    (.style 버림, parseInt() 사용. 가장 바람직함)
  2. CSS 스타일 시트에 정의된 스타일을 인라인 스타일로 변경한다.
    (
    .style 사용, parseInt() 사용. 하지만 보통 html 파일과 CSS 파일을 따로 분리하기 때문에 비추)
  3. Number()를 이용하여 형 변환을 한다.
    (.style 사용, parseInt() 버림. 왕비추. 근본적인 해결책도, 좋은 해결책도 아니다. 이유는 아래에)

 

해결방법 적용

1. getComputedStyle() 활용

  • getComputedStyle() 메소드를 사용하면 요소에 적용된 모든 스타일을 가져올 수 있다.
    👉 인라인 스타일과 CSS 스타일 시트에 정의된 스타일을 모두 반영한다.
  • 활용 코드
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #panel {
            width: 600px;
            height: 400px;
            border: 1px solid #999;
            position: relative;
            overflow: hidden;
        }

        #fish {
            position: absolute;
            left: 50px;
            top: 200px;
        }
    </style>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const fish = document.getElementById('fish');
            document.addEventListener('keydown', function (e) {
                let computedStyle = window.getComputedStyle(fish);
                let x = parseInt(computedStyle.left);
                let y = parseInt(computedStyle.top);
                switch (e.keyCode) {
                    case 37:
                        x -= 10;
                        computedStyle.left = x + 'px';
                        break;
                    case 39:
                        x += 10;
                        computedStyle.left = x + 'px';
                        break;
                    case 38:
                        y -= 10;
                        computedStyle.top = y + 'px';
                        break;
                    case 40:
                        y += 10;
                        computedStyle.top = y + 'px';
                        break;
                }
            });
        });
    </script>
</head>

<body>
    <div id="panel">
        <img src="../../images2/fish.png" id="fish">
    </div>
</body>

</html>

 

2. 인라인 스타일로 변경

  • .style은 인라인 스타일에 있는 스타일을 가져오는 것이기 때문에, CSS 스타일 시트에 있던 스타일을 인라인 스타일로 옮기면 해결이 가능하다.
  • 하지만, 프로젝트를 할 때 보통 html 파일과 css 파일을 분리하기 때문에 첫 번째 해결방법이 가장 바람직하다.
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #panel {
            width: 600px;
            height: 400px;
            border: 1px solid #999;
            position: relative;
            overflow: hidden;
        }
    </style>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const fish = document.getElementById('fish');
            document.addEventListener('keydown', function (e) {
                let x = parseInt(fish.style.left.slice(0, -2));
                let y = parseInt(fish.style.top.slice(0, -2));
                switch (e.keyCode) {
                    case 37:
                        x -= 10;
                        fish.style.left = x + 'px';
                        break;
                    case 39:
                        x += 10;
                        fish.style.left = x + 'px';
                        break;
                    case 38:
                        y -= 10;
                        fish.style.top = y + 'px';
                        break;
                    case 40:
                        y += 10;
                        fish.style.top = y + 'px';
                        break;
                }
            });
        });
    </script>
</head>

<body>
    <div id="panel">
        <img src="../../images2/fish.png" id="fish" style="position: absolute; left: 50px; top: 200px;">
    </div>
</body>

</html>

 

3. Number() 활용

  • Number()0, [], null을 0으로 반환하기 때문에 fish.style을 0으로 반환한다. 따라서 아래 코드대로 작성하면 실행은 잘 되지만 좋은 코드라고 볼 수는 없다.
  • 활용 코드
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #panel {
            width: 600px;
            height: 400px;
            border: 1px solid #999;
            position: relative;
            overflow: hidden;
        }

        #fish {
            position: absolute;
            left: 50px;
            top: 200px;
        }
    </style>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const fish = document.getElementById('fish');
            document.addEventListener('keydown', function (e) {
                let x = Number(fish.style.left.slice(0, -2));
                let y = Number(fish.style.top.slice(0, -2));
                switch (e.keyCode) {
                    case 37:
                        x -= 10;
                        fish.style.left = x + 'px';
                        break;
                    case 39:
                        x += 10;
                        fish.style.left = x + 'px';
                        break;
                    case 38:
                        y -= 10;
                        fish.style.top = y + 'px';
                        break;
                    case 40:
                        y += 10;
                        fish.style.top = y + 'px';
                        break;
                }
            });
        });
    </script>
</head>

<body>
    <div id="panel">
        <img src="../../images2/fish.png" id="fish">
    </div>
</body>

</html>

 

관련 내용 정리

1. .style과 .getComputedStyle() 비교

  .style .getComputedStyle()
공통점 - 기능 스타일을 반환
차이점 - 적용 범위 인라인 스타일 인라인 스타일 + CSS 스타일 시트에 정의된 스타일

 

2. parseInt()와 Number() 비교

  parseInt() Number()
기능 주어진 문자열을 정수로 변환 주어진 문자열을 숫자로 변환
특징 - 문자열의 시작 부분부터 숫자를 읽어 들임. 숫자 이외의 문자가 나타나면 그 뒤의 문자는 무시
- 두 번째 매개변수로 진수를 지정할 수 있음. 이 매개변수가 생략되면 10진수로 가정됨
- 문자열이 숫자 형식으로 이루어져 있어야 함
- 문자열 앞뒤의 공백은 무시됨
주의점 문자열의 시작 부분에 숫자가 없다면 NaN을 반환 - 값이 숫자 형식으로 이루어져 있지 으면 NaN을 반환
- 0, [] (빈 배열), null을 0으로 타입 변환

 

결론

👉 .style보다 포괄적으로 사용할 수 있는 .getComputedStyle() 메소드를 활용하자!

이유를 알고 나니 속이 시원~!~!

 

728x90