빅데이터 Java 개발자 교육 - 42일차 [웹 클로닝 사이트 만들기-2] (실습)

Jun_Gyu·2023년 3월 29일
0
post-thumbnail

지난시간에 이어서 오늘 핀터레스트 클로닝 사이트를 완성해보도록 하겠다.

지난시간에는 사진을 표시하는 Masonry 기능까지 구현을 완료하였다.

오늘부로 추가 작업을 진행하여 마무리해보도록 하겠다.

이번에는 사진을 클릭했을 때 lightbox의 기능이 실행되는것과 더불어 바깥 영역을 클릭하면 바깥으로 나가는 기능을 추가해보도록 하자.

$(document).ready(function () {
            // 풀다운메뉴 이벤트

            $('.outer-menu').hover(function () {    
                $(this).find('.inner-menu').css('display', 'block');
            }, function () {
                $(this).find('.inner-menu').css('display', 'none');
            });

            // masonry layout + imageload plugin
            $('#main-section').imagesLoaded(function () {
                $('#main-section').masonry({
                    itemSelector: '.paper',
                    columnWidth: 220,
                    isAnimated: true,
                });
            });

            // 라이트박스 동작
            function showLightBox(obj) { // 라이트박스 보이기
                var img_src = obj.getElementsByTagName('img')[0].src; // 선택하는 이미지 출력
                $('#random-image').attr('src', img_src); // id값을 불러올때는 공백이 존재하면 안된다! 중요!

                $('#darken-background').show();
                $('#darken-background').css('top', $(window).scrollTop());
                $('body').css('overflow', 'hidden');
            }

            function hideLightBox() { // 라이트박스 숨기기
                $('#darken-background').hide();
                $('body').css('overflow', '');
            }

            $('.paper').on('click', function() {
                showLightBox(this);
            });

            $('#darken-background').click(function (){
                hideLightBox();
            });

            $('#lightbox').click(function (event){
                event.stopPropagation(); // 클릭 이벤트 하위객체 전달 금지
            });
        });

그리고 다음은 CSS 코드이다.

        /* 초기화 */
        * {
            font-family: 'NanumGothic', 'Malgun Gothic' sans-serif;
        }

        a {
            text-decoration: none;
        }

        /* 언더바 모두 삭제 */
        img {
            border: 0;
        }

        li {
            list-style: none;
        }

        body {
            background-color: #fafefe;
        }

        /* ---------------------------------헤더영역 스타일--------------------------------- */
        #main-header {
            height: 40px;
            background-color: #f9fefe;
            position: relative;
        }

        .header-search-form {
            float: left;
            height: 26px;
            padding: 7px;
        }

        .header-menu {
            float: right;
        }

        .header-title {
            position: absolute;
            width: 200px;
            height: 40px;
            left: 10px;
            /* margin-left: -100px; */
            background-image: url('../image/KakaoTalk_20230328_151555545.png'); /* 경로는 점 두개로 지정! */
            background-image: no-repeat;
            text-indent: -9999px;
        }

        /* ---------------------------------풀다운 메뉴영역--------------------------------- */
        .outer-menu {
            float: left;
            width: 100px;
            height: 20px;
            line-height: 20px;
            padding: 10px 0;
            position: relative;
            text-align: center;
            font-size: small;
            font-weight: bold;
            z-index: 9999;
        }

        .outer-menu:hover {
            background-color: #e1dfdf;
        }

        .inner-menu {
            display: none;
            background-color: white;
            margin-top: 10px;
            width: 100%;
            border-top: 1px solid #cccaca;
            box-shadow: 0 2px 2px rgba(34, 25, 25, 0.5)
        }

        .inner-menu a {
            display: block;
            padding: 5px 10px;
            z-index: 5000;
        }

        .inner-menu a:hover {
            background-color: #d1dfdf;
        }

        /* ---------------------------------내비게이션 영역--------------------------------- */
        #main-navigation {
            height: 30px;
            background-color: #f9fefe;
            /* border-top: 1px solid #cfcaca; */
            /* box-shadow: 1px 3px 3px rgba(34, 25, 25, 0.5); */
        }

        #main-navigation>ul {
            position: absolute;
            margin-left: 0%;
            overflow: hidden;
            text-align: center;
        }

        #main-navigation>ul>li {
            display: inline;
            padding: 0 5px;
            line-height: 30px;
            font-size: small;
            color: #524d4d;
            text-shadow: 0 1px 1px white;
        }

        #main-navigation>ul>li:hover {
            background-color: #e1dfdf;
            border-radius: 2px;
        }

        /* ---------------------------------input 영역--------------------------------- */
        .form {
            left: 290px;
            position: relative;
        }

        .form .fa-search {

            position: absolute;
            top: 20px;
            left: 20px;
            color: #9ca3af;

        }

        .form span {

            position: absolute;
            right: 17px;
            top: 13px;
            padding: 2px;
            border-left: 1px solid #d1d5db;

        }

        .left-pan {
            padding-left: 7px;
        }

        .left-pan i {

            padding-left: 10px;
        }

        .form-input {
            width: 250px;
            height: 55px;
            text-indent: 33px;
            border-radius: 10px;
        }

        .form-input:focus {
            box-shadow: none;
            border: none;
        }

        /* ---------------------------------카드영역--------------------------------- */
        .paper {
            width: 210px;
            margin-top: 10px;
            /* padding: 15px 15px 0; */
            font-size: smaller;
            background-color: white;
            box-shadow: 0 1px 2px rgba(34, 25, 25, 0.5);
            border-radius: 10px;
        }

        .paper-img {
            border-radius: 10px;
        }

        .paper-description {
            margin: 10px 0;
        }

        .paper-content {
            z-index: 1000;
            position: absolute;
            bottom: 2px; left: 5px;
            margin-top: 10px;
            padding: 5px;
            background-color: rgba(255, 255, 255, 0.5);
            overflow: hidden;
            border-radius: 10px;
        }

        .paper-link {
            display: block;
            float: left;
        }

        .paper-text {
            float: left;
            width: 150px;
            margin-left: 10px;
            margin-bottom: 0;
        }

        /* ---------------------------------반응형 웹 영역--------------------------------- */
        #main-section {
            width: 920px;
            margin: 0 auto;
            padding-top: 80px;
        }

        /* 한줄에 두개의 카드가 나오도록 설정. */
        @media screen and (max-width: 690px) {
            #main-section {
                width: 460px;
            }
        }

        /* 한줄에 세개의 카드가 나오도록 설정. */
        @media screen and (min-width: 690px) and (max-width: 920px) {

            /* == if 사이즈가 919픽셀 이하이면 */
            #main-section {
                width: 690px;
            }
        }

        /* 한줄에 네개의 카드가 나오도록 설정. */
        @media screen and (min-width: 920px) and (max-width: 1150px) {
            #main-section {
                width: 920px;
            }
        }

        /* 한줄에 다섯개의 카드가 나오도록 설정. */
        @media screen and (min-width: 1150px) and (max-width: 1380px) {
            #main-section {
                width: 1150px;
            }
        }

        /* 한줄에 여섯개의 카드가 나오도록 설정. */
        @media screen and (min-width: 1380px) {

            /* == if 사이즈가 919픽셀 이하이면 */
            #main-section {
                width: 1380px;
            }
        }

        /*---------------------------- 라이트박스 영역 ----------------------------*/
        #darken-background {
            display: none;
            background-color: rgba(60, 60, 60, 0.7);
            z-index: 10000;
            /* 가장 위로 올린다는 이야기. */
            overflow-y: scroll;
            /* 영역 위치 변경 */
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 100%;
        }

        #lightbox {
            width: 700px;
            margin: 20px auto;
            padding: 15px;
            border: 1px solid #999999;
            border-radius: 10px;
            background-color: white;
            text-align: center;
        }
        .head-wrapper {
            width: 100vw;
            position: fixed;
            z-index: 9000;
        }

        .profile-loc {
            position: absolute;
            top: 15px;
            right: 30px;
        }

        /* -------------------------------------------------------------------------------- */

위를 적용하면

이와 같이 꽤 그럴싸한 페이지가 탄생하게 된다.

웹 페이지 작업을 할 때 아래 부분들의 기능을 염두해두도록 하자.

  • Body 부분의 기능들을 구현하기 위해 style과 script를 추가.
  • 클릭 이벤트 하위객체 전달 금지.
  • id값을 불러올때는 공백이 존재하면 안된다.
  • 작업 마무리 후 CSS파일과 JS 파일 분리하여 저장.

Parallax 웹 페이지 구현하기

이번에는 스크롤 다운 기능에 반응하는 웹 페이지를 구현해보려고 한다.

먼저, HTML부터 구성을 해주도록 하자.

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>Parallax Scrolling Web</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
     <!-- 1. Bootstrap용 css CDN 추가 -->
     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/css/bootstrap.min.css" rel="stylesheet"
     integrity="sha384-aFq/bzH65dt+w6FI2ooMVUpc+21e0SRygnTpmBvdBgSdnuTN7QbdgL+OapgHtvPp" crossorigin="anonymous">
     <link rel='stylesheet' type='text/css' media='screen' href='css/parallax.css'>
     <link rel="icon" href="image/ui.ico">

     <!-- 3. jQuery 추가 -->
    <script src="https://code.jquery.com/jquery-3.6.4.min.js"
    integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossorigin="anonymous"></script>

    <script src='javascript/parallax.js'></script>
</head>
<body>
    <header>
        <h2 class="logo">Logo</h2>
        <nav class="navigation">
            <a href="#" class="pullUp">Home</a>
            <a href="#">About</a>
            <a href="#">Service</a>
            <a href="#">Contact</a>
        </nav>
    </header>

    <!-- Section 영역 -->
    <section class="parallax">
        <img src="image/hill1.png" id="hill1"> <!-- 맨뒤 -->
        <img src="image/hill2.png" id="hill2">
        <img src="image/hill3.png" id="hill3">
        <img src="image/hill4.png" id="hill4">
        <img src="image/hill5.png" id="hill5">
        <img src="image/tree.png" id="tree">
        <h2 id="text">Parallax Website</h2>
        <img src="image/leaf.png" id="leaf">
        <img src="image/plant.png" id="plant"> <!-- 맨앞 -->
    </section>

    <section class="contents">
        <h2>Parallex Scrolling Web</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Eum accusamus, tenetur adipisci doloremque dicta voluptatem ea, voluptas aperiam qui quos nesciunt velit nam minima voluptates molestias aspernatur laborum, dolor aliquam possimus illo? Neque aperiam excepturi itaque harum? Totam eligendi nostrum enim! Exercitationem molestias veniam, repudiandae consectetur, eum debitis quisquam doloribus, velit officiis eligendi eius nemo iste animi vero autem facere qui. Qui iste doloribus ipsam sapiente. Explicabo rem officiis ad ut eligendi nesciunt sed! Alias quis maiores impedit eaque quasi? Non suscipit consectetur quidem iusto, at est voluptatibus repellendus, ducimus praesentium temporibus modi, qui commodi numquam quis recusandae molestias excepturi. Illum ab quisquam eum molestias repellendus corporis, magnam minima quod explicabo inventore sint, in placeat sequi harum at architecto quasi sapiente voluptas pariatur accusamus ad hic! Eius odit adipisci quae harum quis quasi dolores, molestias accusamus cupiditate explicabo natus consectetur. Non inventore esse nemo ex quaerat maiores consectetur, temporibus sequi amet a officia eligendi nihil atque et dignissimos hic harum delectus consequuntur accusamus nobis qui rem voluptates molestias! Molestiae asperiores a provident autem, expedita commodi voluptatum consequatur sapiente cumque officiis quibusdam reiciendis sequi optio debitis recusandae exercitationem nisi repellendus perspiciatis. Error, blanditiis debitis! Voluptas soluta deleniti cumque, libero nobis vel ad. Eligendi ipsam, eum itaque soluta magni inventore sunt repellat alias blanditiis molestias eveniet illo non natus voluptatem vero maiores explicabo consequatur quia corrupti nam, doloribus praesentium ut! Similique soluta nesciunt repellat obcaecati odit. Accusantium, ratione officiis natus provident dignissimos odit fugit est iusto quidem maxime nostrum consectetur minus, laboriosam quaerat mollitia repellat expedita, impedit earum voluptatem tempore porro magni. Totam voluptatum harum ipsam eaque dolor ex deserunt possimus numquam, provident hic non tempora, eos optio nemo fugit quae earum sit aspernatur eligendi recusandae. Accusantium laudantium, a, rem dolor facere voluptatem facilis laboriosam nobis quasi sunt fugit nisi possimus maxime!<br><br> </p>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Eum accusamus, tenetur adipisci doloremque dicta voluptatem ea, voluptas aperiam qui quos nesciunt velit nam minima voluptates molestias aspernatur laborum, dolor aliquam possimus illo? Neque aperiam excepturi itaque harum? Totam eligendi nostrum enim! Exercitationem molestias veniam, repudiandae consectetur, eum debitis quisquam doloribus, velit officiis eligendi eius nemo iste animi vero autem facere qui. Qui iste doloribus ipsam sapiente. Explicabo rem officiis ad ut eligendi nesciunt sed! Alias quis maiores impedit eaque quasi? Non suscipit consectetur quidem iusto, at est voluptatibus repellendus, ducimus praesentium temporibus modi, qui commodi numquam quis recusandae molestias excepturi. Illum ab quisquam eum molestias repellendus corporis, magnam minima quod explicabo inventore sint, in placeat sequi harum at architecto quasi sapiente voluptas pariatur accusamus ad hic! Eius odit adipisci quae harum quis quasi dolores, molestias accusamus cupiditate explicabo natus consectetur. Non inventore esse nemo ex quaerat maiores consectetur, temporibus sequi amet a officia eligendi nihil atque et dignissimos hic harum delectus consequuntur accusamus nobis qui rem voluptates molestias! Molestiae asperiores a provident autem, expedita commodi voluptatum consequatur sapiente cumque officiis quibusdam reiciendis sequi optio debitis recusandae exercitationem nisi repellendus perspiciatis. Error, blanditiis debitis! Voluptas soluta deleniti cumque, libero nobis vel ad. Eligendi ipsam, eum itaque soluta magni inventore sunt repellat alias blanditiis molestias eveniet illo non natus voluptatem vero maiores explicabo consequatur quia corrupti nam, doloribus praesentium ut! Similique soluta nesciunt repellat obcaecati odit. Accusantium, ratione officiis natus provident dignissimos odit fugit est iusto quidem maxime nostrum consectetur minus, laboriosam quaerat mollitia repellat expedita, impedit earum voluptatem tempore porro magni. Totam voluptatum harum ipsam eaque dolor ex deserunt possimus numquam, provident hic non tempora, eos optio nemo fugit quae earum sit aspernatur eligendi recusandae. Accusantium laudantium, a, rem dolor facere voluptatem facilis laboriosam nobis quasi sunt fugit nisi possimus maxime!</p>
    </section>

<footer>
    <nav>
        <a href="#">Blog</a>
        <span> | </span>
        <a href="#">Github</a>
    </nav>
    <p>
        <span>author : Codehal</span><span> | </span>
        <span>editor : Jungyu Park</span><span> | </span>
        <span>email : junkue13@gmail.com</span><span> | </span>
        <span>Copyright &copy; 2022.codehal. All Rights Reserved</span><span> | </span>
    </p>
</footer>

    <!-- 2. Bootstrap용 js는 body에 위치해야 함! -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-qKXV1j0HvMUeCBQ+QVp7JcfGl760yU08IQ+GpUo5hlbpg51QRiuqHAJz8+BrxE/N"
        crossorigin="anonymous"></script>
</body>
</html>

여기서 사용한 이미지 파일들은 추후 스크롤바를 내렸을때 상호작용을 위한 이미지 파일들이다.

다음으로는 CSS이다.

/* 구글폰트로 웹사이트 글꼴 변경 */
@import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght@200;300;400;500;600;700;800;900&display=swap');

* {
    box-sizing: border-box;
    font-family: 'Ubuntu', sans-serif;
}

body {
    min-width: 900px;
    background-color: #f9f9f9;
    min-height: 100vh; /* 100vw = 100% */
    overflow-x: hidden; /* x축 스크롤 금지 */
}

.contents {
    position: relative;
    background-color: #003329;
    padding: 50px 100px;
}

@media screen and (max-width : 800px) {
    .body{
        min-width: 720px;
    }
}
@media screen and (min-width : 800px) and (min-width : 1150px) {
    .body{
        min-width: 700px;
    }
}
@media screen and (max-width : 800px) {
    .body{
        min-width: 700px;
    }
}
@media screen and (max-width : 800px) {
    .body{
        min-width: 700px;
    }
}

header {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%; /* 100vw = 100% */
    padding: 30px 100px;
    display: flex;
    justify-content: space-between; /* flex(grid 레이아웃) 꾸밀때 가로정렬 */
    align-items: center; /* 수직 중앙정렬 */
    z-index: 100;
}

.logo {
    font-size: 2em; /* 2배 */
    font-weight:  900;
    color: #359381;
    pointer-events: none; /* 마우스 커서를 올렸을 때 아무 이벤트를 주지 않겠다는 뜻 */
}

.navigation > a {
    text-decoration: none; /* 언더바 삭제 */
    color: #359370;
    font-weight: 500; 
    margin: 0px 10px;
    padding: 5px 15px 8px 15px;
    border-radius: 20px;
}

.navigation a:hover,
.navigation a:active { /* 마우스 커서를 올려둘 때 효과 */
    background-color: #359381;
    color: #f9f9f9;
}

.parallax {
    position: relative;
    display: flex; /* flex 레이아웃 */
    justify-content: center;
    align-items: center; /* 수평 중앙정렬, 수직 중앙정렬 */
    height: 100vh; /* ==100% */
}

.parallax img {
    position: absolute;
    top: 0; left: 0;
    width: 100vw;
    pointer-events: none;
}

#text {
    position: absolute;
    font-size: 5em; /* 5배 더 크게 */
    font-weight: 900;
    color: floralwhite;
    text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
}

.contents > h2 {
    font-size: 3em; /* 3배 */
    font-weight: 600;
    text-align: center;
    color: floralwhite;
    margin-bottom: 10px;
}

.contents > p {
    font-size: 1em;
    font-weight: 300;
    color: white;
}

footer {
    position: relative;
    width: 100%; height: 110px;
    bottom: 0px;
    padding-top: 10px;
    text-align: center;
    font-size: 0.9em;
    font-weight: 400;
    color: #359381;
}

footer a {
    text-decoration-line: none;
    color: #003329;
    display: inline-block;
    margin: 0 10px 10px 10px;
}

구글에서 배포하는 무료 폰트를 사용하기 위하여 @import를 선언하였으며, 글꼴은 "Ubuntu"를 사용하였다. 또한, 폰트의 크기를 200부터 900까지 모두 불러와 사용하는데 있어 불편함이 없도록 하였다.

마지막으로는 JS이다.

$(document).scroll(function () {
    //TODO
});

$(window).scroll(function () {
    let value = window.scrollY /* scrollY는 property, 변수 그 자체로 괄호가 필요없다. */

    $('#text').css('margin-top', value * 2.0 + 'px');
    $('#leaf').css({
        'top': value * -0.4 + 'px',
        'left': value * 1.2 + 'px'
    });
    $('#hill1').css('top', value * 0.2 + 'px' );
    $('#hill2').css('top', value * 0.3 + 'px' );
    $('#hill3').css('top', value * 0.4 + 'px' );
    $('#hill4').css({
        'top': value * 0.5 + 'px',
        'left': value * -1.2 + 'px'
    });
    $('#hill5').css({
        'top': value * 0.5 + 'px',
        'left': value * 1.2 + 'px'
    });
    
    
});

JS의 경우에는 간단하게 스크롤을 내릴 때 상호작용하는 배경화면의 속도를 설정해주었다.

이를 통해서 아래와 같은 멋있는 사이트를 제작하였다.

(스크롤을 내리게 되면 나뭇잎들이 주변으로 걷히고 웹페이지의 문구가 언덕너머로 사라진다!)


profile
시작은 미약하지만, 그 끝은 창대하리라

0개의 댓글