[ KakaoBank-gsap / 클론코딩 ]
- 사용 기술
- HTML5
- SCSS/ CSS
- javascript
- 주요 라이브러리
- Swiper - 슬라이더 라이브러리
- Font Awesome - icon
- [Gsap](https://greensock.com/gsap/) - 애니메이션 라이브러리
GSAP 이란?
GSAP는 GrennSock에서 만든 타임라인 기반의 자바스크립트 애니메이션 라이브러리이다.
CSS와 바닐라 자바스크립트만으로도 동적인 화면을 만들 수 있지만 GSAP은 세밀한 움직임과 동작의 연속성을 훨씬 간편하게 설정할 수 있다.
GSAP의 Tween을 만드는 방법 ( 기본 메서드)
- gsap.to()
- gsap.from()
- gsap.fromTo()
간단한 애니메이션(의 경우 위의 방법만 알면 쉽게 사용이 가능하다.
// 1초 동안 "box" 클래스("x"는 translateX() 변환의 단축키)로 요소를 회전하고 이동합니다.
gsap.to(".box", {rotation: 27, x: 100, duration: 1});
See the Pen GSAP Basic Tween by GreenSock (@GreenSock) on CodePen.
gsap의 장점 중 하나는 , 애니메이션을 적용 시킬 DOM 요소를 첫번째 인자로 querySelector 처럼 넣어주기만 하면 적용이 가능하다는 점이다. ( 중복 되는 곳에 전부 적용이 가능 )
두번째 인자로 옵션값들을 담은 객체를 전달한다. 편의성에 특화된 라이브러리이기 때문에 사용 방법이 꽤 직관적이어서 애니메이션 적용 자체는 어렵지 않다.
세번째 인자는 적용 순서 or 적용 방향에 대해 설정이 가능하다. 0 , 1 , 2 등 순번을 줄 수 도 있고
“<” 전에 적용 하는 애니메이션이 끝난 후 바로 사용 처럼 방향을 정해서 적용이 가능하다.
to() 메서드타겟을 옵션 값으로 변경 from() 메서드타겟을 옵션 값에서 변경 fromTo() 메서드타겟을 어디서부터 어디로 변경 의 의미를 가지고 있는 gsap 의 기본 메서드이다.
Scroll 기반 애니메이션 플러그인 ( ScrollTrigger )
쉬운 설정으로 스크롤 기반의 애니메이션 및 스크롤 관련 트리거 역할을 대신 해주는 플러그인이다.
특정 요소에 애니메이션을 연결 하면 해당 요소가 뷰포트에 있을 때만 재생된다.
- 쉬운 방법
gsap.to(".box", {
scrollTrigger: ".box", // .box 가 viewport에 들어왔을 경우 해당 애니메이션 한번실행
x: 500
});
심화 방법
See the Pen GSAP Starter Pen by GreenSock (@GreenSock) on CodePen.
커스텀 방법(가장 일반적인 사용 사례일 수 있음)callback 으로 사용 하거나 값을 반환 할 수도 있다.
애니메이션에 직접 넣는 방식이 아닌 ScrollTrigger의 기능으로 사용이 가능하다.
gsap.to(".box", {
scrollTrigger: ".box", // .box 가 viewport에 들어왔을 경우 해당 애니메이션 한번실행
x: 500
});
Interactive WEB Design
‘상호간’ 이라는 뜻을 지닌 Inter- 와 ‘활동적’ 이라는 뜻을 지닌 Active 의 합성어로, Interactive 디자인이란, 사용자와 상호작용을 하는 텍스트 혹은 그래픽 사용자의 인터페이스를 디자인을 하는 것으로, 사용자의 직접 참여 및 리액션을 필요로 하는 디자인이다.
단면적인 디자인이 아닌 입체적으로 보다 더 사용자에게 볼거리 및 흥미를 유도 시키게 하는 게 목적으로, 대표적인 디자인 사례로는 애플(Apple) 의 홈페이지가 있다.
스크롤을 이용하여 동적인 움직임으로 홈페이지에 입체적인 시각 효과를 아주 잘 사용하고 나타내고 있다.
클론코딩을 하는 이유
회사에서 사용 가능성이 높은 기술 및 라이브러리 이기 때문에, 인터랙티브에 대한 준비도 해야 했고,
[원본 홈페이지] 의 페이지를 보면 index 및 css 등의 소스가 그대로 노출이 되어 인터랙티브 디자인의 css 및 javascript 의 학습을 하기 위해서 아주 적합하다고 판단하였다.
해당 페이지의 전체적인 디테일을 잡을 순 없더라도 JQuery로 구현되어 있는 원본 사이트에 대한 부분을 Vanilla JS 로 변경 하기 위함도 있었다.
- html
- 마크업은 단일 페이지 구성으로 크게는 main footer, 작게는 main 속 요소들을 section 으로 나눠 진행했다.
- scss
- styles css는 scss로 진행했고, 공통적으로 들어갈 css는 common.scss , 반응형 작업을 하기 위해 mixin.scss , color 값이든 한번에 변경이 가능하도록 변수를 담은 variables.scss 로 나눠 진행했다. ****
- javascript
- 주로 다룬 기능은 gsap의 tween , timeline , scrolltrigger 다.
[ tween , timeline ]
처음 홈페이지가 사용자에게 렌더링이 되었을 때, 나타나는 효과 구현이다.
tween 의 from() , fromTo() 를 사용하여, 현재 위치를 동적으로 변하도록 애니메이션을 설정했다.
let tl = gsap.timeline();
gsap.registerPlugin(ScrollTrigger);
tl.fromTo('.oh', {
scale: 3, // 크기
opacity: 0, // 투명도
}, {
scale: 1, // 크기
opacity: 1, // 투명도
duration: 1, // 지속시간
ease: 'expo.inout', // 애니메이션 부드러움정도? https://greensock.com/docs/v3/Eases
//stagger - 시차
}, 0)
.from('.logo-box', { // logo
opacity: 0, y: -50, ease: 'expo.inout', duration: 1.1
}, "-=1")
.from('.friends', {
opacity: 0, y: 50, ease: 'expo.inout'
}, "-=1")
.from('.main_wrap .inner > ul > li:nth-child(3),' +
' .main_wrap .inner > ul >li:nth-child(4)', {
opacity: 0, y: 50, ease: 'expo.inout', duration: 1.1
}, "-=1")
[ scrollTrigger ]
스크롤 시 메인 화면에서 진행 되는 기능 구현이다.
한 화면에서 스크롤 이벤트를 이용하여 화면 전환이 되게 하는 기능을 사용함에 있어서
한번에 동적으로 구현 되어야 할 부분을 전부 position : fixed 를 하여 한번에 겹쳐서 스크롤 시 opacity 조절로 변경 되어 나타나게 하는 방법으로 조절 하기로 했다.
//scrollTrigger
gsap.timeline({
immediateRender: false, // 즉시렌더링
scrollTrigger: {
trigger: ".main_wrap", // 실행 될 트리거
endTrigger: '.main_wrap', // 끝날 트리거
start: 'top 0%', // 시작 지점
end: 'bottom 0%', // 끝나는 지점
scrub: 2, // 스크롤 2만큼 부드럽게.
}
}).set(".oh", {scale: 1}) // 초기화
.set('.main_wrap .inner > ul > li:nth-child(3),' +
' .main_wrap .inner > ul >li:nth-child(4)', {y: 0, opacity: 1}) // 초기화
.to(".oh", {scale: 3,}, "<") // "<" 애니메이션 실행 순서
.to('.main_wrap .inner > ul > li:nth-child(3),' +
' .main_wrap .inner > ul >li:nth-child(4)', {y: -50, opacity: 0}, "<")
.to('.Surprise', {y: -50, opacity: 1}, "<")
.to('.ryan', {y: -200, x: -150, scale: 2, opacity: 1}, "<")
.to('.chun', {y: 320, x: 150, scale: 2, opacity: 1}, "<")
.to('.main_wrap', {scale: 2, opacity: 0, display: 'none'}, "<=1")
.to('.block', {delay:0.5 ,opacity: 0}, "<")
.to('.mask', {scale: 5}, "<=1")
.to('.down_arrow', {opacity: 0}, "<")
.to('.mask', {opacity: 0}, "<")
.to('.activeBg', {opacity: 1}, "<")
.to('.cute_chun', {y: -50, opacity: 1, duration: 2}, "<")
[메인 스크롤 끝난 후 포지션 조절]
메인 스크롤이 끝났을 지점을 트리거로 지정해, 포지션과 위치를 조절하여 자연스럽게 내려가지도록 설정했다. scrollTrigger의 기능 중에는 여러 callback 함수가 내장 되어 있다. toggle 이벤트를 사용 했다.
gsap.timeline({ // 포지션 조절
scrollTrigger: {
trigger: ".videos",
start: 'bottom 0% += 300px',
endTrigger: '.quizInfo',
scrub: 2,
onToggle: (e) => PositionEvent(e),
}
})
const PositionEvent = (e) => {
const logo = document.querySelector('.logo');
const videos = document.querySelector('.videos');
const arr = [videos, logo];
arr.map((i, v) => {
(!e.isActive) ? (i.style.cssText = 'top:0; position:fixed') :
(i.style.cssText = `top:100%; position:absolute `)
});
}
[ NavBar 생성 ]
포지션을 조절하고 나온 페이지의 시작 부분에는 navbar가 나타나게 되는데 해당 navbar 의 기능을 구현했다. quizInfo가 시작하는 지점이 되기 5% 전에 navAction이 기능하도록 설정하여 display 를 관리했다. 그리고 전체 길이 스크롤 % 를 구해 위치 만큼의 값을 “on” 이라는 class를 넣어주며 현재 위치를 표시했다.
gsap.timeline({
scrollTrigger: {
trigger: ".quizInfo",
start: 'top 5% ',
endTrigger: '.footer',
scrub: 2,
onToggle: (self) => navAction(self),
}
})
const navAction = (self) => {
const nav = document.getElementsByTagName('nav')[0];
(!self.isActive) ? (nav.style.cssText = 'display: none') :
(nav.style.cssText = 'display: block');
}
/* 스크롤 시 */
console.log(document.getElementsByTagName('main')[0].offsetHeight)
console.log(document.body.offsetHeight + window.innerHeight)
window.addEventListener('scroll', () => {
let scrollTop = window.scrollY;
// console.log(document.getElementsByTagName('main')[0].scrollHeight )
let per = Math.ceil(scrollTop / (document.body.scrollHeight - window.outerHeight) * 100);
if (64 <= per && per < 65) {
quiz.classList.add('on')
gift.classList.remove('on')
limited.classList.remove('on')
} else if (65 <= per && per < 83) {
quiz.classList.remove('on')
gift.classList.add('on')
limited.classList.remove('on')
} else if (per >= 90) {
quiz.classList.remove('on')
gift.classList.remove('on')
limited.classList.add('on')
}
});
[ Button Modal ]
//toggleButton
toggleBtn.addEventListener('click', () => {
let icon = document.querySelector('.toggleBtn > span ')
let detail = document.querySelector('.detail ')
icon.classList.toggle('on');
detail.classList.toggle('on');
})
//modal
button.forEach((v) => {
v.addEventListener('click', () => {
modalWrap.style.display = 'flex'
})
})
modalWrap.addEventListener('click', (e) => {
modalWrap.style.display = 'none';
})
문제점 ( 변경 사항 Study 예정 사항 )
- 매끄럽지 못한 scroll 애니메이션 ( 대안 ScrollMagic GSAP(TweenMax) 으로 적용 예정 )
- 반응형 구현 X ( 추후 React 구현 시 적용 )
작성 - 22. 08. 05
'STUDY > LIBRARY' 카테고리의 다른 글
[Swiper] 스와이퍼 이벤트 리스트 정리 (0) | 2023.05.10 |
---|---|
타입 ORM (Type ORM ,Object Relational Mapping) (0) | 2023.01.03 |
[library] Swiper.js 편하게 슬라이드 캐러셀 구현하기 (0) | 2022.11.25 |
댓글