태그호이어

seungyeon·2024년 12월 9일

Portfolio_Code Review

목록 보기
7/9
post-thumbnail

태그호이어

  • 사이트명 : 태그호이어
  • 사용언어 : HTML, CSS, JS
  • 사용플러그인 : Swiper, GSAP, Lenis
  • 분류 : 적응형 PC, 클론코딩

1. lenis

Lenis는 부드러운 스크롤을 구현하는 JavaScript 라이브러리이다.

<script src="https://unpkg.com/lenis@1.1.18/dist/lenis.min.js"></script>
const lenis = new Lenis();

lenis.on('scroll', ScrollTrigger.update);

gsap.ticker.add((time) => {
  lenis.raf(time * 700);
});

gsap.ticker.lagSmoothing(0);
  • 좀 더 매끄러운 움직임을 볼 수 있는 좋은 라이브러리이다 😊

2. .space 크기에 맞게 비디오 축소

<div class="group-text">
  <div class="text-wrap">
    <span class="text txt1">TAG HEUER</span>
  </div>
  <div class="text-wrap">
    <span class="text txt2">FORMULA</span>
    <span class="space"></span>
    <span class="text txt3"> 1 | KITH</span>
  </div>
</div>
const kithVideo = gsap.timeline({
  scrollTrigger:{
    trigger: ".sc-kith .sticky-wrapper",
    start: "top top",
    end: "100% 100%",
    scrub: 0,
  }
})
kithVideo
.to('.sc-kith .group-video .video-area',{
  'clip-path': function(){
    const sticky = document.querySelector('.sc-kith .sticky-wrapper .sticky');
    const space = document.querySelector('.sc-kith .space');

    const stickyRect = sticky.getBoundingClientRect();
    const spaceRect = space.getBoundingClientRect();

    const relativeTop = spaceRect.top - stickyRect.top;
    const relativeLeft = spaceRect.left - stickyRect.left;
    const relativeBottom = spaceRect.top - space.clientHeight;
    const relativeRight = spaceRect.left;

    return `inset(${relativeTop}px ${relativeLeft}px ${relativeBottom}px ${relativeRight}px )`
  }
},'b')
  • 이번 포트폴리오에서 가장 어려운 부분이었다. 텍스트가 붙어있고, 정해진 넓이로 변경이 되어야 했다.
  • inset을 사용해서 비디오가 위,아래,왼쪽,오른쪽이 줄어들도록 했다.
  • 큰 부분은 .sticky에 height: 100vh;가 잡혀있었고,
  • 사각형 부분은 .space에 height값을 줬고,
  • 위,오른쪽,아래,왼쪽을 각각 큰 부분에서 .space부분을 빼줘서 구했다.

3. 시계 부품 rotate, 텍스트 opacity

const kithRow = gsap.timeline({
  scrollTrigger:{
    trigger: ".sc-kith .product-inner",
    start: "top top",
    end: "100% 100%",
    scrub: 0,
  }
});
kithRow.to('.sc-kith .group-product .product-list', {
  x:0,
  xPercent:-100,
  ease: 'none',
});

textList = document.querySelectorAll('.sc-kith .group-product .text-item');

$('.sc-kith .group-product .product-item').each(function(i, el){

  // product clock
  const kithProd = gsap.timeline({
    scrollTrigger:{
      containerAnimation: kithRow,
      trigger: el,
      start: "left 100%",
      end: "right 0%",
      scrub: 0,
      // markers: true,
    },
  })
  kithProd
  .to(el.querySelector('.product-case'), {
    rotate: 360,
    duration: 12,
  }, 'prod')
  .to(el.querySelector('.product-hours'), {
    rotate: 360,
    duration: 4,
  }, 'prod')
  .to(el.querySelector('.product-minute'), {
    rotate: 360, 
    duration: 8, 
  }, 'prod')
  .to(el.querySelector('.product-second'), {
    rotate: 360, 
    duration: 12, 
  }, 'prod');

  // product info text
  const kithText = gsap.timeline({
    scrollTrigger:{
      containerAnimation: kithRow,
      trigger: el,
      start: "left 65%",
      end: "right 50%",
      scrub: 0,
      // markers: true,
    },
  })
  kithText
  .from(textList[i],{
    y: 30,
    opacity: 0
  })
  .to(textList[i],{
    y: 0,
    opacity: 1
  })
  .to(textList[i],{
    y: -30,
    opacity: 0
  })
});
  • 🌟 trigger: el로 설정하는게 포인트이다.
  • el은 시계라고 생각하면 된다.
  • 해당 시계 .product-item에 도달하면 시계의 부품들이 돌아가도록 설정했고,
  • 해당 시계 .product-item에 도달하면 .text-item 해당 시계의 정보 텍스트가 나오도록 했다.

4. 스크롤 방향에 따라 무한 슬라이드

slide2 = gsap.to('.sc-collabo .group-slide .slide-item', {
  duration: 10,
  xPercent: 100,
  ease: 'none',
   overwrite: 'all',
   paused:true,
  repeat: -1,
  onReverseComplete:function(){
    slide1.restart();
  }
});
slide1 = gsap.to('.sc-collabo .group-slide .slide-item', {
  duration: 10,
  xPercent: -100,
  ease: 'none',
   overwrite: 'all',
  repeat: -1,
  onReverseComplete:function(){
    slide2.restart();
  }
});

let up = false;
let firstLeftFlag = false;
let firstRightFlag = false;

ScrollTrigger.create({
trigger: '.area',
start: '0% 50%',
end: '100% 50%',
// markers:true,

onUpdate:function(self){

if(self.direction === 1 && firstLeftFlag === false){
if(slide1.isActive()){
  slide1.reverse();
}
else{
  slide2.play();
}

firstLeftFlag = true;
firstRightFlag = false;

}else if(self.direction === -1 && firstRightFlag === false){

if(slide2.isActive()){
  slide2.reverse();
}else{ 
  slide1.play();
}

firstLeftFlag = false;
firstRightFlag = true;
}

}
})
  • .sc-collabo .group-slide .slide-item 요소들이 왼쪽(slide1) 또는 오른쪽(slide2)으로 계속 이동하는 무한 슬라이드 애니메이션이다.
  • 기본은 marquee 슬라이드를 만들어두는 것이다.
  • ScrollTrigger는 .area 섹션을 감지하여, 스크롤 방향에 따라 슬라이드 애니메이션의 방향을 변경되도록 했다.
  • 아래로 스크롤할 때, slide1이 실행 중이면 역재생, slide2가 실행 중이면 재생되고,
  • 위로 스크롤할 때, slide2가 실행 중이면 역재생, slide1이 실행 중이면 재생되도록 했다.

🌟 Point

  • GSAP xPercent와 repeat: -1을 활용하여 슬라이드가 계속 반복되도록 설정했다.
  • ScrollTrigger의 onUpdate를 사용하여 스크롤 방향 감지 및 슬라이드 방향이 변경되도록 했다.
  • reverse()와 play()를 사용하여 자연스럽게 슬라이드 애니메이션 연결되도록 했다.

0개의 댓글