본문 바로가기

UI 디자인 애니메이션 연구소

HTML/CSS/JS 를 이용한 스트리밍효과 토글 UI 만들기

반응형

이전 애니메이션

 

CSS, JS를 이용한 웅장한 N-S(자석) 애니메이션 제작

[이전 애니메이션] 3D 카드 회전 애니메이션 HTML,CSS 를 사용한 3D 카드 회전 애니메이션 만들기미리보기이번에 만들어볼 애니메이션은 원의 중심축을 기준으로 카드가 회전하는 애니메이션을 3D

duklook.tistory.com

 

미리보기

이번 과정을 따라오시면 아래와 같이 스트리밍 되는 듯한 토글 애니메이션을 구현하실 수 있게 됩니다.

 

HTML

마크업은 크게 추가할 것은 없습니다. 아래와 같이 두 가지 요소만 만들어주면 됩니다.  나중에 box 태그 내부에 스트리밍 효과의 span 태그를 추가할 예정입니다. 

<div class="container">
  <div class="box">
  </div>
</div>

 

CSS

CSS 기본 여백 제거

우선 브라우저에 기본 적용된 여백을 제거하고, 콘텐츠의 길이와 높이를 계산 시 margin 과 padding 을 포함하도록 box-sizing 을 border-box 로 지정해주고, 여백 제거를 위해 margin 과 padding을 모두 0으로 설정해줍니다.

* {
  margin:0;
  padding:0;
  box-sizing:border-box;
}

 

 body 태그 설정

배경은 약간 밝고 어두운 계열의 #333 을 지정해주고, body 태그 내부의 요소가 가로-세로 모두 중앙정렬이 될 수 있도록 display 속성을 flex 로 지정 후, align-items 와 jsutify-content 속성 모두 center 로 지정 해줍니다. 

body {
  background:#333;
  width:100%;
  height:100vh;
  display:flex;
  align-items:center;
  justify-content:center;
}

 

.box 꾸미기

position을 relative 로 설정하여, 향후 .box 태그 내부에 추가할 자식요소의 position을 absolute 로 지정하여도 좌표 기준이 box 태그가 되도록 해줍니다.  또한 자식요소가 랜덤한 위치에 배치될 때 부모 요소 바깥으로 나가도 보이지 않도록 overflow를 hidden 으로 지정합니다. 그 외에는 모양을 만들어주기 위한 속성이므로 원하는 모양으로 꾸미셔도 상관 없습니다.

  .box {
    position:relative;
    overflow:hidden;
    border-radius:20px;
    width:100px;
    height:45px;
    border:none;
    box-shadow:0 0 100px white;
  }

 

 

그 코드를 그대로 적용한다면,  아래와 같은 형태가 만들어집니다.

 

 

line 꾸미기

스트리밍 처럼 움직여줄 line 을 꾸며줍니다. 이는 자바스크립트에서 동적으로 생성되어 DOM 에 삽입될 span 태그를 나타냅니다. box 태그 내부에서 랜덤한 Y 축에 배치될 것이므로 position을 absolute 로 지정하고, width의 경우에는 앞서 .box 박스(상위 부모요소)의 width/2-1  이 되도록 설정해줍니다. height의 경우에는 적절한 값을 넣어주기만 하면 됩니다. 이는 완성후에 나타나는 모양에 따라서 조절합시다.

  .line {
    box-shadow:0 4px 0px 0 white;
    transition: 0.5s left ease;
    width:49px;
    height:2px;
    border-radius:5%;
    background:white;
    position:absolute;
    left:0;
    top:0;
  }

 

나머지는 애니메이션 효과를 위한 부분과 위치좌표를 부모요소의 (0,0) 좌표로 고정시키기 위한 left 와 top 속성을 지정하는 등 부수적인 것이므로 설명을 넘어가도록 하겠습니다.

 

.active 속성 추가 시 line의 이동 거리 설정

CSS 설정 마지막입니다. 향후 박스를 사용자가 클릭하면 해당 .box 는 새로운 클래스인 .active를 받게 됩니다. 즉, 활성화 시 line의 이동 거리를 설정해주는데, 이 또한 부모요소의 넓이/2-1 이 되도록 설정해주면 됩니다. 참고로 일일이 계산하기 귀찮다고 느끼신다면, calc(var(--parent-wdith)/2px-1)) 와 같이 CSS의 계산기 함수와 변수를 사용해도 동일한 결과를 얻으 실 수 있습니다.

  .active.box {
    .line {
      left:49px;
    }
  }

 

JS

box 태그 가져오기

우선 box 태그를 가져와서 box 변수에 할당해 줍니다.

const box = document.querySelector('.box')

 

box 에 이벤트 리스너 등록 및 handleToggle 함수 구현하기

그 후 box 태그에 click 이벤트를 등록해주고, 이벤트 콜백으로 실행할 handleToggle 함수를 구현해 줍니다.

box.addEventListener('click',handleToggle)

function handleToggle(e){
  const target = e.currentTarget
  target.classList.toggle('active')
}

 

handleToggle 함수의 경우, box 태그의 classList 객체에 .activle 클래스를 토글(toggle) 하여 추가 및 제거를 손쉽게 할 수 있도록 해주는 함수입니다.

 

createRandomPositionElement | 요소 생성 함수 구현하기

이번에는 매개변수로 전달받은 요소를 갯수 만큼 생성하여 반환하는 함수를 구현 합니다. 이 때 요소를 생성함과 동시에 각 요소에 style 속성 중 transform:translate 를 적용하여 순차적으로 요소가 상단에서 하단으로 그려지도록 해줍니다. 또한, transition 적용 시 딜레이를 랜덤하게 설정하여 스트리밍 효과가 나타나도록 만들어줍니다. 해당 로직들이 애니메이션의 핵심이 되겠습니다.

/** 요소 생성*/
function createRandomPositionElement(count=1, elName='span', className='line'){
  const elements = []
  for(let i=0; i<count; i++) {
    const position= i
    const el = document.createElement(elName)
    el.classList.add(className)
    
    el.style.transform=`translate(0,${position}px)` // Y 축 위치에 요소를 차례대로 배치합니다.
    el.style.transitionDelay=`${Math.random()*0.5}s`// 생성된 각 요소에 transition 시 지연시간을 랜덤하게 추가해줍니다.
    elements.push(el)
  }
  return elements
}

 

 

renderElement | 생성 요소를 DOM 에 렌더링하는 함수 구현

마지막으로 앞서 create 함수를 통해 생성된 요소를 실제 DOM 에 그려주는 함수를 구현합니다.  매개변수로 요소를 추가할 부모요소인 target 과 각 요소들을 의미하는 elements 를 받습니다. 그리고 해당 요소들은 배열 형태로 받기 때문에 target.append(...elements) 와 같이 전개연산자를 사용하여 [span, span] 형식을 span, span 형식으로 만들어주고 이를 target 요소의 자식 요소로 모두 추가하도록 해줍니다. 이렇게 되면 굳이 element의 수 만큼 반복문을 돌 필요 없이 성능을 최적화할 수 있습니다.

/** DOM 요소 렌더링 */
function renderElement(target, elements){
  target.append(...elements)
}

 

구현한 함수 호출하기

앞서 요소를 만들고, 요소를 DOM 에 반영하는 함수를 호출해주면 끝입니다.

const elements =  createRandomPositionElement(40, 'span','line')
renderElement(box, elements )

 

 

구현결과

이상 애니메이션 구현을 마치도록 하겠습니다. 고생 많으셨습니다.

 

See the Pen 샤샤샥 토글 by youngwan2 (@youngwan2) on CodePen.

반응형