사이트명 : MMCA 국립현대미술관 (반응형, Renewal)
작업 기간 : 23.03.13 ~ 23.03.16 (4일 소요)
사용언어: HTML, CSS, Jquery, Gsap, JS
유형 : 반응형, 리뉴얼
특징 : gsap를 활용해 다양한 스크롤 이벤트를 구현한 동적인 페이지입니다.
📋 첫 로드시에 Header 메뉴가 부드럽게 나타나고, 왼쪽 영역의 텍스트들과 오른쪽 영역에서의 도형들이 부드럽게 나타나는 모션을 구현하였습니다 .
CSS에서 도형요소마다 다른 위치와 크기를 설정해 주었습니다.
$(function(){
// header, main visual motion
introMotion = gsap.timeline({})
introMotion
.addLabel('a')
.from('.header .inner',{ y: -30, opacity : 1, },'a')
.from('.sc-hero .sub-tit, .sc-hero .btn-wrap',{ x: -170 },'a')
.from('.sc-hero .tit01, .sc-hero .tit04',{ x: 100 },'a')
.from('.sc-hero .elem08',{ height:0 },'a')
.from('.sc-hero .elem04, .sc-hero .elem10, .sc-hero .elem12',{ scale:0 },'a')
.from('.sc-hero .circle01.top, .sc-hero .circle01.btm',{ rotateZ: 180 },'a')
.from('.sc-hero .hero-elem.elem02, .sc-hero .elem13',{ y:-100 },'a')
.from(' .sc-hero .elem14',{ width : 0 },'a')
.from('.sc-hero .elem07 .circle-pink-top',{ rotateZ: -180 },'a')
.from('.sc-hero .circle-right',{ rotateZ: -180 },'a')
.to('.sc-hero .elements-area .elem03',{ x : 0, opacity : 1,},'a')
.to('.sc-hero .elements-area .elem05',{
y : 0,
opacity : 1,
},'a')
.to('.sc-hero .elements-area .dot-square',{
scale3d :0,
opacity : 1,
},'a')
gsap.from
타겟의 시작점에서 애니메이션 실행
gsap.to
타겟의 끝점으로 애니메이션 실행addlabel
: 동시에 효과를 주기 위해 라벨링.from('.header .inner',{ y: -30, opacity : 1, },'a')
헤더메뉴들은 위에서 나타나도록 구현.from('.sc-hero .sub-tit, .sc-hero .btn-wrap',{ x: -170 },'a')
hero영역의 텍스트들은 각각 왼쪽과 오른쪽에서 나타나도록 구현.from('.sc-hero .elem04, .sc-hero .elem10, .sc-hero .elem12',{ scale:0 },'a')
점 모양의 도형들은 스케일로 사라졌다가 나타나게 조절.from('.sc-hero .circle01.top, .sc-hero .circle01.btm',{ rotateZ: 180 },'a')
돌아가며 채워지는 도형들은 rotate로 조절.from('.sc-hero .hero-elem.elem02, .sc-hero .elem13',{ y:-100 },'a')
조각상들은 y축을 이용해 위에서 아래로 나타나게끔 조절
📋 화면을 스크롤 하면 각각의 섹션마다 텍스트들과 도형들이 화면을 채우는 모션을 구현해 보았습니다.
// sc-visit
scVisit = gsap.timeline({
scrollTrigger:{
trigger:".sc-visit",
start:"0% 60%",
end:"100% 0%",
},
})
scVisit
.to('.sc-visit .tit-visit',{
x: 0, opacity : 1,
})
.to('.sc-visit .card-list > *',{
y: 0, opacity :1 ,
stagger:0.1
})
// sc-digital
scDigital = gsap.timeline({
scrollTrigger:{
trigger:".sc-digital",
start:"0% 80%",
end : "100% 0%",
scrub : 1
},
})
scDigital
.addLabel('a')
.to('.sc-digital .illustr-area img',{ scale : 1 },'a')
.to('.sc-digital .border-area',{ opacity : 1, },'a')
.to('.sc-digital .desc-wrap',{ x : 0, opacity : 1, },'a')
.to('.sc-digital .tit-wrap .tit01, .sc-digital .tit-wrap .tit02, .sc-digital .tit-wrap .tit03',{ x : 0, opacity : 1, },'a')
// Audio
scAudio = gsap.timeline({
scrollTrigger:{
trigger:".sc-audio",
start:"0% 70%",
end : "100% 0%",
},
})
scAudio
.addLabel('a')
.to('.sc-audio .group-tit > * ',{
x : 0,
opacity : 1
},'a')
.to('.sc-audio .audio-list > *',{
y : 0,
opacity : 1,
stagger : 0.1,
},'a')
audioBtm = gsap.timeline({
scrollTrigger:{
trigger:".sc-audio",
start:"50% 40%",
end : "100% 0%",
},
})
audioBtm
.to('.sc-audio .group-more',{
y : 0,
opacity : 1,
})
})
// footer
footerMotion = gsap.timeline({
scrollTrigger:{
trigger:".footer",
start:"0% 70%",
end : "100% 100%",
scrub : 1
},
})
footerMotion
.addLabel('a')
.to('.footer .flex-area > * ',{
y : 0,
opacity : 1,
},'a')
.to('.footer .group-elements .elem01, .footer .group-elements .elem02, .footer .group-elements .elem03',{
x : 0, y:0, z:0,
opacity : 1,
},'a')
.from('.footer .footer-elem01',{
rotateZ: 180,
},'a')
gsap.timeline
gsap를 한꺼번에 묶어 순차적으로 실행하는 메서드
이때addLabel
메서드도 함께 추가하여 사용해서 스크롤을 내리면 동시에 모션이 작동하게 끔 구현하였습니다.scDigital
영역은scrub
을 이용해 스크롤을 위아래로 올리거나 내릴때마다 나타났다가 사라지는 모션을 주었습니다.
📋 Sign-up 버튼이나 Trial 버튼 등 클릭시 Supscribe 모달창이 나오도록 클릭 이벤트를 이용해 구현하였습니다.
// modal
$('.modal').click(function(e){
e.preventDefault();
$('.sc-modal').addClass('on');
$('body').addClass('hidden');
})
$('.sc-modal .btn-close, .sc-modal .bg-area').click(function(e){
e.preventDefault();
$('.sc-modal').removeClass('on');
$('body').removeClass('hidden');
})
📋 화면이 줄여졌을 때, 햄버거 버튼 클릭시 나오는 아코디언 메뉴을 구현
메뉴 클릭시에 해당 요소 위치로 돌아가게끔 구현
<div class="accodian-menu">
<div class="inner">
<button type="button" class="btn-close">
<span class="blind">닫기</span>
</button>
<nav class="gnb-area">
<a data-type="hero" class="btn-link underline">
VIRTUAL MUSEUM<i class="btn-link arrow-hover"></i>
</a>
<a data-type="visit" class="btn-link underline">
visit<i class="arrow-hover"></i>
</a>
<a data-type="hero" class="btn-link underline">
digital MUSEUM<i class="arrow-hover"></i>
</a>
<a data-type="audio" class="btn-link underline">
exhibition<i class="arrow-hover"></i>
</a>
</nav>
<div class="group-right">
<a href="" class="login modal underline" role="button">login</a>
<a href="" class="btn modal" role="button">sign up</a>
</div>
</div>
</div>
$('.accodian-menu .gnb-area a').click(function(e){
e.preventDefault();
$('.accodian-menu, .accodian-menu .btn-close').removeClass('on');
$('.header .btn-hamburger').removeClass('off');
$('body').removeClass('hidden');
type=$(this).data('type');
sec_top = $('.sc-'+type).offset().top;
// console.log(sec_top);
$('html,body').animate({scrollTop:sec_top}, 300);
})
- html
자바스크립트에서 쓰일 변수설정에서 data를 이어주기 위해section class
의 name을 보고 각각에 해당하는 data-type 입력
ex)a data-type="hero"
- javascript
type=$(this).data('type');
메뉴 클릭시 아코디언메뉴 창이 닫히고this
(내가 선택한 링크메뉴) 를 통해 data type 지정sec_top = $('.sc-'+type).offset().top;
section의 탑 위치 변수설정console.log(sec_top);
콘솔로 위치가 잘 잡혀여 있는 지 확인$('html,body').animate({scrollTop:sec_top}, 300);
:animate
메서드를 이용하여 0.3초 동안 특정 요소의 위치로 이동하도록 구현
<div class="subscribe-wrap">
<p class="intro">MMCA 뉴스레터 구독 신청 </p>
<form action="" method="get">
<fieldset>
<legend class="blind">e-mail</legend>
<div class="wrap">
<input type="email" placeholder="E-MAIL" required>
</div>
<button type="submit" class="btn checked" aria-label="전송">
<i class="footer-checked"></i>
</button>
</fieldset>
</form>
</div>
- form 태그 에서 양식을 기입하여 버튼 클릭시 전송하기 때문에
button type="submit"
입력aria-label
은 버튼 안의 모든 텍스트 콘텐츠를 재정의하므로 '전송' 버튼이라 칭하였고 스크린 리더를 사용하는 모든 사람에게 작업을 명확하게 설명할 수 있습니다.
📋 미디어쿼리를 통해 화면의 사이즈마다 맞는 레이아웃으로 구현해주었습니다.
화면 사이즈는 아래와 같이 3가지 기준으로 잡았습니다.
레이아웃 잡을 때는 각 화면의 최소기준을 보고 진행하였습니다.
@media screen and (max-width: 1280px) {}
@media screen and (max-width: 1024px) {}
@media screen and (max-width: 767px) {}
@media screen and (max-width: 480px){}