MONCOLONY

김종민·2023년 8월 31일
0

Portfolio

목록 보기
4/9
post-thumbnail
post-custom-banner

MONCOLONY 클론코딩


🔎 작업내용

  • 사이트명: MONCOLONY
  • 작업 기간: 3일
  • 유형: 반응형, GSAP, swiper, 클론 코딩
  • 특징: gsap을 이용한 스크롤트리거 활용, 웹/모바일 반응형 사이트, 세계시간 표시

새로고침 시 스크롤 상단이동

새로고침 시에 페이지의 상단으로 자동이동되어 페이지의 이벤트를 다시 구현하도록 한다.

이전 포트폴리오에서 사용했던 방법보다 더 간단하고 용이한 방법을 찾아 수정하였다!

before

window.onload = function(){

    setTimeout(function(){
      scrollTo(0,0)
    },100);
}

after

history.scrollRestoration = "manual"

더욱 짧고 작동 상에도 더 부드러워진 코드!



gsap 스크롤 트리거 정리

동일한 이벤트가 적용되는 요소를, 구역별로 하나하나 지정해서 이벤트를 넣는 것보다, each 반복문을 사용하여 하나로 묶어 돌리는게 더욱 깔끔하고 효과적이다!


같은 라인요소를 하나로 묶어주기

before

//sc-clients의 라인
gsap.set('.sc-clients .line, .sc-service .line', { width: 0 });

gsap.to('.sc-clients .line',3,{
    scrollTrigger:{
        trigger:'.sc-clients .text-group',
        start:"0% 80%",
        end:"100% 0%",
        // markers:true,
    },
    width:'100%',
    ease: "power4.out",
})

//sc-service의 라인
gsap.to('.sc-service .line',3,{
    scrollTrigger:{
        trigger:'.sc-service .text-group',
        start:"0% 80%",
        end:"100% 0%",
        // markers:true,
    },
    width:'100%',
    ease: "power4.out",
})

각각의 라인을 따로따로 불러서 이벤트를 지정했지만,

after

1️⃣
gsap.set('.sc-clients .line, .sc-service .line', { width: 0 });

$('.line').2️⃣each(function(3️⃣ i, el){
    gsap.to(3️⃣ el,3,{
        scrollTrigger:{
            trigger:el,
            start:"0% 80%",
            end:"100% 0%",
        },
        width:'100%',
        ease: "power4.out",
    })
})
  1. gsap.set으로 두 라인 클래스를 같이 묶어준 후 width값 셋팅

  2. .line을 each문으로 각각 반복문을 돌려준다.

  3. 매개변수 정의

  • i: 인덱스(index) 매개변수로서, 현재 요소가 반복문 내에서 몇 번째 요소인지를 나타냅니다. 인덱스는 0부터 시작하며, 첫 번째 요소의 인덱스는 0이 됩니다.

  • el: 요소(element) 매개변수로서, 현재 반복되는 요소 자체를 나타내며 $(this)와 같은 의미기도 하다. 이 경우에는 클래스가 "line"인 요소 중 하나가 됩니다.



웹 상에서 동일하게 작용하는 슬라이드 효과 묶어 처리하기

<!--html-->
<ul class="list">
	<li class="item">
		<a href="" ✅data-up="">
			<figure class="img-wrap" >
				<img src="https://www.datocms-assets.com/84325/1682701161-hearthstone_barrens_01.jpg?auto=format&dpr=1.5&fit=crop&fm=jpg&h=953&q=70&w=1395" alt="">
			</figure>
			<p class="title">Hearthstone Cinematic: Forged in the Barrens</p>
			<span class="subtitle">Blizzard Entertainment</span>
		</a>
	</li>
	<li class="item">
		<a href="" ✅data-up="">
			<figure class="img-wrap" >
				<img src="https://www.datocms-assets.com/84325/1675720505-hearthstone_sc_shot04_a_final.jpg?auto=format&dpr=2&fit=crop&fm=jpg&h=953&q=70&w=1395" alt="">
			</figure>
			<p class="title">Hearthstone Cinematic: Voyage to the Sunken City</p>
			<span class="subtitle">Blizzard Entertainment</span>
		</a>
	</li>
		/~~중략~~/

위치값을 받아서 아래에서 위로 올라오는 슬라이드 효과가 들어가야 하는 태그들에게 동일한 데이터 값인 data-up을 넣어준다. 따로 ""에 값은 넣어주지 않아도 되며,
필요시에 따로 넣어주면 된다!


<!--js-->
gsap.set('1️⃣[data-up]',{
    opacity:0,
    yPercent:100,
})
$('[data-up]').3️⃣each(function(i,el){
    gsap.to($(this),{
        scrollTrigger:{
            trigger:el,
            start:"0% 100%",
            end:"100% 0%",
            // markers:true,
        },
      2️⃣opacity:1,
        yPercent:0,
    })
})
  1. gsap.set으로 속성값인 data-up 요소들을 불러준다.
    ( 여기서 속성값은 [ ]를 사용해서 불러줄 수 있다!)

  2. gsap.to()의 변해줄 값을 설정해준다.

  3. 셋팅해 준 data-up을 each 반목문을 통하여 data-up을 돌려준다.


잠깐❗❗
여기서 star/end 속성값만 다른 'data-up'이 필요하다면!?


<!--html-->
<li class="item">
		<a href="" ✅data-up="-50% 100%">
			<figure class="img-wrap" >
				<img src="https://www.datocms-assets.com/84325/1682701161-hearthstone_barrens_01.jpg?auto=format&dpr=1.5&fit=crop&fm=jpg&h=953&q=70&w=1395" alt="">
			</figure>
			<p class="title">Hearthstone Cinematic: Forged in the Barrens</p>
			<span class="subtitle">Blizzard Entertainment</span>
		</a>
	</li>

이때는 다른 속성값을 줘야하는 태그의 data-up에 임의의 값을 넣어준다!

<!--js-->
gsap.set('[data-up]',{
    opacity:0,
    yPercent:100,
})
$('[data-up]').each(function(i,el){
 	1️⃣start = $(this).data('up');
  	2️⃣startVal =✨ (start)?start:"0% 80%"; ✨

    gsap.to($(this),{
        scrollTrigger:{
            trigger:el,
            start:3️⃣startVal,
            end:"100% 0%",
            // markers:true,
        },
      opacity:1,
        yPercent:0,
    })
})
  1. start라는 변수에 $(this), 즉 data-up을 가진 속성 중 내가 선택한 것!, 이것의 data-up을 넣어준다.

  2. startVal라는 변수에 삼항연산자를 사용하여 조건문을 넣어준다.

    ```
    if(start){   		//start가 맞다면~
    	start();  		//start인 $(this).data('up')가 그대로 실행되고
    } else { 			//start가 아니라면
    	"0% 80"			// "0% 80%"가 입력되도록 한다~ 
    }
    
    ```

    위와 같은 if문과 동일한 문장이다.

    startVal = (start) ? start : "0% 80%" ; 

    만약 start 변수가 존재한다면 (start 변수가 truthy한 경우),
    startVal 변수에 start 변수의 값을 할당합니다.
    그렇지 않은 경우에는 (start 변수가 falsy한 경우), startVal 변수에 "0% 80%" 값을 할당합니다.

  3. scrollTrigger의 start옵션에 이 조건문이 담긴 startVal를 넣어주어 상황별로 조건 값이 입력된다.


타임라인 사용 및 addLabel

아래와 같이 스크롤트리거를 사용, 어느 위치에 도달했을 때
양옆의 배경의 크기가 커져 커튼효과를 내도록 하였다.

1️⃣
gsap.set('.sc-commu .sidebg .leftbg', {width:'20vw'});
gsap.set('.sc-commu .sidebg .rightbg', {width:'20vw'});

✨sideBgTl = gsap.2️⃣timeline({
    scrollTrigger:{
        trigger:'.sc-commu',
        start:"0% 90%",
        end:"50% 80%",
        scrub:0,
    },
})
sideBgTl
4️⃣.addLabel('a')

3️⃣
.to('.sc-commu .sidebg .leftbg',{ width:'0vw', },5️⃣' a')
.to('.sc-commu .sidebg .rightbg',{ width:'0vw', },5️⃣ 'a')

❗❗ 주의 ❗❗
timeline 속성을 이용할 때는 꼭 변수를 할당해줘야 한다!!

  1. gsap.set()으로 기본값을 설정

  2. timeline을 사용한 스크롤트리거를 sideBgTl 변수에 할당.

  3. gsap.to()로 이동 후 값 설정

  4. .addLabel()을 사용, 값에 'a'를 넣어주어 라벨을 만들어 준다.

  5. 같이 묶어줄 .to()의 값에 만들어준 'a'라는 라벨을 달아주어 같은 제품으로 묶어준다.
    그렇다면 타임라인이지만 각기 움직이지않고 동시에 움직이게 된다.



세계 시간 구하기.

해당 국가의 시간을 나타나도록 하였고 am/pm으로 간편히 확인할 수 있도록 하였다.

// console.log('KST (한국 표준시):<br />',       getWorldTime(+9), '<br /><br />');
// console.log('PST (태평양 표준시):<br />',     getWorldTime(-8), '<br /><br />');
// console.log('PDT (태평양 표준시 DST):<br />', getWorldTime(-7), '<br /><br />');
// console.log('EST (뉴욕 시간):<br />',         getWorldTime(-5), '<br /><br />');
// console.log('EST (LA 시간):<br />',         getWorldTime(-7), '<br /><br />');
// console.log('EST (브라질 시간):<br />',         getWorldTime(+9), '<br /><br />');
// console.log('EDT (뉴욕 시간 DST):<br />',     getWorldTime(-4), '<br /><br />');
// console.log('CET (파리 시간):<br />',         getWorldTime(+1), '<br /><br />');
// console.log('CEST (파리 시간 DST):<br />',    getWorldTime(+2), '<br /><br />');
// console.log('CST (중국 표준시):<br />',       getWorldTime(+8), '<br /><br />');
// console.log('UTC (세계 표준시):<br />',       getWorldTime(0),  '<br /><br />');

1️⃣
getWorldTime(-7,'.us-time')
getWorldTime(+9,'.br-time')
getWorldTime(+1,'.uk-time')
getWorldTime(+8,'.ch-time')


function getWorldTime(tzOffset, frame) { // 24시간제
    var now = new Date();
    var tz = now.getTime() + (now.getTimezoneOffset() * 60000) + (tzOffset * 3600000);
    now.setTime(tz);
  
  	2️⃣
    var hours = now.getHours();
    var ampm = hours >= 12 ? 'PM' : 'AM';
    hours = hours % 12;
    hours = hours ? hours : 12; // 0시일 경우 12로 변경
    
    var s =
      leadingZeros(hours, 2) + ':' +
      leadingZeros(now.getMinutes(), 2) + ' ' + ampm;
  
    $(frame).html(s);
  }
  
  function leadingZeros(n, digits) {
    var zero = '';
    n = n.toString();
  
    if (n.length < digits) {
      for (i = 0; i < digits - n.length; i++)
        zero += '0';
    }
    return zero + n;
  }


  /**
   * 1초마다 업데이트
   */
   3️⃣
  setInterval(function() {
    getWorldTime(tzOffset, frameSelector); // tzOffset과 frameSelector는 필요한 값으로 대체해야 합니다.
  }, 1000);
  1. 각 나라별로 다른 클래스를 주어 시간차이를 주도록 함수에 기입

  2. 12를 기준으로 하여 am/pm 표현 하도록 설정

  3. setInterval로 1초마다 업데이트가 되어 시간이 흘러가는걸 체크하도록 설정


✅세계 시간 수정

각 국의 시간이 조금 맞지않아 시차를 수정하였고, 작업 도중 시간이 업데이트가 되지 않는 점을 확인해 다시금 수정하였습니다.

function getWorldTime(tzOffset, frame) {
    var now = new Date();
    var tz = now.getTime() + (now.getTimezoneOffset() * 60000) + (tzOffset * 3600000);
    now.setTime(tz);
  
    var hours = now.getHours();
    var ampm = hours >= 12 ? 'pm' : 'am';
    hours = hours % 12;
    hours = hours ? hours : 12;
  
    var s =
      leadingZeros(hours, 2) + ':' +
      leadingZeros(now.getMinutes(), 2) + ' ' + ampm;
  
    $(frame).html(s);
  }
  
  function leadingZeros(n, digits) {
    var zero = '';
    n = n.toString();
  
    if (n.length < digits) {
      for (var i = 0; i < digits - n.length; i++)
        zero += '0';
    }
    return zero + n;
  }
  
  /**
   * 1초마다 업데이트
   */
  setInterval(function () {
    var tzOffset = arguments[0]; // 필요한 값을 대체
    var frameSelector = arguments[1]; // 필요한 값을 대체
    var frameElement = document.querySelector(frameSelector);
    getWorldTime(tzOffset, frameElement);
  }.bind(null, -8, '.us-time'), 1000);
  
  setInterval(function () {
    var tzOffset = arguments[0]; // 필요한 값을 대체
    var frameSelector = arguments[1]; // 필요한 값을 대체
    var frameElement = document.querySelector(frameSelector);
    getWorldTime(tzOffset, frameElement);
  }.bind(null, -3, '.br-time'), 1000);
  
  setInterval(function () {
    var tzOffset = arguments[0]; // 필요한 값을 대체
    var frameSelector = arguments[1]; // 필요한 값을 대체
    var frameElement = document.querySelector(frameSelector);
    getWorldTime(tzOffset, frameElement);
  }.bind(null, 0, '.uk-time'), 1000);
  
  setInterval(function () {
    var tzOffset = arguments[0]; // 필요한 값을 대체
    var frameSelector = arguments[1]; // 필요한 값을 대체
    var frameElement = document.querySelector(frameSelector);
    getWorldTime(tzOffset, frameElement);
  }.bind(null, 8, '.ch-time'), 1000);
profile
웹 퍼블리셔의 코딩 일기
post-custom-banner

0개의 댓글