본문 바로가기
JavaScript

[javascript] setTimeout()사용하여 타이핑 효과 주기

by teamnova 2023. 9. 1.

안녕하세요! 오늘은 Javascript와 css를 사용하여 화면에 타이핑 효과를 주어 아래 처럼 보여줄 수 있도록 해보겠습니다.

이전에 작성했던 @keyframe에 대한 개념(https://stickode.tistory.com/814) 과 함께 setTimeout() 메서드를 사용할 예정입니다. 

 

1.setTimeout()

setTimeout() : 일정 시간이 지난 후에 함수를 실행하는 전역 호출 스케줄링 메서드.

1.(문법) 
let timerId = setTimeout ( func | code ,[delay],[arg1],[arg2], ...);

2. (파라미터 설명)

func | code :

실행하고자 하는 코드로, 함수 또는 문자열 형태입니다. 대개는 이 자리에 함수가 들어갑니다. 하위 호환성을 위해 문자열도 받을 수 있게 해놓았지만 추천하진 않습니다.( eval() 이 보안 취약점인 것과 이유가 동일합니다.)

delay :

실행 전 대기 시간으로, 단위는 밀리초(millisecond, 1000밀리초 = 1초)이며 기본값은 0입니다.

[arg1, arg2…] :

함수에 전달할 인수들로, IE9 이하에선 지원하지 않습니다.

3. *주의사항*

setTimeout()에 함수를 파라미터로 넣을 때에 함수를 실행시키지않습니다. => '()'를 붙이지 않습니다.

setTimeout에 함수를 넘길 때, 함수 뒤에 () 을 붙이는 실수를 하곤 합니다.

잘못된 코드예: setTimeout(sayHi(), 1000);

setTimeout은 함수의 참조 값을 받도록 정의되어 있는데 sayHi()를 인수로 전달하면 함수 실행 결과가 전달되어 버립니다. 그런데 sayHi()엔 반환문이 없으므로 호출 결과가 undefined로 나옵니다. 따라서 setTimeout은 스케줄링할 대상을 찾지 못해 코드가 동작하지않는 오류가 발생합니다.

4. 스케줄링 취소하기.
아래 예제에서는 쓰이지않았지만 setTimeout으로 설정한 스케줄링을 취소하는 방법도 있습니다.

//setTimeout으로 스케줄링 설정.
let timerId = setTimeout( ... ) ;
//스케줄링 취소하는 부분
clearTimeout(timerId);

 

 

타자 효과 주기 결과

 

1. HTML 코드입니다.

 

<!-- 컨테이너 요소를 나타내는 div 태그. -->
<div class="container">
  <!-- 단락(p) 요소를 나타내는 태그. -->
  <p>
    <!-- "키보드 치는" 텍스트를 나타내는 span 요소. -->
    키보드 치는<span class="typed-text">
      <!-- 타이핑 중인 텍스트를 나타내는 span 요소 (초기에는 빈 텍스트로 표시됨). -->
    </span>
    <!-- 커서를 나타내는 span 요소 (가운데 정렬을 위해 &nbsp; 공백 문자를 사용). -->
    <span class="cursor">&nbsp;</span>
  </p>
</div>

 

2. CSS 코드입니다.

 

/* 구글 폰트 임포트 */
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300&display=swap');

/* 모든 요소에 대한 초기화 스타일 설정. */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* body 요소의 스타일 설정: 폰트, 배경색, 텍스트 색상 등. */
body {
  font-family: 'Noto Sans KR', sans-serif;
 /* import한 폰트 사용. */
  background-color: #2a9d8f; /* 배경색: 청록*/
  color: #eee; /* 텍스트 색상: 밝은 회색(#eee). */
}

/* 컨테이너 스타일: 가운데 정렬, 높이, display 속성 등. */
.container {
  height: 100vh; /* 컨테이너의 높이를 화면의 전체 높이로 설정. */
  display: flex; /* 자식 요소들을 가로 방향으로 나열. */
  justify-content: center; /* 가로 방향으로 가운데 정렬. */
  align-items: center; /* 세로 방향으로 가운데 정렬. */
}

/* 단락 요소 스타일: 폰트 크기, 여백, 굵기, 글자 간격, 가운데 정렬 등. */
.container p {
  font-size: 3rem; /* 폰트 크기: 3rem. */
  padding: 0.5rem; /* 여백(padding) 설정. */
  font-weight: bold; /* 굵은 폰트로 설정. */
  letter-spacing: 0.1rem; /* 글자 간격: 0.1rem. */
  text-align: center; /* 가운데 정렬. */
  overflow: hidden; /* 내용이 넘치면 숨김. */
}

/* 타이핑된 텍스트 스타일: 기본 폰트, 주황색 색상. */
.container p span.typed-text {
  color: #e9c46a; /* 텍스트 색상: 노란색. */
}

/* 커서 스타일*/
.container p span.cursor {
  display: inline-block; /* 인라인 블록 요소로 표시. */
  background-color: #fff;
  margin-left: 0.1rem; /* 왼쪽 여백: 0.1rem. */
  width: 3px; /* 가로 크기: 3px. */
  animation: blink 1s infinite; /* 1초 간격으로 깜빡임 애니메이션 반복. */
}

/* 타이핑 중인 커서 스타일: 깜빡임 애니메이션 제거. */
.container p span.cursor.typing {
  animation: none; /* 깜빡임 애니메이션 제거. */
}

/* 깜빡임 애니메이션 정의. */
@keyframes blink {
  0%  { background-color: #ccc; } /* 시작 시 배경색은 회색(#ccc). */
  49% { background-color: #ccc; } /* 49% 진행 중, 배경색은 계속 회색(#ccc). */
  50% { background-color: transparent; } /* 50% 진행 중, 배경색은 투명(transparent). */
  99% { background-color: transparent; } /* 99% 진행 중, 배경색은 계속 투명(transparent). */
  100%  { background-color: #ccc; } /* 종료 시 배경색은 다시 회색(#ccc). */
}

 

3. JS코드입니다.

 

// 텍스트를 출력할 span 요소와 커서 요소를 가져옵니다.
const typedTextSpan = document.querySelector(".typed-text");
const cursorSpan = document.querySelector(".cursor");

// 출력할 텍스트 배열과 딜레이 설정들을 정의합니다.
const textArray = ["예제가 필요하셨나요?", " 화면을 보시죠.", " 효과 주기입니다."];
const typingDelay = 200; // 타이핑 딜레이 (한 글자씩 출력하는 딜레이)
const erasingDelay = 100; // 지우기 딜레이 (한 글자씩 지우는 딜레이)
const newTextDelay = 2000; // 현재 텍스트와 다음 텍스트 사이의 딜레이 (타이핑이 끝나고 다음 텍스트가 나타나는 딜레이)

let textArrayIndex = 0; // 현재 텍스트 배열의 인덱스
let charIndex = 0; // 현재 타이핑 또는 지우기 중인 텍스트의 인덱스

// 타이핑 효과 함수
function type() {
  // 현재 타이핑 중인 텍스트의 인덱스가 해당 텍스트의 길이보다 작은 경우
  if (charIndex < textArray[textArrayIndex].length) {
    // 커서가 타이핑 중인 상태가 아니면 "typing" 클래스를 추가하여 깜빡임 효과를 적용합니다.
    if (!cursorSpan.classList.contains("typing")) cursorSpan.classList.add("typing");
    
    // 타이핑 중인 텍스트를 한 글자씩 출력합니다.
    typedTextSpan.textContent += textArray[textArrayIndex][charIndex];
    charIndex++; // 다음 글자 인덱스로 이동
    setTimeout(type, typingDelay); // 일정 딜레이 후 다음 글자 타이핑
  } else {
    // 타이핑이 완료된 경우 "typing" 클래스를 제거하여 커서 깜빡임 효과를 중지합니다.
    cursorSpan.classList.remove("typing");
    setTimeout(erase, newTextDelay); // newTextDelay 시간 후 지우기 효과 시작
  }
}

// 지우기 효과 함수
function erase() {
  // 현재 지우기 중인 텍스트의 인덱스가 0보다 큰 경우
  if (charIndex > 0) {
    // 커서가 타이핑 중인 상태가 아니면 "typing" 클래스를 추가하여 깜빡임 효과를 적용합니다.
    if (!cursorSpan.classList.contains("typing")) cursorSpan.classList.add("typing");
    
    // 타이핑 중인 텍스트를 한 글자씩 지웁니다.
    typedTextSpan.textContent = textArray[textArrayIndex].substring(0, charIndex - 1);
    charIndex--; // 이전 글자 인덱스로 이동
    setTimeout(erase, erasingDelay); // 일정 딜레이 후 다음 글자 지우기
  } else {
    // 지우기가 완료된 경우 "typing" 클래스를 제거하여 커서 깜빡임 효과를 중지합니다.
    cursorSpan.classList.remove("typing");
    
    // 다음 텍스트 배열의 인덱스로 이동하고, 배열 범위를 벗어나면 다시 처음으로 돌아갑니다.
    textArrayIndex = (textArrayIndex + 1) % textArray.length;
    
    // 일정 딜레이 후 다음 타이핑 효과를 시작합니다.
    setTimeout(type, typingDelay + 1100);
  }
}

// 페이지가 로드되면 (DOMContentLoaded 이벤트 발생 시), 텍스트 타이핑 효과를 시작합니다.
document.addEventListener("DOMContentLoaded", function () {
  setTimeout(type, newTextDelay + 250);
});

 

+ 자세한 내용은 아래 글 참고부탁드립니다. 

 

https://developer.mozilla.org/ko/docs/Web/API/setTimeout

 

setTimeout() - Web API | MDN

전역 setTimeout() 메서드는 만료된 후 함수나 지정한 코드 조각을 실행하는 타이머를 설정합니다.

developer.mozilla.org

https://ko.javascript.info/settimeout-setinterval

 

setTimeout과 setInterval을 이용한 호출 스케줄링

 

ko.javascript.info