이번 시간에는 Array.from, grid를 사용하여 계산기를 만들어보자!
1. preview
See the Pen calculator by KumJungMin (@kumjungmin) on CodePen.
2. html
preview에서 본 계산기는 어떻게 구성되었을까? 자세한 코드를 알아보자!
1) 전체 구조
frmae
은calculator
의 부모로, 내부 자식이 수평&수직 정렬되게 한다.calculator
에는 크게result
,content
가 있다.result
는 결과를 보여주는 영역이다.content
내부에는key-wrap
,clac-wrap
이 있는데, 자판 역할을 한다.
2) 전체 코드
- 위 그림을 코드로 보면 아래와 같다.
<div class="frame"> <div class="calculator"> <div class="result"></div> <!--결과창--> <div class="content"> <div class="key-wrap"></div> <!--좌측 키판--> <div class="calc-wrap"></div> <!--우측 키판--> </div> </div> </div>
3. scss(1)
1) frame 설정하기
frame
가 수평&수직 중앙 정렬이 되도록 그림과 같이 지정한다.
.frame {
width: 400px;
height: 400px;
position: absolute;
top: 50%; //[1]
left: 50%; //[1]
transform: translate(-50%, -50%); //[1]
}
frame
의 자식인calculator
를 수평&수직 중앙 정렬하기 위해 flex를 사용한다.
.frame { ... display: flex; //[2] justify-content: center; //[2] 수평 중앙 align-items: center; //[2] 수직 중앙 background: ...; //배경색은 자유 }
2) calculator 설정하기
(1) 내부 요소 배열하기
calculator
내부에는result
,content
가 있다.
이 두 요소는 아래 그림과 같이 column방향으로 배열되어야 한다.
.calculator {
width: 16rem;
height: 20rem;
display: flex; //[1]
justify-content: flex-end; //[2]
flex-direction: column; //[3]
...
}
[1] 그러기 위해서는 먼저 display: flex
를 한다.
[2] justify-content: flex-end
를 하여 수직 하단 정렬을 한다.
[3] flex-direction
을 column
으로 지정해서, 요소의 방향을 변경한다.
(2) calculator의 배경색을 반투명하게
calculator의 배경색을 반투명으로 설정하여 뒷배경이 흐릿하게 보여야 한다.
.calculator {
background: rgba( 36, 36, 36, 0.75);
box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.7 );
backdrop-filter: blur(4px); //[5]
border-radius: 0.5rem;
border: 1px solid rgba( 255, 255, 255, 0.18 ); //[6]
...
}
[5] backdrop-filter
는 요소 뒤 영역에 그래픽 효과를 적용하는데, blur(4px)
을 하면 요소 뒤 영역이 흐려진다.
(단, 이 효과를 위해서는 요소나 요소의 배경을 반투명하게는 설정해야 함)
[6] backdrop-filter
가 적용되기 위해 rgba
로 배경색을 반투명하게 지정한다.
3) 결과창 꾸미기
- 계산 결과를 알려주는 result에는 아래와 같이 설정한다.
.result { width: 100%; height: 2.5rem; padding: 0 1.4rem; font-weight: 500; font-size: 1.2rem; overflow: auto; box-sizing: border-box; color: #fff; }
4) 키패드 정렬하기
content
에는key-wrap(좌측 키패드)
&calc-wrap(우측 키패드)
이 있다. 이 키패드들은 content에서 좌우 정렬이 되어야 하며,wrap
내부 요소인 숫자&계산 버튼은 일정한 간격으로 배치되어야 한다.
(1) 키패드를 좌우 정렬하기
.content {
width: 100%;
display: flex; //[1]
}
[1] content의 내부 요소들이 좌우 정렬이 되도록 flex
를 설정한다.
.key-wrap,
.calc-wrap {
height: 13rem;
...
}
.key-wrap {
flex: 4; //[2]
...
}
.calc-wrap {
flex: 1; //[2]
}
[2] flex: N
을 설정하여 N비율만큼 차지하게 된다.좌측:우측 = 4:1
비율이 되도록 key-wrap
에는 flex:4
& calc-wrap
에는 flex:1
을 설정한다.
(2) 버튼을 일정하게 정렬하기
.key-wrap,
.calc-wrap {
...
display: grid; //[3]
}
.key-wrap {
grid-template-columns: auto auto auto; //[4]
}
[3] 키패드 내부 버튼들이 격자 배치되도록 display:grid
를 한다.
[4] 좌측 키패드의 버튼이 3열이 되도록 grid-template-columns: auto auto auto
를 해준다.
버튼 디자인의 경우 js을 사용해 버튼을 추가한 후 진행하도록 하자 :)
4. js
1) 필요한 dom 가져오기
- 좌측&우측 키패드에 버튼을 추가하기 위해
querySelector
로 dom을 가져온다. result
의 경우, 연산을 보여줘야하므로querySelector
로 가져온다.const numWrap = document.querySelector('.key-wrap'); //좌측키패드 const calcWrap = document.querySelector('.calc-wrap'); //우측키패드 const result = document.querySelector('.result'); //결과창
2) 버튼과 연산을 위한 변수 선언하기
(1) 좌측 키패드 버튼 선언하기
- 좌측 키패드는
1~9
,초기화(C)
,0
,계산(=)
이 필요하므로 아래와 같이 선언할 수 있다.const keyboard = [1, 2, 3, 4, 5, 6, 7, 8, 9, 'C', 0, '='];
하지만, 1
9를 일일이 작성한다니 너무 비효율적인 거 같다! 🤔🤔N`까지의 숫자를 한 번에 만들 수 있는 방법은 무엇이 있을까?
그렇다면 `
2가지 정도 알아보자!
A. Array.from 사용하기
: Array.from()
은 새로운 배열 객체를 생성할 수 있다.
Array.from(A, B) |
---|
A에는 배열로 반환하고자 하는 이터러블 객체 B에는 배열의 모든 요소에 대해 호출할 맵핑 함수를 선언 |
: 먼저 첫번째 인자에 {length: 9}
를 넣어주면, 길이가 9인 배열이 생성된다.
const keyboard = Array.from({length:9});
//[undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined]
: 그 다음 두 번째 인자는 (v, i)=>i+1
을 하면 index+1 형태의 배열이 생성된다.
const keyboard = Array.from({length:9}, (v,i)=>i+1));
//[1, 2, 3, 4, 5, 6, 7, 8, 9]
: 만약 다른 배열에 넣어서 사용할 경우 전개 연산자를 이용하면 된다.
const keyboard = [...Array.from({length:9}, (v,i)=>i+1), 'C', 0, '='];
//[1, 2, 3, 4, 5, 6, 7, 8, 9, 'C', 0, '=']
B. map() & fill() 사용하기
: 먼저 길이가 9인 배열을 생성한다.
const keyboard = Array(9);
//[undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined]
: fill()
는 배열의 시작 ~ 끝 인덱스 전까지 정적인 값으로 채우는 함수이다.
: 그런데 이 fill()
을 map()
과 같이 사용하면 map()
에서 리턴된 값으로 배열을 채울 수 있다!
const keyboard = Array(9).fill().map((v,i)=>i+1);
////[1, 2, 3, 4, 5, 6, 7, 8, 9]
: 다른 배열에 넣어서 사용할 경우 전개 연산자를 이용하면 된다.
const keyboard = [...Array(9).fill().map((v,i)=>i+1), 'C', 0, '='];
//[1, 2, 3, 4, 5, 6, 7, 8, 9, 'C', 0, '=']
이 예시에서는
Array.from
방식을 사용했지만, 둘 중 어느 것을 사용해도 좋다 :)
지금까지 좌측 키패드 변수 선언에 대해 알아보았으니 이제는 우측&연산 변수도 살펴보자!
(2) 우측 키패드 버튼 & 연산 결과를 담을 변수 선언하기
const calc = ['<-', '+', '-']; //우측 키패드
let formula = []; //연산 결과
- 우측 키패드에서 사용할
지우기(<-)
,더하기(+)
,빼기(-)
버튼 변수를 선언한다. - 연산 결과를 담을 배열(
formula
)을 선언한다.
3) 각각의 키패드에 버튼 추가하기
(1) 좌측 키패드에 버튼 추가하기
for (const i in keyboard) {
const btn = document.createElement('button'); //[1]
btn.classList.add('num'); //[2]
btn.classList.add('label-' + i); //[2]
btn.value = keyboard[i]; //[3]
btn.innerText = keyboard[i]; //[4]
btn.addEventListener('click', calculate); //[5]
numWrap.appendChild(btn); //[6]
}
[1] createElement
을 사용하여 button 요소를 생성한다.
[2] classList.add(클래스명)
으로 button 요소에 클래스를 지정한다.
[3] btn.value
을 사용하면 버튼 요소의 value를 지정할 수 있다.
[4] innerText
로 버튼 내부의 글자를 작성한다.
[5] addEventListener
로 click 이벤트시 calculate 함수를 실행하게 한다.
[6] 완성된 버튼 요소를 numWrap
의 자식으로 추가한다.
(2) 우측 키패드에 버튼 추가하기
for(const i in calc) {
const btn = document.createElement('button'); //[1]
btn.classList.add('calc'); //[2]
btn.value = calc[i]; //[3]
btn.innerText = calc[i]; //[4]
btn.addEventListener('click', calculate);//[5]
calcWrap.appendChild(btn); //[6]
}
[1] createElement
을 사용하여 button 요소를 생성한다.
[2] classList.add(클래스명)
으로 button 요소에 클래스를 지정한다.
[3] btn.value
을 사용하면 버튼 요소의 value를 지정할 수 있다.
[4] innerText
로 버튼 내부의 글자를 작성한다.
[5] addEventListener
로 click 이벤트시 calculate 함수를 실행하게 한다.
[6] 완성된 버튼 요소를 calcWrap
의 자식으로 추가한다.
4) 연산 함수 만들기
(1) 필요한 데이터는...
function calculate(e) {
const value = e.target.value; //[1]
...
}
[1] e.target.value
로 버튼의 value값을 가져온다.
이 함수에서는 이 value이 무엇인지에 따라 다른 연산을 진행한다.
(2) = 버튼 클릭하면 연산을 한다.
function calculate(e) {
...
if (value === '=') {
const data = eval(formula.join('')) || ''; //[2-1][2-2]
formula = data.toString().split(''); //[3-1][3-2]
}
...
}
[2-1] formula.join('')
을 하여 배열을 하나의 문자로 만든다.
[2-2] 그 다음 eval()
을 사용하여 string 형태의 연산식을 계산한다.
[3-1] 계산된 값(data)을 toString()
로 문자로 변환하고, split('')
을 하여 배열로 만든다.
[3-2] 이렇게 생성된 값을 다시 formula
에 저장한다.
왜 연산한 값(
data
)을 string으로 만들고 다시 배열로 만들어서formula
에 넣을까?
그 이유는 계산된 결과값에 지우기 버튼(<-
)을 클릭했을 때에 하나씩 지워지게 하기 위함이다!
(3) C 버튼 클릭하면 초기화한다.
function calculate(e) {
...
else if (value === 'C') formula = []; //[4]
}
[4] c버튼을 누르면 초기화가 되어야 하므로 formula
을 빈 배열로 초기화한다.
(5) <- 버튼 클릭하면 가장 마지막 문자를 지운다.
function calculate(e) {
...
else if (value === '<-') formula.pop(); //[5]
}
[5] <-
클릭시 마지막에 작성한 문자를 삭제해야하므로, pop()을 사용한다.
(6) 값을 추가하고 나타내기
function calculate(e) {
...
else formula.push(value); //[6]
result.innerText = formula.join(''); //[7]
}
[6] 숫자나 연산을 클릭했을 경우에는 push
를 사용해 formula에 추가한다.
[7] formula.join('')
을 한 값을 result에 나타내기 위해 innerText
를 사용한다.
5. scss (2)
우리는 결과적으로 js를 이용해 버튼과 이벤트를 추가하였다!
그럼 이제 마지막으로 추가한 버튼에 디자인을 적용하고 끝내자 :)
- 버튼 디자인의 경우 간단하다.
- hover시 배경색과 글자색이 변하게 하고, (=) 버튼의 경우 다른 css를 적용하였다.
.num, .calc { position: relative; background: transparent; color: #fff; border: 1px solid rgba(0,0,0, 0.2); font-size: 1.2rem; font-weight: 500; cursor: pointer; transition: 0.25s; &:hover { background: #fff; color: #3d3d3d; } }
.label-11 { background: #6A82FB; &:hover { background: #FC5C7D; } }
출처
아래 출처로 이동하면 더 자세히 알 수 있다고? 꼭 가봐야 겠는데~ 🤔
'개발 기술 > css 애니메이션 (with js)' 카테고리의 다른 글
Gooey Effect 만들기 (with js) (0) | 2021.09.29 |
---|---|
carousel slider 만들기 (with js) (0) | 2021.09.27 |
(css, js) 햄버거 메뉴 애니메이션 만들기 (0) | 2021.09.26 |
hover시 색이 변하는 애니메이션(with. box-shadow로 네온 효과) (0) | 2021.09.25 |
이미지 로딩 애니메이션(feat. 저화질, skeleton loading) (0) | 2021.09.23 |
댓글