-
얼마나 자주 올릴지는 모르겠지만 갑자기 생각나서 쓰러왔당 ㅎㅎ
아무거나 쓰다 보면 기록하는 습관이 늘지 않을까 하고 ~ ~ ~
Three.js 프로젝트도 얼른 올리고 싶은데 차근차근.. 언젠간 올리겠지? ?
그래서 오늘 쓸 건 아이폰 새로 나온 기념으루다가
간단하게 연습해본 에어팟프로2 스크롤 기반 인터랙션이당
나중의 내가 지금 쓴 코드를 보면 어떤 생각이 들깝 ㅎㅎㅎ
내 에어팟 왼쪽 이상해서 교체받아야되는뎅 온제받지
아이폰 출시할 때 마다 느끼는 건데
나는 폰 욕심은 진짜 없는고같당
아직 XR 쓰는 중인데 너무 튼튼해 내 엑스알 최고
암텅 ~~
<section class="section01"> <article> <span class="same">완전히 새로운</span> <h2 class="text">AirPodsPro</h2> <p class="text">듣는다는 것을 다시 생각하다.</p> <div class="same"> <p>출시일은 추후 공개됩니다.</p> <ul> <li><a href="/">동영상 시청하기</a></li> <li><a href="/">이벤트 시청하기</a></li> </ul> </div> <figure> <img src="../img/airpod-sequence/0.png" alt="airpod img"> </figure> </article> </section> <section class="section02"></section> <section class="section03"></section>
우선 HTML은 대충 요렇게 ~!~!
연습용으로 후다닥 만들어서 지저분하지만..🙈
섹션당 높이는 100vh를 줬고
section01에는 300vh를 줬다! 스크롤 해야하니까 ~~
이제 나의 작고 귀여운 Javascript Time^ㅇ^
1. scrollY값 구하기
let scrollTop = 0; addEventListener('scroll', () => { // document.addEvent~ -> document 생략 scrollTop = scrollY; // window.scrollY -> window 생략 });
가장 먼저 스크롤값을 구해야겠찌 ? ? 당연함
2. 사용할 변수들과 애니메이션에 필요한 수치들을 객체에 정리
const sceneInfo = { objs : { // 인터랙션에 필요한 대상들! 클래스 모음집이라 생각하면 편함 section01_el : document.querySelector('.section01'), section01_title : document.querySelector('.section01 h2'), section01_txt : document.querySelector('.section01 p'), section01_eyebrow : document.querySelectorAll('.section01 .same'), section01_img : document.querySelector('.section01 img') }, values : { // 수치시작점, 수치끝점, {비율시작점, 비율끝점} titleScale : [1, 1.2, {start: 0, end: 0.7}], // 비율의 0부터 0.7까지 scale(1) -> scale(1.2)로 주겠다는 뜻 titleOpacity : [1, 0, {start: 0.3, end: 0.6}], textScale : [0.8, 1, {start: 0.65, end: 0.8}], textOpacityIn : [0, 1, {start: 0.65, end: 0.8}], textOpacityOut : [1, 0, {start: 0.8, end: 0.9}], eyebrowOpacity : [1, 0 , {start: 0.18, end: 0.4}], imgCount : [0, 29, {start: 0, end: 0.8}], imgScale : [1, 5, {start: 0, end: 0.8}], imgTranslateY : [20, 100, {start: 0, end: 0.8}], }, };
이건 따로 설명할 게 없당
구냥 말 그대로 여러가지 정보들을 담아 놓는 곳~! 찾기 편하게용
음.. 책에 필요한 부분 마다 라벨 붙여 놓은 너낌..?
3. 스타일 주는 함수 만들고 섹션 scrollY와 비율 구하기
let scrollTop = 0; addEventListener('scroll', () => { // document.addEvent~ -> document 생략 scrollTop = scrollY; // window.scrollY -> window 생략 addStyle(scrollTop) // 스크롤 이벤트 함수에서 구한 scrollY값을 style함수에 인자로 넘겨줌 }); const objs = sceneInfo.objs; // 객체에서 가져올 건데 길게 쓰기 귀찮으니까 변수에 담아줌 const values = sceneInfo.values; let sectionScrollY, sectionScrollRatio; function addStyle(scroll){ // 인자로 받은 scrollY를 style함수에선 scroll이라 부를고임 sectionScrollY = Math.max(0, (scroll - objs.section01_el.offsetTop)); sectionScrollRatio = Math.min(1, (sectionScrollY / (objs.section01_el.offsetHeight - innerHeight))); };
왜 Math.max를 썼냐면!!
우선 지금 내가 만드는 구간은 첫 섹션인 section01이기 때문에 scrollY 또한 0에서 시작하지만
예시로 높이가 100px인 section들 중 두 번째인 section02의 scrollY를 구해보잡
sectionScrollY = scroll - section02.offsetTop을 하게 되면??
sectionScrollY의 값은 -100 부터 시작하다 section02의 offsetTop에 닿는 순간 부터 0이 되겠징?
좌: 최댓값 0 설정 안 한 예시 속 section02의 scrollY / 우: 최솟값 1 설정 안 한 ratio 내가 필요한 건
1. 인터랙션을 줄 섹션의 scrollY를 0으로 만들어주기
2. 그 섹션의 스크롤 비율(0 ~ 1) 구하기 ~! 별표★
때문에 0 이하의 숫자는 버리는 것
마찬가지로 Ratio도!! 스크롤을 계속 내리면
아래에 더 있는 섹션들 만큼 ratio 수치가 쭉쭉 올라갈테니까 최대치를 1로 잡아준 것이당~~
4. 스타일 함수에 스타일 넣어주기(?)
function addStyle(scroll){ sectionScrollY = Math.max(0, (scroll - objs.section01_el.offsetTop)); sectionScrollRatio = Math.min(1, (sectionScrollY / (objs.section01_el.offsetHeight - innerHeight))); if(sectionScrollRatio < values.titleScale[2].end + 0.02){ objs.section01_title.style.transform = `scale(${calcValue(sectionScrollY, values.titleScale, objs.section01_el)})` } };
코드 길어지면 괜히 읽기 싫어지니까 ㅎㅎ~~ 우선 하나만 줘보장
sectionScrollRatio는 0~1 이니까! 요게
객체에 내가 미리 넣어둔 titleScale의 end 즉 0.7 보다 작을 때 까지만 스타일을 바꾸라는 말!
뒤에 + 0.02는 뭐냐면 마우스 휠을 굴릴 때 ratio를
0.00001, 0.00002, 0.00003 이렇게 정확!!하게 잡아주지 않기 때문에
오차범위(?)를 안전빵으로 넣어준 것이당~ 0.02 정도 넣어주면 대충 잘 잡힌다 ㅎㅎ
헉 근데 scale()안에 숫자가 아니라 calcValue() 함수가 들어있다! !!
세 개의 인자도 가지고 있지롱
요게 뭐냐면 ~ ~ ~
5. 범위 자동 계산 함수 만들기
let start, end, range, rangeY, rangeRatio; function calcValue(scroll, value, el){ start = (el.offsetHeight - innerHeight) * value[2].start; // 인터랙션 시작점 end = (el.offsetHeight - innerHeight) * value[2].end; // 인터랙션 끝점 range = end - start; //애니메이션범위 rangeY = Math.max(0, (scroll - start)); // 범위의 스크롤Y rangeRatio = Math.min(1, (rangeY / range)); // 범위의 비율 styleVal = rangeRatio * (value[1] - value[0]) + value[0]; // 스타일값 return styleVal; };
어떻게 설명을 쓰지?? 움. .. 예를 들어서
스크롤이 AirPodsPro 구간에 닿을 때 인터랙션을 주기 위해선
해당 구간의 scrollY랑 ratio를 또 구해야겠지!?
높이가 100px인 element에 시작점 0.2를 곱하면~?~? 또, 끝점 0.3을 곱하면 ~??
start = 20px, end = 30px 짜잔 ~~
아까 위에선 offsetTop으로 구했던 방식이
element에 비율을 곱하는 방식으로 조금 달라졌을 뿐 같은 공식이당
styleVal은 내가 부여하는 스타일 값 그대로를 계산한 건데
매개변수로 받아와서 계산한 스타일값을
리턴해줘야 하니까 선언해준 것이당 ~~
자판기에 동전 넣으면 음료수 나오자나?
calcValue()에 scroll, value, el 넣었더니 styleVal 나온겨 ~~ 와아
calcValue 함수 없이도 직접 계산식을 쓰면서
노가다로 수치를 넣어줄 순 있지만
그러면 코드도 길어지고 귀찮자낭
알아서 계산해주는 착한 calcValue() ^ㅇ^
objs.section01_title.style.transform = `scale(${calcValue(sectionScrollY, values.titleScale, objs.section01_el)})`
그럼 다시 이 부분을 보며 calcValue가 어떻게 쓰였나 ~~ 생각해보깅 ㅎㅇㅎ
이러면 끝이다! 스크롤 수치에 맞춰 스타일 수치 주기 끝!
근데 만약 scale이 0.4 ~ 0.8 구간 동안 커지기만 하는데
같은 구간 동안에 opacity가 0에서 1됐다가 다시 0이 되길 원한다면 !?
if(sectionScrollY < values.opacityIn_02[2].end + 0.02){ objs.overview02_txt[1].style.opacity = `${calcValue2(currentPageScrollVal, values.opacityIn_02, objs.overview02_el)}` }else{ objs.overview02_txt[1].style.opacity = `${calcValue2(currentPageScrollVal, values.opacityOut_02, objs.overview02_el)}` }
간단함ㅋ else로 주면 된당ㅎㅎ
하지만 sceneInfo에서 수치를 잘 맞춰줘야게찌 ??
6. 마지막으로 초간단 이미지 시퀀스
if(sectionScrollY < values.imgScale[2].end + 0.02){ objs.section01_img.style.transform = `translateY(-${calcValue(sectionScrollY, values.imgTranslateY, objs.section01_el)}%) scale(${calcValue(sectionScrollY, values.imgScale, objs.section01_el)})` objs.section01_img.src = `../img/airpod-sequence/${Math.floor(calcValue(sectionScrollY, values.imgCount, objs.section01_el))}.png` }
여러장의 이미지를 스크롤에 맞춰 보여주며
애니메이션 처럼 보이게 하는 기법~!
나는 총 30장의 이미지라 imgCount = 30이라고 주었당
스타일 주는 것 처럼 src에 넣어주면 끝!
정수로 떨어져야 하니까 Math.floor 주는 거 잊지말기 ~~
완성작 ^_^ ㅋㅋㅋㅋㅋㅋㅋㅋ
ㅋ ㅋㅋㅋ ㅋㅋㅋ ㅋㅋㅋㅋ 아
수치도 대강 때려 맞춰서 넣고.. 느낌대로 한거라
영 볼품없지만은 ㅎㅎ ㅋㅋ ㅋ ㅋㅋㅋ
이게 지금 나의 최선이어따..
난 이것도 만족해!! 앞으로 경험치 쌓고 레벨업하면 되찌~!!!!
내 눈엔 이것도 나름 예뿌다 히 히
우와 근데 맨날 일기나 써봤지 이런 건 처음 써봐서 그른가??
짱어렵다 !!! 설명글 쓰는 건 되게 어려운 거구나! !!
설명이 아주 많이 생략된 누낌 ^ㅇ^
쓸데 없는 설명은 또 많은 누낌 ^ㅇ^
딱 한 섹션만 한 건데두... ㅎㅎ 어렵따
그래도 다음 섹션은 간단하니까 짧게 쓸 수 있을거같당~~
언제 또 쓰러올지가 의문이지만 히히
지금은 반복되는 코드도 많고 잘 정리가 안되어있어서
코드를 왔다갔다 하면서 봐야되는데
다다음 글이나 다다다음 글 쯤에선
더 정리가 잘 된 함수로 다른 섹션 정리글 쓰지 않을까 싶네욤 ~ ~
아 일기도 쓰고싶당 할 말 짱 많은데 ㅜㅇㅜ
잊기 싫은 것만 간단하게 캘린더에 쓰고이따 호호
근데 왜 아직도 월요일? 얼룬 토요일 됐으면 좋겠당~~~ 두근두근
'🦄' 카테고리의 다른 글
카메라 가지고 놀기 1탄 (6) 2022.10.04 벌써 10월 (0) 2022.10.01 🔗 (0) 2022.09.22 댓글