일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 포트포워딩
- express
- socket.io
- scrapping
- 웹팩
- Redux
- styled-component
- typescript
- route
- CDN
- sequelize
- 반응형웹
- cicd
- Recoil
- graphql
- react
- 정규표현식
- go
- component
- 회고
- AWS
- npx
- Modal
- javascript animation
- 성능최적화
- 웹크롤링
- docker
- Today
- Total
프로그래밍 공부하기
JS / 계산기 본문
HTML+CSS+Javascript로 계산기 만들기 프로젝트를 수행했으므로 어떻게 만들었는지 주요 내용들을 정리해보려 한다.
CSS
1. 버튼에 마우스를 올리면 색상 바꾸기
.button__row > button:hover {
background-color: #FFB2F5;
}
.button__row > button:active {
background-color: #ef7993;
}
2. 버튼 정중앙 정렬(ex. AC, Enter 버튼)
.clear__and__enter {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.clear__and__enter > button {
border-radius: 10px;
}
Javascript
0. 주요 변수 설정
- firstNum: 숫자(x+y에서 x)
- intermediateOperator: 입력된 연산자(+-*/)
- previousKey: 전에 입력한 버튼 class(number, operator, decimal, clear, calculate)
- previousNum: 숫자(x+y에서 y/Reference 코드) / 계산결과(내 코드)
- secondNum: 숫자(x+y에서 y). Reference에는 없고 내 코드에서 새로 추가하였다.
- firstNum을 빼고 기본값은 undefined 이다. (clear버튼 누르면 기본값으로 초기화된다)
- Reference코드의 경우 firstNum도 기본값이 undefined이며 display.textContent = '0' 으로 화면을 초기화한다.
1. 숫자 연속으로 입력하기
분석)
- (+-*/)를 기준으로 앞부분은 첫번째 숫자, 뒤는 두번째 숫자가 된다.
- 처음에 계산기의 화면의 값은 0이다.
- 0인 상태에서 0을 입력하면 화면에 입력되지 않고, 숫자를 입력하면 화면의 0이 입력한 숫자로 바뀐다.
- 화면에 0이 아닌 숫자가 있는 경우 화면의 숫자 뒤에 숫자를 추가한다.
- 직전에 연산자(+-*/) 입력 후 숫자를 입력하면 화면이 입력한 숫자로 변한다.
처리)
- 현재 계산기의 값이 0이거나 이전에 operator가 입력되었다면 새롭게 숫자를 입력하는 상태이다.
- 그 외의 경우는 기존 값(string)에 새로 입력한 숫자(버튼)를 더한다.
if(display.textContent === '0' || previousKey === 'operator'){
display.textContent = buttonContent;
}else{
display.textContent += buttonContent;
}
previousKey = 'number';
2. 연산자를 누르면 누른 버튼의 색상이 바뀌고 숫자를 누르면 다시 돌아온다.(연산자는 계산기 화면에 표시되지 않는다)
처리)
- 연산자를 누르면 해당 버튼에 isPressed라는 클래스 추가
(<Button Class=operator isPressed...>로 만든다.)
- css에서 isPressed 클래스 색상 변경
- 숫자를 눌렀을 때 이전 누른 버튼이 연산자라면 해당 버튼의 isPressed 클래스를 제거한다.
(<Button Class=operator..>로 만든다.)
- 일단 여기서는 pressedOperator[0]만 isPressed를 제거했지만 사실 pressedOperator 배열의 요소 모두의 isPressed를 제거해주어야 한다.(Reference에서는 그렇게 한다)
const target = event.target;
//...number 버튼을 누른 경우
if(previousKey === 'operator'){
let pressedOperator = document.getElementsByClassName('isPressed')
pressedOperator[0].classList.remove('isPressed');//일단 0번째 클래스만 제거
}
//...operator 버튼을 누른 경우
//누른 버튼의 html 태그에 isPressed 클래스를 추가한다.
target.classList.add('isPressed');
3. .7을 입력하면 0.7이 입력된다.
처리)
- .(decimal)을 입력할 때 직전에 입력한 값이 숫자라면 화면에 .을 더하고 0이거나 연산자라면 0.을 더한다
if(previousKey === 'number' || display.textContent === '0'){
display.textContent += buttonContent;
}else if(previousKey === 'operator'){
display.textContent = '0' + buttonContent;
}
4. Enter를 누르면 이전 연산 수행
분석)
- 3, -, 3, enter, enter 입력 = 3-3-3 = -3
- 연산자가 없는 상태에서 Enter를 누르면 동작X
- 이전 연산값을 기억해야한다.
처리1(Reference))
- Reference의 경우 firstNum을 undefined로 기본값을 가지므로 if(firstNum) 을 통해 숫자와 연산자가 입력되었는지 확인할 수 있다.
- 처음 Enter를 누른 경우(else) 현재 계산기에 보이는 값(두번째 숫자)을 previousNum에 넣고 계산하여 화면에 결과를 보여준다.
- 그 후 Enter를 눌렀다면 현재 계산기에 보이는 값과 두번째 숫자(previousNum)를 계산하여 화면에 보여준다.
ex1. '10 - 3 Enter' 를 입력했다면 previousNum = 3, display.textContent = 7이 된다.
ex2. ex1 후에 다시 'Enter'를 입력했다면 display.textContent = 7 - 3 = 4가 된다.
if (firstNum){
if (previousKey === 'calculate') {
display.textContent = calculate(display.textContent, intermediateOperator, previousNum);
} else {
previousNum = display.textContent;
display.textContent = calculate(firstNum, intermediateOperator, display.textContent);
}
}
처리2(내 방식))
- 원리는 동일한데 previousNum의 의미가 다르고 secondNum이라는 변수를 추가하였다.
- secondNum이라는 변수를 따로 만들어서 두번째 숫자를 저장한다.(Reference의 경우 두번째 숫자를 PreviousNum에 넣었다.)
- PreviousNum에는 현재 계산기에 보여지는 숫자를 넣었다.
if (action === 'calculate') {
if(intermediateOperator === undefined){
return;
}
if(previousKey === 'calculate'){
previousNum = calculate(previousNum, intermediateOperator, secondNum);
display.textContent = previousNum;
}else{
secondNum = display.textContent;
previousNum = calculate(firstNum, intermediateOperator, secondNum);
display.textContent = previousNum;
}
previousKey = 'calculate';
}
5. 다항식 처리
처리1(Reference))
- 연산자 버튼을 눌렀는데 첫번째 숫자와 연산자가 이미 존재하는 경우 앞의 값을 계산해야 한다.
- ex. '1+2'를 클릭한 상태에서 '-'를 클릭한 상황이라 볼 수 있다. 이 경우 1+2를 연산해주어서 화면에 표시해야함
- 현재 입력된 연산자 앞의 값 앞의 값 혹은 앞의 값을 계산하여 firstNum으로 할당한다.
- ex1. '1+2'를 클릭한 상태에서 '-'가 왔다면 앞의 1+2를 계산하여 firstNum으로 만든다.
- ex2. '1'을 입력한 상태에서 '+'가 왔다면 1을 firstNum으로 만든다.
//연산자 버튼을 눌렀다면...
if (firstNum && intermediateOperator && previousKey !== 'operator' && previousKey !== 'calculate') {
display.textContent = calculate(firstNum, intermediateOperator, display.textContent);
}
firstNum = display.textContent;
처리2(내코드))
- Reference와 원리는 동일한데 secondNum을 만들어서 이를 할당해주었다.
//연산자 버튼 눌렀다면...
if(firstNum !== undefined && intermediateOperator !== undefined && previousKey === 'number'){
secondNum = display.textContent;
firstNum = calculate(firstNum, intermediateOperator, secondNum);
display.textContent = firstNum;
}else{
firstNum = display.textContent;
}
6. 키보드로도 작동되게 한다.
처리)
- 입력한 키에 알맞는 버튼 클릭 이벤트를 발생시킨다.
- 숫자, 연산자의 경우 키가 여러개 이므로 일단 숫자인경우/연산자인경우로 나누고 그 안에서 다시 해당 입력에 해당하는 버튼을 찾는다.
(키보드 9 > 숫자 > '9'버튼 클릭 이벤트)
window.addEventListener('keydown', function (event){
const key = event.key;
if(key >= '0' && key <= '9'){
let classList = document.getElementsByClassName("number");
for(let i=0; i < classList.length; i++){
if(classList[i].textContent === key){
classList[i].click();
break;
}
}
}else if(key == 'Enter'){
document.getElementsByClassName("calculate")[0].click();
}else if(key == 'Escape'){
//....(생략)
previousNum이라는 변수의 의미를 착각해서 코드가 복잡해진 것 같다...ㅠㅠ previousNum이 무슨 뜻일지 먼저 집착하기 보단 어떻게 문제를 풀지 방법을 먼저 생각하고 previousNum을 적절히 끼워넣는 식으로 하는 것이 더 좋았을 것 같다.
'Project > Practice' 카테고리의 다른 글
TypeScript / Project Timer (0) | 2021.04.05 |
---|---|
GraphQL / Tour Sight Search (0) | 2021.02.21 |
socket.io / 실시간 채팅 (0) | 2021.02.09 |
JSAnimation / BrawlStars GunFight! (0) | 2021.01.18 |
DOM / Twittller (0) | 2020.12.30 |