5. Poomgo 반응형 웹 클론 코딩

wj·2022년 9월 22일
0

포트폴리오 작업

목록 보기
4/7
post-thumbnail

📌
사이트 명: 품고 반응형 (Poomgo)
제작 기간: 22.08.27 ~ 22.08.31 (5일 소요)
사용 언어: html, css, jQuery, java script, GSAP

[Poomgo 반응형 웹 클론 코딩 작업]

GSAP 플러그인을 활용하여 다양한 스크롤 애니메이션 기능들을 구현하는 법을 배운 반응형 클론 코딩 작업물입니다!

💡Learning point

  • css 미디어 쿼리
  • header, gnb 영역
  • picture>source 태그 활용
  • rolling banner 영역
  • tab 영역 스크립트
  • GSAP 라이브러리 활용

1. css 미디어 쿼리

@media (조건) {
스타일
}

  • 미디어 쿼리는 CSS에서 어떤 스타일을 선택적으로 적용하고 싶을 때 사용! 스타일 부분에는 일반적인 CSS 코드가 들어가는데, 해당 조건 부분이 만족될 때는 스타일이 적용되고, 만족되지 않을 때는 스타일이 적용되지 않는다.
@media all and (max-width: 1300px){
    .sc-main .text-wrap{
        max-width: 704px;
        top:calc(30vh - 124px);
        padding-top: 58px;
    }
    ... 이하 생략
}
@media all and (max-width: 750px){
    .header{
        min-height: 64px;
        height: 64px;
    }
    ... 이하 생략
}
@media (min-width:600px) and (max-width:820px){
    .sc-main .banner-area{
        padding-left: 50px;
    }
}
@media all and (max-width:600px){
    .banner-area .swiper-slide img{
        width: 20px;
        height: 20px;
    }
}

해당 사이트의 break point를 참고하여 제작했다.
공통적으로는 750과 1300이라는 두 개의 break point를 만들고 특정 사이즈에서 따로 수정되어야 하는 부분들은 각각 잡아서 수정해주었다.

2. header, gnb 영역

스크롤을 내리면 header 및 gnb 영역의 디자인이 바뀌도록 설정

[css]

/* 스크롤 내린 후 header */
.header.fixed{
    background: #fff;
}
.header.fixed h1{
    position: relative;
    width: 160px;
    height: 32px;
    background: url(../images/logo-blue.svg);
    background-repeat: no-repeat;
    background-size: 160px 32px;
}
.header.fixed .gnb-item:not(:last-child){
    color: #4d5968;
}
.header.fixed .group-header .depth1{
    background: #fff;
    color: #4d5968;
}
.header.fixed .group-header .gnb-item .depth1::after{
    content: '';
    background: #0040d1;
}
.header.fixed .group-header .depth1 > li:hover a{
    color: #4d5968;
    background: #f4f8ff;
}

[js]

//header 스크롤 이벤트
    $(window).scroll(function(){
        const curr = $(this).scrollTop();
        if (curr > 0) {
            $('.header').addClass('fixed');
        } else {
            $('.header').removeClass('fixed');
        }
    })
    $(window).trigger('scroll');//스크롤 이벤트 강제 실행

3. picture>source 태그 활용

  • picture, source 태그를 활용하여 사이즈가 다른 두 장의 이미지를
    브라우저 사이즈에 맞게 적절하게 보여주도록 설정했다.
<picture class="bg">
  <source srcset="./assets/images/slide01.webp" media="all and (min-width: 750px)">
  /* 750px 사이즈 이후부터는 pc용 이미지 */
  <img src="./assets/images/slide01-mo.webp" alt="슬라이드 이미지01">
  /* 750px 사이즈까지는 모바일용 이미지 */
</picture>

4. rolling banner 영역

  • 각각 좌우로 흐르면서 이어지는 롤링 배너 영역을 제작하기 위해 브라우저 사이즈가 커지더라도 이미지가 잘리지 않도록 이미지 영역의 너비를 2000px넘게 설정해주었고, 두 장의 이미지가 자연스럽게 이어지도록 @keyframes 를 활용한 애니메이션을 적용했다.

[html]

<div class="logo-slide" data-fade>
  <div class="img-box row1">
    <img src="./assets/images/partner01.webp" alt="파트너사 브랜드 로고">
    <img src="./assets/images/partner01.webp" alt="파트너사 브랜드 로고">
  </div>
  <div class="img-box row2">
    <img src="./assets/images/partner02.webp" alt="파트너사 브랜드 로고">
    <img src="./assets/images/partner02.webp" alt="파트너사 브랜드 로고">
  </div>
</div>

  • row2의 경우 row1과 시작점이 다르기 때문에 transform: translateX(-100%);로 미리 x축을 당겨 시작점을 같게 만들어준 뒤 애니메이션을 적용시킨다.

[css]

.sc-partnership .img-box{
    display: flex;
    position: absolute;
    width: 2329px;
    height: 232px;
}
.sc-partnership .img-box.row1{
    top: 0; left: 0;
    animation: movetoleft 50s linear infinite;
}
@keyframes movetoleft{
    0%{
        transform: translateX(0);
    }
    100%{
        transform: translateX(-100%);
    }
}
.sc-partnership .img-box.row2{
    bottom: 0; right: 0;
    animation: movetoright 50s linear infinite;
    transform: translateX(-100%);
}
@keyframes movetoright{
    0%{
        transform: translateX(-100%);
    }
    100%{
        transform: translateX(0);
    }
}

5. tab영역 구성

  • WAI-AREA로 tablist, tab, presentaion role 설정해주고, 각각의 tab-contents에 id를 부여하고 tab 클릭시 해당하는 컨텐츠가 호출되도록 제작했다.
/* 탭 영역*/
<div class="tab-nav">
  <ul class="skill-list" role="tablist">
    <li class="skill-item active" role="presentation">
      /* 탭 영역 active시 보이는 영역*/
      <span class="move"></span>
      <a href="#skill01" data-target="#skill01" role="tab">업무 자동화</a>
    </li>
    <li class="skill-item" role="presentation">
      <a href="#skill02" data-target="#skill02" role="tab">빅데이터 분석</a>
    </li>
    <li class="skill-item" role="presentation">
      <a href="#skill03" data-target="#skill03" role="tab">수요 예측</a>
    </li>
  </ul>
</div>

/* 탭 컨텐츠 영역 */
<div class="tab-contents">
  <div id="skill01" class="cont active">
  ... 이하 생략
  </div>
  <div id="skill02" class="cont">
  ... 이하 생략
  </div>
  <div id="skill03" class="cont">
  ... 이하 생략
  </div>
</div>

[js]

//탭영역 nav focus 구현
$(".skill-item").click(function (e) {
  e.preventDefault();
  //탭 부분이 클릭되면

  i = $(this).index();//순서 구하기
  w = $(".move").width();//너비 구하기
  $(".move").css("left", w * i);//순서*너비 값만큼 left값 주기

  if ($(".move").width() >= 0) {
    $(this).addClass("active").siblings().removeClass("active");
    //move에 값이 생기면 해당 탭 영역 활성화 시키고, 나머지 비활성화
  }
});


//해당하는 탭 컨텐츠 노출
const tabList = document.querySelectorAll(".tab-nav .skill-item");
const contents = document.querySelectorAll(".tab-contents .cont");
let activeCont = ""; //현재 활성화 된 컨텐츠

for (var l = 0; l < tabList.length; l++) {
  tabList[l]
    .querySelector(".skill-item a")
    .addEventListener("click", function (e) {
      e.preventDefault();
      for (var j = 0; j < tabList.length; j++) {
        //나머지 버튼 클래스 제거
        tabList[j].classList.remove("active");

        //나머지 컨텐츠 display:none 처리
        contents[j].style.display = "none";
      }

      //버튼 관련 이벤트
      // this.parentNode.classList.add('active');

      //버튼 클릭시 컨텐츠 전환
      activeCont = this.getAttribute("href");
      document.querySelector(activeCont).style.display = "block";
    });
}

6. GSAP 라이브러리 활용

스크롤에 반응하는 애니메이션을 구현하기 위해 GSAP scrollTrigger 라이브러리를 활용했다. GSAP를 활용하기 위해서는 gsap cdn과 사용할 라이브러리 cdn을 세팅해두어야 한다.

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.10.4/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.10.4/ScrollTrigger.min.js"></script>

6-1. GSAP 기본 속성

  • gsap.to : 타겟의 끝점으로 애니메이션 실행
  • gsap.from : 타겟의 시작점에서 애니메이션 실행
  • gsap.fromTo : ~부터 ~로 애니메이션 실행

scrollTrigger

scrollTrigger:{
	trigger:"기준 요소",
	start:"top top", //[기준 요소 시작점, 윈도우 시작점]
    top->0% bottom->100% 20%,30% 다됨
	end:"bottom top"//기준
	markers:true, //페이지 내에 시작점, 끝점 표시
	scrub:1 // 반복하거나, 시작점부터 끝점까지 동작 이어지도록(end 필수)
}

6-2. matchMedia

break point를 지정하여 해당 지점에서 원하는 동작을 실행하도록 설정

ScrollTrigger.matchMedia({
  "(min-width: 1025px)": function() {},
  "(min-width: 768px) and (max-width: 1024px)": function() {},
  "(max-width: 767px)": function() {},
  "all": function() {}    });

6-3. 가로 스크롤 슬라이드

헤더 영역에 가려지지 않게 헤더 높이만큼을 슬라이드 영역 높이에서 빼주고, 화면이 고정된 상태에서 가로로 슬라이드 가 동작하도록 구현했다.

[css]

.sc-experience .group-list{
    width: 400vw;
    display: flex;
    height: calc(100vh - 100px);
    //헤더 높이 100px을 빼줌
}
.sc-experience .content{
    width: 100vw;
    //한 슬라이드가 화면에 가득 차도록
    padding: 5px 15px 40px;
}

[js]

//gsap 슬라이드 영역
ScrollTrigger.matchMedia({
  //large
  "(min-width:751px)": function () {
  //751px 이상부터 동작하도록
    gsap.to(".sc-experience .group-list", {
      scrollTrigger: {
        trigger: ".group-list", //기준
        start: "top 100px", //기준 시작점, 윈도우 시작점 => 헤더 영역 제외
        end: "+=500%", //기준 끝점, 윈도우 끝점 => 트리거의 5배의 스크롤 값
        // markers: true,
        scrub: 1,
        pin: true
        //슬라이드 되는 동안 화면이 고정되도록
      },
      xPercent: -75
    });
  }
});

6-4. 배너 패널

스크롤을 내리면 배너가 가로로 점점 길어지는 애니메이션 구현.
좌우로 하얀색 사각형을 만들어주고, 스크롤 시 이 길이가 조절되도록 설정했다.

[html]

<div class="banner-area panel-banner">
  <div class="img-box"><img src="./assets/images/banner.webp" alt="배너 이미지"></div>
  <p class="txt-box"><span>비즈니스 성장에 필요한<br>품고의 서비스를 확인하세요</span></p>
  <span class="panel left-panel"></span>
  <span class="panel right-panel"></span>
</div>

[css]

.left-panel{
    position: absolute;
    top: 0;left: 0;
    width: 400px;
    height: 100%;
    background: #fff;
}
.right-panel{
    position: absolute;
    top: 0;right: 0;
    width: 400px;
    height: 100%;
    background: #fff;
}

[js]

//배너 패널 영역
gsap.to(".panel", {
  scrollTrigger: {
    trigger: ".panel-banner",
    start: "top 100%",
    end: "bottom 50%",
    scrub: 1
    //스크롤 시, 반복되도록
  },
  width: 0
  //width가 0이 될 때까지 동작
});

6-5. 컨텐츠 페이드업

페이지 내에 스크롤 시 페이드업 되는 기능을 가진 섹션이 많아서,
동일한 data명을 주고 그 값을 활용해서 스크롤 트리거 기능을 적용했다.

[html]

<div class="text-wrap" data-fade>
  <h2 class="headline">운영 솔루션</h2>
  <strong class="main-txt">남다른 디테일로<br>완-벽한 물류 환경</strong>
  <p class="sub">어떤 점이 궁금하세요?</p>
</div>

[js]
페이드업 영역

  • data-fade값을 가진 요소들은 단순 페이드업 되도록 적용
$("[data-fade").each(function (i, l) {
  gsap.from(l, {
    scrollTrigger: {
      trigger: l,
      start: "top 100%",
      end: "bottom 100%"
      // markers:true,
      // scrub:1
    },
    opacity: 0,
    yPercent: 20
  });
});
  • data-child값을 가진 요소의 자식 요소들은 순차적으로 페이드업
$("[data-child]").each(function (i, l) {
  child = $(this).find("> *");
  gsap.from(child, {
    scrollTrigger: {
      trigger: l, //[기준]
      start: "top 90%", //[기준시작점][윈도우시작점]   0% -> top or 100% -> bottom
      end: "bottom 90%" //[기준끝점][윈도우끝점]
      // markers:true,
      // scrub:1
    },
    opacity: 0,
    yPercent: 20,
    stagger: 0.1 //stagger값을 주면 요소들이 순차적으로 움직인다
  });
});

scrollTrigger의 활용 방법은 무궁무진한 것 같은데 아직 헷갈리는 게 많아서 더 자주 사용해봐야 익숙해질 것 같다..! 그래도 새로운 기능 너무 신기하고 재밌어

profile
tistory로 옮겼습니다

0개의 댓글