[TIL] typing 효과3

이진호·2023년 10월 14일
0

TIL

목록 보기
4/66
post-custom-banner

이전글

https://velog.io/@dygmm4288/TIL-typing-%ED%9A%A8%EA%B3%BC2

기존에 생각했던 방식이 아닌 다른 방식으로 typing 효과를 구현하는 방식에 대해서 알아보았다.

CSS를 이용

css의 animation typing function 중 steps를 이용하여 구현할 수 있었다.
steps(n,<jumpterm>)의 방식으로 사용하고, 주어진 n만큼 크기를 나눠서 뚝뚝 끊기는 듯한 애니메이션을 보여준다.

// html
<h1>Hello world</h1>

// css
h1 {
	animation: typing 3.5s steps(40,end)
    overflow:hidden;
	white-space: nowrap;
}
@keyframes typing {
	from {
    	width: 0;
    }
    to {
    	width: 100%;
    }
}

라이브러리 이용

찾아보니 typewriter.js라는 라이브러리가 있었다.
기본적인 사용방법은 아래와 같다.

const app = document.getElementById('app');
const typewriter = new Typewriter(app,{
	loop: true,
    delay: 75,
});

typewriter
	.pauseFor(2500)
    .typeString('A simple yet powerful native javascript')
    .pauseFor(300)
    .deleteChars(10)
    .typeString('<strong>JS</strong> plugin for a coll typewriter effect')
    .start()

new 생성자 키워들 사용하는 것으로 보아 class 형태로 이뤄진 것 같고 내부 상태 값들은 아래와 같다

state = {
    cursorAnimation: null,
    lastFrameTime: null,
    pauseUntil: null,
    eventQueue: [],
    eventLoop: null,
    eventLoopPaused: false,
    reverseCalledEvents: [],
    calledEvents: [],
    visibleNodes: [],
    initialOptions: null,
    elements: {
      container: null,
      wrapper: document.createElement('span'),
      cursor: document.createElement('span'),
    },
  }

init

처음 생성자 내부에는 container 엘리먼트와 옵션들을 저장하고 init()이라는 함수를 실행하는데 다음과 같다

init() {
    this.setupWrapperElement();
    this.addEventToQueue(EVENT_NAMES.CHANGE_CURSOR, { cursor: this.options.cursor }, true);
    this.addEventToQueue(EVENT_NAMES.REMOVE_ALL, null, true);

    if(window && !window.___TYPEWRITER_JS_STYLES_ADDED___ && !this.options.skipAddStyles) {
      addStyles(STYLES);
      window.___TYPEWRITER_JS_STYLES_ADDED___ = true;
    }

    if(this.options.autoStart === true && this.options.strings) {
      this.typeOutAllStrings().start();
		}
  }

setUpWrapperElement

setUpWrapperElement 함수는 다음과 같고, container내부에 을 넣는 함수이다.

setupWrapperElement = () => {
    if(!this.state.elements.container) {
      return
    }

    this.state.elements.wrapper.className = this.options.wrapperClassName;
    this.state.elements.cursor.className = this.options.cursorClassName;

    this.state.elements.cursor.innerHTML = this.options.cursor;
    this.state.elements.container.innerHTML = '';

    this.state.elements.container.appendChild(this.state.elements.wrapper);
    this.state.elements.container.appendChild(this.state.elements.cursor);
  }

start

start = () => {
    this.state.eventLoopPaused = false;
    this.runEventLoop();

    return this;
  }

아직까지 정확하게는 잘 몰라도 eventLoop, EventToQueue라는 곳에서 이벤트들을 쌓아놓고 한번에 실행하는 방식으로 진행하는 것 같다.

addEventToQueue

addEventToQueue = (eventName, eventArgs, prepend = false) => {
    return this.addEventToStateProperty(
      eventName,
      eventArgs,
      prepend,
      'eventQueue'
    );
  }

addEventToStartProperty() 함수는 state안에 이벤트 아이템을 만들어서 넣는 함수로 addEventToQueue는 eventQueue에 이벤트 아이템을 넣는다
이벤트 아이템의 구조는 이벤트 이름과 이벤트 인수들로 구성된다.

const eventItem = {
      eventName,
      eventArgs: eventArgs || {},
    };

runEventLoop

이벤트 큐에 넣은 내용들을 하나하나 꺼내면서 실행을 하는데 lastFrameTime이라는 변수를 이용해서 현재 frame이 동작해야하는지를 계산한다 그리고 이벤트큐에서 아이템을 하나 꺼내서 해당 아이템에 맞는 동작을 실행을 하는 방식인데 이때 requestAnimationFrame을 이용하여 다음번 runEventLoop를 호출한다.

profile
dygmm4288
post-custom-banner

0개의 댓글