[TIL] typing 효과

이진호·2023년 10월 11일
1

TIL

목록 보기
7/66
post-thumbnail
post-custom-banner

계획

글자가 하나하나 typing 되는 효과를 구현하기 위해서 3가지 과정을 생각을 해봤다.

  1. 앞으로 text가 채워진다
  2. 잠시 멈춘다
  3. 잠시 멈춘 뒤에 다시 text가 지워진다

단순 반복문을 사용하게되면 typing하는 효과처럼 보이지 않고 text가 한번에 나왔다가 줄었다가처럼 보일 것 같아서 interval 함수를 이용해서 약간의 간격을 주면서 하나씩 추가해야 typing 하는 효과가 주어질 것 같았다.

그래서 다음과 같이 작성을 했다.

const secondText = select('.second-text');

// text를 앞에서 부터 붙여 나간다.
function moveForward(text) {
    let textIndex = 0;
    return setInterval(() => {
        if (textIndex >= text.length) return;
        secondText.innerText += text[textIndex++];
    }, 200);
}
// 현재 정해진 text를 지워 나간다
function moveBack() {
    return setInterval(() => {
        if (secondText.innerText.length < 0) return;
        secondText.innerText = secondText.innerText.slice(0, -1);
    }, 200);
}
// 끝이 나면 다음 텍스트에 대해서 해당 기능들을 수행한다
function changeText() {
    const texts = ['개발자', '꿈나무', '칠칠맞조'];
    let curIndex = 0;
    // 시작 : toFlag == fales, 끝 플래그 : toFlag === true

    return () => {
        let backTimeout = null;
        let forwardTimeout = null;
        setInterval(() => {
            // 특정 초 안에 아래 동작을 완수한다.
            if (backTimeout) clearInterval(backTimeout);
            if (forwardTimeout) clearInterval(forwardTimeout);
            console.log('here');
            forwardTimeout = moveForward(texts[curIndex++]);
            curIndex %= texts.length;
            setTimeout(() => {
                backTimeout = moveBack();
            }, 1000);
        }, 2000);
    };
}

changeText()();


function select(selector) {
    return document.querySelector(selector);
}

처음에는 잘 작동하는 것처럼 보였지만 시간이 지난 후에 아래처럼 변하였다.

에러 원인

추측 에러 원인1 :

아마도 에러의 원인을 브라우저가 동작하면서 interval과 timeout 함수가 쌓이면서 그것들의 충돌로 인해서 제대로 출력이 안된다.
-> 처음에 좀 빡빡하게 typing 속도와 delay를 줬었는데 그 부분을 조금 더 변경을 해도 같은 문제가 발생하였다. 항상 켜놓으면 정상적으로 작동한다. 더 적은 시간이어도 다시보면 문제가 발생해있었다.

추측 에러 원인2 :

브라우저가 백그라운드에서 작동하면서 타이머 함수들을 조작하는게 아닌가 생각이 들어서 그 부분이 문제일 것 같다.
그래서 setTimeout과 setInterval에 대한 것을 조금 더 동기적으로 다루기 위해서 async, await을 도입을 하였다.

수정

현재까지는 같은 증상을 보이고 있지 않아서... 아마도 수정에 성공한 것 같은데 나중에 시간을 내서 다시 한번 보면 좋을 것 같다.

const secondText = select('.second-text');

function wait(time) {
  return new Promise((res) =>
    setTimeout(() => {
      res();
    }, time),
  );
}

function moveForward(speed, delay) {
  return (element) => async (text) => {
    let textIndex = 0;
    const size = text.length;
    while (textIndex < size) {
      element.innerText += text[textIndex++];
      await wait(speed);
    }
    await wait(delay);

    moveBack(speed)(element);
  };
}
function moveBack(speed) {
  return async (element) => {
    while (element.innerText) {
      element.innerText = element.innerText.slice(0, -1);
      await wait(speed);
    }
  };
}
const texts = ['개발자', '꿈나무', '칠칠맞조'];
let curIndex = 0;
const delay1000 = moveForward(100, 1000);
delay1000(secondText)(texts[curIndex++]);
curIndex %= texts.length;
setInterval(() => {
  delay1000(secondText)(texts[curIndex++]);
  curIndex %= texts.length;
}, 3000);

function select(selector) {
  return document.querySelector(selector);
}
profile
dygmm4288
post-custom-banner

0개의 댓글