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 값을 바꾸려고 했는데 작동이 되지 않았다.
문제점
- 콘솔에 fish.style을 콘솔에 찍었을 때 공란이 떴다.
- parseInt()를 수행한 후에 fish.style.left를 콘솔에 찍어보았을 때, NaN이 찍혔다.
이유?
- fish.style을 통해 스타일을 확인하는 것은 인라인 스타일을 확인하는 것이다.
내가 작성한 코드는 인라인 스타일이 아니라 CSS 스타일 시트에 정의된 스타일이기 때문에 해당 방법으로는 스타일 정보를 얻을 수 없다. - parseInt()는 문자열의 시작이 숫자가 아니면 NaN이 저장된다. 첫 번째 문제로 인해 fish.style이 공란이라 숫자가 아니기 때문에 NaN이라고 콘솔에 찍힌 것이다.
해결방법?
- .getComputedStyle() 메서드를 활용하여 스타일 정보를 얻는다.
(.style 버림, parseInt() 사용. 가장 바람직함) - CSS 스타일 시트에 정의된 스타일을 인라인 스타일로 변경한다.
(.style 사용, parseInt() 사용. 하지만 보통 html 파일과 CSS 파일을 따로 분리하기 때문에 비추) - 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() 메소드를 활용하자!
'Trouble Shooting' 카테고리의 다른 글
[SpringBoot & Postman] HTTP method names must be tokens 오류 해결 (0) | 2024.06.25 |
---|---|
[NCP] Server 생성 시 잘못된 IP입니다. 해결 방법 (1) | 2024.05.28 |
[SpringBoot] SpringBoot 3 버전 Querydsl build.gradle 설정 오류 및 해결 (0) | 2024.05.07 |
[Spring] beancreationexception 오류 해결 (0) | 2024.05.03 |
[JSONObject] Date 타입 처리 방법 (0) | 2024.03.22 |