연습문제

- 다음과 같은 HTML 문서와 JavaScript 프로그램을 작성하라.

  • 글자가 차례대로 타이핑되는 것 처럼 보이는 JavaScript 프로그램 작성
  • 타이핑이 다 되면 글자 밑에 있는 커서가 깜박이는 기능 추가

 

풀이

1. #effect 요소의 내부 문자를 한 글자씩 잘라낸다.

    1.A. String 객체의 charAt 메서드를 이용

    1.B. String 객체의 split 메서드를 이용

2. #effect 요소의 내부 문자를 제거한다.

3. 한 글자씩 자라놓은 문자들을 #effect 요소에 추가한다.

    3.A. 모든 문자들을 보이지 않게 추가해놓고 한 글자씩 보이게 한다.

    3.B. 순차적으로 글자를 하나씩 #effect 요소에 추가한다.

          → A가 더 편한 방법이므로 A로 JavaScript 프로그램을 작성하도록 한다.

4. #effect 요소에 커서(caret)를 표현할 요소를 추가

5. 지정한 시간이 지난 다음 문자들이 순차적으로 나오도록 지연을 설정하고, 글자가 보이게 한다.

6. 글자가 모두 화면에 표시된 다음에 커스(caret)이 깜빡이도록 설정

 

 

 

● HTML

<body>
    <div id="effect">
        Have a good time!
    </div>
</body>

 

 

● CSS

<style>
    #effect {
        position: absolute;
        top: 50%; left: 50%;
        transform: translate(-50%, -50%);

        /* 너비를 따로 설정하는 이유는? 너비를 설정하지 않으면
            가운데에 배치되어 있으므로 글자가 나올 때 가운데서부터 나오게 된다.
            너비를 설정하게 되면 왼쪽부터 차례대로 나오게 된다. */
        width: 950px;

        font-size: 7em;
        font-weight: 900;
        letter-spacing: -4px;
        white-space: nowrap;
    }
</style>

 

 

● script

<script src="https://code.jquery.com/jquery.min.js"></script>
<script>
    $(function () {
        // 프로그램에서 참조하는 요소를 미리 탐색
        var $effect = $("#effect");

        // 글자들이 입력되는 간격 → 표준 입력값은 이렇게 변수에 저장하는 것이 좋다.
        var typingDelay = 200;

        // 커서(caret)가 깜빡이는 간격
        var caretDelay = 600;
        
        // 1. #effect 요소의 내부 문자를 한 글자씩 잘라낸다.
        //    → html() 메서드는 white-space를 포함한 html 내부문자를 불러들인다.
        //    → white-space는 공백(space), 개행, 탭을 포함하는데 이러한 white-space를 제외한
        //    → 내부문자를 불러들이려면 trim() 메서드를 이용한다.     
        var effectText = $effect.html().trim();

        // 1.A. String 객체의 charAt 메서드를 이용
        // for (var i = 0; i < effectText.length; i++)
        //    console.log("effectText[i] = " + effectText.charAt(i));

        // 1.B. String 객체의 split 메서드를 이용
        //       → 첫번째 인자가 어떤 글자를 기준으로 쪼갤 것인지(생략 가능, 만약 생략한다면 글자 전체를 반환),
        //       → 빈문자열을 인자로 삼는다면 쪼개 놓은 문자열을 담은 배열이 반환값이 된다.
        var letters = effectText.split("");
        
        // 2. #effect 요소의 내부 문자를 제거한다.
        $effect.html("");

        // 3. 한 글자씩 자라놓은 문자들을 #effect 요소에 추가한다.
        // 3.A. 모든 문자들을 보이지 않게 추가해놓고 한 글자씩 보이게 한다.
        // 3.B. 순차적으로 글자를 하나씩 #effect 요소에 추가한다.
        //      → A가 더 편한 방법이므로 A로 JavaScript 프로그램을 작성하도록 한다.
        
        // 3.A. 모든 문자들을 보이지 않게 추가해놓고 한 글자씩 보이게 한다.
        for (var i = 0; i < letters.length; i++) {
            // 빈칸(space)의 경우 HTML 문서에서 제대로 표현되지 않으므로 HTML 엔티티를 이용해서 표현
            letters[i] = (letters[i] == " ") ? "&nbsp;" : letters[i]
            // if 조건문보다 ?: 조건문을 쓰는 것이 처리 속도가 훨씬 빠르다.

            // 3.A.1. 새로운 span 요소를 생성해서 각 문자들을 내부 문자로 설정하고
            //        보이지 않게 한 다음 #effect 요소에 추가
            $("<span></span>").html(letters[i]).hide().appendTo($effect);
        }

        // 4. #effect 요소에 커서(caret)를 표현할 요소를 추가
        var $caret = $("<span></span>").addClass("caret").css({
            display: "inline-block", height: "1em", width: "0.4em",
            // borderBottom: "20px solid #555", transform: "translateY(30px)",
            borderBottom: "20px solid #555", marginBottom: -30,
        }).appendTo($effect);

        // 5. 지정한 시간이 지난 다음 문자들이 순차적으로 나오도록 지연을 설정하고, 글자가 보이게 한다.
        window.setTimeout(function () {
            $effect.children().each(function (index) {
                $(this).delay(index * typingDelay).show(10);
            })
        }, 2000);
        
        // 6. 글자가 모두 화면에 표시된 다음에 커스(caret)이 깜빡이도록 설정
        //    → 글자가 모두 화면에 표시되는데 걸리는 시간 = (글자의 개수) * (표시되는 간격)
        //      = (letters.length + typingDelay)
        window.setTimeout(function () {
            window.setInterval(function () {
                $caret.hide().delay(caretDelay / 2).show(10);
                // show 메서드는 시간을 주지 않으면 애니메이션 큐에 쌓이지 않고 바로 실행되므로
                // 짧게라도 시간을 인자로 주어야 한다.
            }, caretDelay);
        }, letters.length * typingDelay);
        
    }); // document.onready
</script>

 


 

 

연습문제

- 다음과 같은 HTML 문서와 JavaScript 프로그램을 작성하라.

  • 가운데 부터 한글자씩 나타나면서 커지는 JavaScript 프로그램 작성

 

 

풀이

1. #effect 요소의 너비 설정

2. #effect 요소의 내부 문자를 읽어놓은 다음 내부 문자를 제거한다.

3. #effect 요소의 내부 문자를 한글자씩 잘라내서 배열에 저장

4. 새로운 span 요소를 생성해 잘라놓은 글자를 내부 문자로 설정한 후

5. #effect 요소의 각 span 요소들의 위치(x축 값)를 저장해둔다.

6. span 요소들을 #effect 요소의 영역을 기준으로 가운데에 배치

7. span 요소들을 순차적으로 본래 위치로 배치

 

 

 

● HTML

<body>
    <div id="effect">EFFECT</div>
</body>

 

 

● CSS

<style>
    body  {background-color: #222; }

    #effect {
        position: absolute;
        top: 50%; left: 50%;
        transform: translate(-50%, -50%);

        color: white;
        font-size: 10em;
        font-weight: 900;
        letter-spacing: -1px;
        white-space: nowrap;
    }
</style>

 

 

● script

<script src="https://code.jquery.com/jquery.min.js"></script>
<script>
    $(function () {

        //---------------------------------------------------------------------------------
        // 프로그램에서 참조하는 요소를 미리 탐색
        var $effect = $("#effect");

        // 1. #effect 요소의 너비 설정
        $effect.css("width", $effect.outerWidth());

        // 2. #effect 요소의 내부 문자를 읽어놓은 다음 내부 문자를 제거한다.
        var text = $effect.html().trim();
        $effect.html("");

        // 3. #effect 요소의 내부 문자를 한글자씩 잘라내서 배열에 저장
        var letters = text.split("");

        console.log("letters = " + letters);

        // 4. 새로운 span 요소를 생성해 잘라놓은 글자를 내부 문자로 설정한 후
        //    #effect 요소에 추가
        // $.each() 메서드 → 이때 $ 기호는 jQuery를 가리키고 첫번째 인자는 배열, 두번째 인자는 함수
        $.each(letters, function (index, item) {
            $("<span></span>").html(item).appendTo($effect);
        });

        // 5. #effect 요소의 각 span 요소들의 위치(x축 값)를 저장해둔다.
        $effect.children().each(function () {

            // offset() 메서드는 본래 문서의 좌상단점을 기준으로 좌표를 구한다.
            // 여기서는 문서의 좌상단점이 아닌 #effect 영역의 좌상단점을 기준으로 구해야 한다.
            // #effect 요소의 영역을 기준으로 한 span 요소의 좌표
            // var left = $(this).offset().left - $effect.offset().left;

            // offsetParent() 메서드 → 문서가 아닌 요소의 조상 요소 중에 position이 static이 아닌 요소(위치 지정 요소)를 찾는 메서드
            // offsetPosition() 메서드 → 조상 요소 중 가장 가까운 위치 지정 요소를 기준으로 한 좌표를 구하는 메서드
            var left = $(this).position().left;

            $(this).data("left", left);
            // $(this).attr("data-left", $(this).offset().left);
        });

            // 6. span 요소들을 #effect 요소의 영역을 기준으로 가운데에 배치
            $effect.children().css({
                position: "absolute",
                top: "50%", left: "50%",
                transform: "translateY(-50%)",
                fontSize: "0.1em",
                opacity: 0,
            });
            
            // 7. span 요소들을 순차적으로 본래 위치로 배치
            $effect.children().each(function (index) {
                $(this).delay(index * 400).animate({ 
                    left: $(this).data("left"), fontSize: "1.2em", opacity: "0.6"
                }).animate({ fontSize: "1em", opacity: "1" })
            });

    }); // document.onready
</script>