0탄 보러가기
결과 미리보기
이번 포스팅을 잘 따라오시면 아래와 같은 애니메이션을 구현할 수 있게 됩니다. 영상은 약간 짤려서 나왔는데 원래 시작 화면은 하얗게 가득찬 상태에서 시작됩니다.
HTML
<section>
<h2> 이것이 프론트엔드다</h2>
<div class="banner">
<div class="blocks"></div>
</div>
</section>
우선 HTML 마크업을 아래와 같이 작성해줍니다. h2 는 헤딩태그로서 앞서 미리보기의 화면 중앙에 위치한 텍스트가 됩니다. banner 클래스가 부여된 div 태그는 화면의 뒷단에 위치한 검은 배경이 되고, blocks 클래스가 부여된 div 태그는 각각의 하얀 박스가 되어줄 해당 애니메이션의 주요 포인트에 해당하는 친구입니다.
CSS
CSS Reset
@font-face {
font-family: 'Giants-Inline';
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2307-1@1.1/Giants-Inline.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
* {
margin:0;
padding:0;
box-sizing:border-box;
}
우선 화면의 margin 과 padding 을 모두 0 으로 지정하여 공백이 없도록 만들어 줍니다. 그 후 box-sizing 속성을 border-box 로 설정해서 텍스트가 차지하는 콘텐츠 영역뿐만 아니라 padding 괴 margin 과 같은 여백을 결정하는 속성 또한 요소의 넓이와 높이를 계산하는데 사용하도록 해줍니다. box-sizing 의 경우 굳이 설정할 필요는 없지만, 보다 자연스러운 레이아웃을 위해서 설정해둡시다.
section 태그 와 h2 태그 속성 지정
section {
position:relative;
color:white;
width:100%;
height:100vh;
text-align:center;
line-height:100vh;
h2 {
font-family: 'Giants-Inline';
font-size:5em;
font-weight:bold;
font-style:italic;
}
}
그 다음에는 section 태그에 속성을 지정해줍니다. 해당 영역은 h2 라는 헤딩 태그를 감싸는 컨테이너 역할을 해주며, h2 태그의 텍스트를 중앙정렬하기 위해서 width를 100%으로 설정하여 전체 넓이를 뷰포트에 꽉 채워주도록 설정 해줍니다.
그 후 중앙정렬 하기위해 line-height 를 100vh 로 지정하고, text-aligin 을 center 로 지정해줍니다. 그리고 position을 relative 로 지정하여 그 안의 자식요소인 .banner의 position 속성이 absolute 가 되었을 때 기준점이 되도록 해줍니다.
참고로 line-height 을 100vh 로 지정하면 수직 중앙정렬이 되는 이유는 line-height 는 설정된 텍스트의 높이를 벗어나는 경우 중앙에 정렬이 되는 특징이 있기 때문입니다. 단 텍스트가 한 줄로 있는 경우에만 가능하며, 두 줄로 나뉘는 경우에는 레이아웃을 크게 벗어나므로 font-size 등을 적절하게 조절해서 뷰포트에 맞도록 해줘야 합니다.
만일 그것이 싫으면 justify-content 를 center 로 지정하고, align-items 또한 center 로 지정하면 동일한 효과를 얻으실 수 있습니다.
banner 클래스가 적용된 div 태그 속성 지정
.banner{
z-index:-1;
background:black;
position:absolute;
left:0;
top:0;
width:100%;
height:100%;
overflow:hidden;
display:flex;
flex-wrap:wrap;
}
그 다음에는 뒷 배경이 되어줄 banner 의 css 속성을 지정해줍니다. z-index 의 경우 레이어의 우선순위를 지정해주는 속성인데 -1 을 지정하는 경우 기본 우선순위가 0인 요소의 제일 뒤로 위치하게 됩니다. position 의 경우 absolute 로 지정하여 현재 문서객체의 흐름에서 벗어나게 설정해줍니다.
그 후 left, top 을 0 으로 지정해서 좌측 최상단으로 요소를 고정시킨 후 width 와 height 를 100% 으로 지정하여 section 태그의 넓이만큼 영역을 채우도록 해줍니다.
overflow 의 경우 hidden 으로 지정해두는데, 이는 향후 .blocks 클래스가 부여된 div 태그를 무한대로 찍어낼 때 부모 영역을 벗어나면서 흔히 저희가 사용하고 있는 스크롤바가 생기는 것을 방지하기 위해서입니다.
flex-wrap 의 경우 flex 레이아웃에 의해 정렬된 자식 요소가 부모 요소의 넓이를 벗어나는 경우 자동으로 개행해주도록 하기 위해 wrap 을 설정해줍니다.
.blocks 클래스가 부여된 div 태그 속성 지정
.blocks{
position:relative;
width:5vw;
height:5vw;
background:white;
animation:1s 1 drop ease-in-out forwards;
}
그 다음에는 앞서 banner 요소가 차지하는 영역 위에 덮어씌워지는 하얀색 박스를 만드는 작업을 해야 합니다. width 와 height를 5vw 으로 설정하게 되면, 뷰포트가 전체 100% 라고 했을 때 그중에서 5%만 차지하게 되므로 작은 정사각형의 형태가 만들어집니다. 거기에 background를 white 로 지정해두면 하얀색 정사각형이 됩니다.
@keyframes drop {
0% {
opacity:0;
scale:0;
transform:translateY(1000px);
}
50% {
opacity:1;
}
100% {
transform:translate(0px);
opacity:0;
}
}
애니메이션의 경우에는 위와 같이 설정해두면, 초기에 렌더링 시 생성된 div 요소가 아래로 바운딩 된 후 위로 다시 올라오는 애니메이션이 렌더링됩니다. 즉, 투명 -> 하단으로 1000px 이동 -> 불투명 하얀 정사각형 -> 상단의 원래 위치로 이동 -> 투명 이라는 순서로 애니메이션이 동작합니다.
자바스크립트 작성
대망의 자바스크립트 코드를 작성해보겠습니다.
banner 태그 가져오기
const banner = document.querySelector('.banner');
우선은 .banner 클래스가 부여된 div 태그를 document 객체의 메소드인 querySelector 를 사용해 가져옵니다. 이 때 인자로 전달된 .banner 와 일치하는 class 속성을 지닌 요소를 가져오게 됩니다.
Block 클래스 생성하기
class Block {
blocks=[];
setBlocks(n){
for(let i=0; i<n; i++) {
let block = document.createElement('div')
block.classList.add('blocks')
this.blocks.push(block)
}
}
getBlocks(){
return this.blocks
}
}
const cBlock = new Block();
무수히 많은 div 태그를 동적으로 찍어내기 위해 block class 를 구현해줍니다. 여기서 주요한 포인트는 setter 와 getter 를 구분하여 메소드를 구현하는 것 입니다.
setter 함수 구현
setBlocks(n){
for(let i=0; i<n; i++) {
let block = document.createElement('div')
block.classList.add('blocks')
this.blocks.push(block)
}
}
우선 setBlocks 메소드의 경우에는 매개변수로 n 을 받습니다. n 는 생성할 block 요소의 갯수를 의미하는데, 내부에서는 해당 n 개 만큼 for 반복문을 통해 div 태그를 생성해줍니다. 이 떄 document 객체의 createElemet 메소드를 사용하면 인자로 전달된 태그명으로 새로운 element 를 만들어 줍니다.
그 후 생성된 block 태그에 classList.add('blocks') 라고 입력해주면 해당 태그의 class 속성의 값으로 blocks 를 지정해줍니다. 그 다음에는 this.blocks.push(block) 메소드를 실행하여 n 개 만큼 생성된 blocks 태그를 배열 형태로 모아둡니다.
getter 함수 구현
getBlocks(){
return this.blocks
}
getter 함수로서 getBlocks 함수는 그저 앞서 생성된 blocks 배열을 반환해주기만 하면 됩니다.
block 인스턴스 생성 및 blocks 요소 찍어내기
앞서 생성한 클래스와 메소드를 사용해서 .blocks 클래스가 부여된 div 태그를 원하는 만큼 만들어줍니다.
const cBlock = new Block();
cBlock.setBlocks(400);
const blocks = cBlock.getBlocks();
for(let i=0; i<blocks.length; i++){
banner.append(blocks[i])
blocks[i].style.animationDelay=`${Math.random()*i/30}s`
}
우선 new 키워드를 사용해서 Blocks 클래스의 인스턴스를 생성한 후 cBlock 변수에 담아줍니다.
그 후 cBlock 인스턴스가 참조하고 있는 Block 클래스 내부에 정의된 setBlocks 메소드의 인자로 400을 전달하여 총 400개의 div 요소를 생성해줍니다.
그 다음 cBlock.getBlock() 메소드를 호출해서 앞서 생성했던 400개의 요소를 blocks 변수에 담아줍니다. 여기서 blocks 벼 변수는 [<div class='.blocks'></div>,....] 형태가 됩니다.
마지막으로 해당 blocks 배열을 for 문을 사용해서 그 길이 만큼 반복을 돌려주고, .blocks 요소의 부모 요소인 banner 요소의 자식요소로 추가해주며, 이 때 blocks[i].style.animationDelay 에 접근하여 애니메이션 실행에 지연시간을 추가해줍니다. 추가되는 값은 Math.random 메소드를 사용해서 각 요소 마다 랜덤된 시간 마다 애니메이션이 동작하도록 하는데, *i/30 와 같이 적절한 딜레이 타이밍을 조절하여 자연스럽게 애니메이션이 동작하도록 설정해줍니다.
완성!
여기까지 무사히 따라오셨다면, 결과적으로 아래와 같은 애니메이션을 보실 수 있게 됩니다. 고생하셨습니다.
See the Pen Untitled by youngwan2 (@youngwan2) on CodePen.
2탄 보러가기
'UI 디자인 애니메이션 연구소' 카테고리의 다른 글
바닐라 JS/HTML/CSS 로 재밌는 애니메이션 효과 만들기 (3탄) (0) | 2024.05.05 |
---|---|
HTML/CSS 만으로 재밌는 마우스 호버 애니메이션 구현하기(var 함수 활용)(2탄) (0) | 2024.05.04 |
바닐라 JS/HTML/CSS 로 재미있는 애니메이션 구현하기(0탄) (0) | 2024.04.09 |
gsap flip 을 이용한 인터렉티브 카드 스위칭 (0) | 2024.04.06 |
무한슬라이드 (0) | 2024.03.31 |