연습문제

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

  • PhotoViewer : 2초마다 이미지가 자동으로 슬라이드, 마우스 포인터가 이미지 영역에 있으면 슬라이드 정지, 포토뷰어 오른쪽 아이콘을 클릭할 때마다 이미지 한 개씩 넘어가는기능
  • 중간 배너 이미지와 푸터 영역은 스크롤을 내려도 고정되게끔 구현

 

 

풀이 (PhotoViewer)

1. #slide 요소의 이미지 슬라이드 기능

    1.1. 일정한 시간마다

    1.2. #slide 요소를 li 요소의 너비만큼 왼쪽으로 이동시킨다.

    1.3. #slide 요소의 움직임이 끝나면

    1.4. #slide 요소에 설정했던 스타일 속성을 제거하고

    1.5. #slide 요소의 첫 번째 자식 요소를 #slide 요소의 마지막으로 옮긴다.

2. #goods 요소의 영역에 마우스 포인터가 들어가면 이미지 슬라이드 기능 정지

    2.1. #goods 요소의 영역에 마우스 포인터가 들어가면

    2.2. #slide 요소를 움직이게 하는 타이머를 해제한다.

3. #goods 요소의 영역에서 마우스 포인터가 빠져나가면 이미지 슬라이드 기능 다시 시작

    3.1. #goods 요소의 영역에서 마우스 포인터가 빠져나가면

    3.2. #slide 요소를 움직이게 하는 타이머를 다시 등록한다.

4. #next 요소를 클릭하면 #slide 요소의 다음 사진을 표시

    4.1. #next 요소를 클릭하면

    4.2. #slide 요소의 다음 사진이 나오도록 왼쪽으로 이동시킨다.

5. #prev 요소를 클릭하면 #slide 요소의 이전 사진을 표시

    5.1. #prev 요소를 클릭하면

    5.2. #slide 요소의 마지막 자식 요소를 #slide 요소의 처음으로 옮기고

    5.3. #slide 요소를 li 요소의 너비만큼 왼쪽으로 이동시킨다.

    5.4. 그 다음 #slide 요소를 li 요소의 너비만큼 오른쪽으로 이동시킨다.

 

 

 

● HTML

<body>
<header id="header">
    <h1>JO MALONE<span>London</span></h1>
</header>

<main id="content">
    <div id="goods">
        <ul id="slide">
            <li><img src="images/jo-malone/jo-malone-goods-1.jpg" alt="Thumbnail"></li>
            <li><img src="images/jo-malone/jo-malone-goods-2.jpg" alt="Thumbnail"></li>
            <li><img src="images/jo-malone/jo-malone-goods-3.jpg" alt="Thumbnail"></li>
            <li><img src="images/jo-malone/jo-malone-goods-4.jpg" alt="Thumbnail"></li>
            <li><img src="images/jo-malone/jo-malone-goods-5.jpg" alt="Thumbnail"></li>
            <li><img src="images/jo-malone/jo-malone-goods-6.jpg" alt="Thumbnail"></li>
            <li><img src="images/jo-malone/jo-malone-goods-7.jpg" alt="Thumbnail"></li>
            <li><img src="images/jo-malone/jo-malone-goods-8.jpg" alt="Thumbnail"></li>
        </ul>
        <button id="next"><span>Next</span></button>
        <button id="prev"><span>Previous</span></button>
    </div>

    <div id="banner">
        <h2>The Talk Of The Townhouse</h2>
    </div>

    <div id="messages">
        <ul>
            <li>
                <h2>A Special Delivery</h2>
                <p>
                    Want your gifts to arrive on time?
                    We'll arrange your delivery to suit you.
                    <a href="#special-delivery">Learn More</a>
                </p>
            </li>
            <li>
                <h2>Live Chat</h2>
                <p>
                    Looking for a magical gift for someone special?
                    We can help. Speak to our experts with Live Chat.
                    <a href="#live-chat">Learn More</a>
                </p>
            </li>
            <li>
                <h2>Personalized Engraving</h2>
                <p>
                    Give your loved one something truly thoughtful.
                    Engrave their gift with a unique fesitive message.
                    <a href="#personalized-engraving">Learn More</a>
                </p>
            </li>
        </ul>
    </div>
</main>

<footer id="footer">
    <h2>JO MALONE<span>London</span></h2>
</footer>
</body>

 

● CSS

<style>
    /* 1. 헤더 영역 */
    #header {
        height: 800px;
        position: relative;

        /* #footer 요소의 fixed scrolling 구현하기 (1-3)
            같은 형제요소가 똑같이 position 속성이 부여되어 있다면
            형제 요소 중 가장 마지막에 위치한 요소가 맨위에 나타나게 된다.
            그러므로 #footer 요소보다 위에 배치하기 위해 z-index 스타일 속성 설정한다. */
        z-index: 10;

        /* #footer 요소의 fixed scrolling 구현하기 (2) 
            background-color의 기본값은 transparent이므로
            #footer 요소가 비쳐보이지 않도록 하기 위해 배경 색상을 주어야 한다. */
        background-color: white;
    }

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

        font-size: 3.8em;
        font-weight: 900;
        font-variant: small-caps;
        letter-spacing: 8px;
        line-height: 1.2;
        text-align: center;
        white-space: nowrap;
    }

    #header > h1 > span {
        display: block;
        font-size: 0.7em;
    }

    /* 2. 본문 영역 */
    #content {
        /* #footer 요소의 fixed scrolling 구현하기 (1-2) 
            #footer 요소가 뷰포트를 기준으로 fixed 되어 있으므로
            #header, #content 요소를 가리게 된다.
            #footer 요소보다 위에 배치하기 위해 position 스타일 속성 설정 */
        position: relative;
        z-index: 10;

        /* #footer 요소의 fixed scrolling 구현하기 (2) 
            background-color의 기본값은 transparent이므로
            #footer 요소가 비쳐보이지 않도록 하기 위해 배경 색상을 주어야 한다. */
            background-color: white;

        /* #footer 요소의 fixed scrolling 구현하기 (3) 
            브라우저가 스크롤 되면 아래쪽에 있는 #footer 요소가 보이도록 
            #footer 요소의 높이만큼 아래쪽에 여백 설정 */
        margin-bottom: 800px;
    }

    /* 2.1. 이미지 슬라이드 영역 */
    #goods {
        width: 1080px;
        margin: 0 auto 200px;
        overflow: hidden;

        position: relative;
    }

    #slide {
        width: 200%;
        height: 250px;
    }

    #slide > li {
        float: left;
        width: 250px;
        height: 250px;
        padding: 0 10px;
        overflow: hidden;
        position: relative;
    }

    /* li 요소의 영역의 너비와 높이를 고정시킨 다음 이미지를 가운데 영역에 배치시키고
        너비만 고정시킨 후 li 요소의 영역에 overflow: hidden을 걸어주면 각자 비율이 다른 사진을
        1대 1 크기의 썸네일 이미지로 구현할 수 있다. */
    #slide > li > img {
        position: absolute;
        top: 50%; left: 50%;
        transform: translate(-50%, -50%);
        width: 250px;
    }

    /* 다음 사진, 이전 사진 버튼 */
    #goods > button {
        border: none;
        outline: none;
        background-color: transparent;
        padding: 0;
        cursor: pointer;

        position: absolute;
        top: 50%;
        transform: translateY(-50%);

        width: 48px; height: 48px;
        opacity: 0.2;
        transition-duration: 200ms;
    }

    #goods:hover > button { opacity: 1; }

    #goods > button > span { display: none; }

    #prev {
        left: 10px;
        background: url("images/jo-malone/prev-button.png") no-repeat center;
    }

    #next {
        right: 10px;
        background: url("images/jo-malone/next-button.png") no-repeat center;
    }

    /* 2.2 배너 영역 */
    #banner {
        height: 300px;
        margin-bottom: 200px;
        background: url("images/jo-malone/jo-malone-banner.png") no-repeat center;
        background-size: cover;
        background-attachment: fixed;
    }

    #banner > h2 {
        width: 1080px;
        padding-top: 50px;
        margin: 0 auto;
        text-align: right;

        font-size: 3em;
        font-weight: 900;
        font-variant: small-caps;
    }

    /* 2.3. 메시지 영역 */
    #messages {
        height: 560px;
        border-top: 1px solid #999;
        position: relative;
    }

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

        width: 1080px;
    }

    #messages > ul::after { content: ""; display: block; clear: both; }

    #messages > ul > li {
        float: left;
        width: 33.333%;
        text-align: center;
    }

    #messages > ul > li > h2 {
        font-size: 1.8em;
        font-weight: bold;
        font-variant: small-caps;
        margin-bottom: 1em;
    }

    #messages > ul > li > p {
        line-height: 1.8;
    }

    #messages > ul > li > p > a {
        display: block;
        width: 200px;
        border: 1px solid #999;
        border-radius: 4px;
        margin: 1.4em auto 0;

        text-decoration: none;
        line-height: 2.4;
        color: black;

        transition-duration: 100ms;
    }

    #messages > ul > li > p > a:hover {
        box-shadow: 0 0 4px rgba(0, 0, 0, 0.4);
    }

    /* 3. 푸터 영역 */
    #footer {
        height: 800px;
        background-color: black;
        color: white;

        /* #footer 요소의 fixed scrolling 구현하기 (1-1) 
            #footer 요소 영역을 뷰포트를 기준으로 하단에 고정시킨다. */
        position: fixed;
        bottom: 0; right: 0; left: 0;
    }

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

        font-size: 3.8em;
        font-weight: 900;
        font-variant: small-caps;
        letter-spacing: 8px;
        line-height: 1.2;
        text-align: center;
        white-space: nowrap;
    }

    #footer > h2 > span {
        display: block;
        font-size: 0.7em;
    }
</style>

 

● script

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

        // 1. #slide 요소의 이미지 슬라이드 기능
        // 1.1. 일정한 시간마다
        var timerId = window.setInterval(slideGoods, 2000);


        $goods.hover(
            // 2. #goods 요소의 영역에 마우스 포인터가 들어가면 이미지 슬라이드 기능 정지
            // 2.1. #goods 요소의 영역에 마우스 포인터가 들어가면
            function () {
                // 2.2. #slide 요소를 움직이게 하는 타이머를 해제한다.
                window.clearInterval(timerId);
            },

            // 3. #goods 요소의 영역에서 마우스 포인터가 빠져나가면 이미지 슬라이드 기능 다시 시작
            // 3.1. #goods 요소의 영역에서 마우스 포인터가 빠져나가면
            function () {
                // 3.2. #slide 요소를 움직이게 하는 타이머를 다시 등록한다.
                timerId = window.setInterval(slideGoods, 2000)
            });

        // 4. #next 요소를 클릭하면 #slide 요소의 다음 사진을 표시
        // 4.1. #next 요소를 클릭하면
        $goods.children("#next").on("click", function () { 
            // 4.2. #slide 요소의 다음 사진이 나오도록 왼쪽으로 이동시킨다.
            slideGoods(); 
        });

        // 5. #prev 요소를 클릭하면 #slide 요소의 이전 사진을 표시
        // 5.1. #prev 요소를 클릭하면
        $goods.children("#prev").on("click", function () {
            // 5.2. #slide 요소의 마지막 자식 요소를 #slide 요소의 처음으로 옮기고
            // 5.3. #slide 요소를 li 요소의 너비만큼 왼쪽으로 이동시킨다.
            $slide.prepend( $slide.children(":last") ).css("margin-left", "-25%")
                // 5.4. 그 다음 #slide 요소를 li 요소의 너비만큼 오른쪽으로 이동시킨다.
                .animate({ "margin-left": 0 });
        });

        //-------------------------------------------------------------------------
        function slideGoods() {
            // 1.2. #slide 요소를 li 요소의 너비만큼 왼쪽으로 이동시킨다.
            //      li 요소의 너비 = #goods 요소 너비의 1/4 = 270px
            $slide.animate({"margin-left": "-25%"}, function () {
                // 1.3. #slide 요소의 움직임이 끝나면
                // 1.4. #slide 요소에 설정했던 스타일 속성을 제거하고
                // 1.5. #slide 요소의 첫 번째 자식 요소를 #slide 요소의 마지막으로 옮긴다.
                $slide.removeAttr("style").children(":first").appendTo($slide);
            });
        }

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