선생님 질문이 있습니다.
159
작성한 질문수 37
/**
*ECMA6 SCRIPT STUDY
*/
//const arr=[1,2,3];
//바람직한 패턴이 아닙니다.
(()=>{
//const arr=[1,2,3]; //지역변수로 선언하고 코딩하는 것을 제안.
const sceneInfo=[
{
type:'sticky',
//0
heightNum:5, //브라우저 높이의 5배로 scrollheight 세팅.
scrollHeight:0, //문서길이에 대해서 섹션의 애니메이션 구간을 미리 설정합니다.
//일단 0이라고 설정한 부부은 기기마다 값이 달라질 수 있기 때문에
//스크롤 높이의 몇배수 만큼 설정을 해주려고 합니다.
objs:{
container: document.querySelector('#scroll-section-0'),
messageA: document.querySelector('#scroll-section-0 .main-message.a'),
messageB: document.querySelector('#scroll-section-0 .main-message.b'),
messageC: document.querySelector('#scroll-section-0 .main-message.c'),
messageD: document.querySelector('#scroll-section-0 .main-message.d'),
},
values:{
messageA_opacity_in: [0, 1, { start: 0.1, end: 0.2 }],
messageB_opacity_in: [0, 1, { start: 0.3, end: 0.4 }],
messageC_opacity_in: [0, 1, { start: 0.5, end: 0.6 }],
messageD_opacity_in: [0, 1, { start: 0.7, end: 0.8 }],
messageA_translateY_in: [20, 0, { start: 0.1, end: 0.2 }],
messageB_translateY_in: [20, 0, { start: 0.3, end: 0.4 }],
messageC_translateY_in: [20, 0, { start: 0.5, end: 0.6 }],
messageD_translateY_in: [20, 0, { start: 0.7, end: 0.8 }],
messageA_opacity_out: [1, 0, { start: 0.25, end: 0.3 }],
messageB_opacity_out: [1, 0, { start: 0.45, end: 0.5 }],
messageC_opacity_out: [1, 0, { start: 0.65, end: 0.7 }],
messageD_opacity_out: [1, 0, { start: 0.85, end: 0.9 }],
messageA_translateY_out: [0, -20, { start: 0.25, end: 0.3 }],
messageB_translateY_out: [0, -20, { start: 0.45, end: 0.5 }],
messageC_translateY_out: [0, -20, { start: 0.65, end: 0.7 }],
messageD_translateY_out: [0, -20, { start: 0.85, end: 0.9 }]
}
},
//각구간을 4개로 나눴습니다.
{
//1
type:'normal',
heightNum:5,
scrollHeight:0,
objs:{
container: document.querySelector('#scroll-section-1')
}
},
{
type:'sticky',
//2
scrollHeight:0,
objs:{
container: document.querySelector('#scroll-section-2'),
messageA: document.querySelector('#scroll-section-2 .a'),
messageB: document.querySelector('#scroll-section-2 .b'),
messageC: document.querySelector('#scroll-section-2 .c'),
pinB: document.querySelector('#scroll-section-2 .b .pin'),
pinC: document.querySelector('#scroll-section-2 .c .pin')
},
values: {
messageA_translateY_in: [20, 0, { start: 0.15, end: 0.2 }],
messageB_translateY_in: [30, 0, { start: 0.6, end: 0.65 }],
messageC_translateY_in: [30, 0, { start: 0.87, end: 0.92 }],
messageA_opacity_in: [0, 1, { start: 0.25, end: 0.3 }],
messageB_opacity_in: [0, 1, { start: 0.6, end: 0.65 }],
messageC_opacity_in: [0, 1, { start: 0.87, end: 0.92 }],
messageA_translateY_out: [0, -20, { start: 0.4, end: 0.45 }],
messageB_translateY_out: [0, -20, { start: 0.68, end: 0.73 }],
messageC_translateY_out: [0, -20, { start: 0.95, end: 1 }],
messageA_opacity_out: [1, 0, { start: 0.4, end: 0.45 }],
messageB_opacity_out: [1, 0, { start: 0.68, end: 0.73 }],
messageC_opacity_out: [1, 0, { start: 0.95, end: 1 }],
pinB_scaleY: [0.5, 1, { start: 0.6, end: 0.65 }],
pinC_scaleY: [0.5, 1, { start: 0.87, end: 0.92 }],
}
},
{
//3
type:'sticky',
scrollHeight:0,
heightNum:5,
objs:{
container: document.querySelector('#scroll-section-3'),
canvasCaption: document.querySelector('.canvas-caption')
},
values:{
}
}
];
let yOffset=0;
let prevScrollHeight=0;
//현재 스크롤위치보다 이전에 위치한 스크롤 섹션들의 스크롤 높이값의 합.
let currentScene=0;
//활성화된 씬
let enterNewScene=false; //새로운 scene이 시작되는 순간.
function setLayout(){
for(let i=0; i<sceneInfo.length; i++){
if (sceneInfo[i].type==='sticky'){
sceneInfo[i].scrollHeight = sceneInfo[i].heightNum * window.innerHeight;
sceneInfo[i].objs.container.style.height=`${sceneInfo[i].scrollHeight}px`;
//기본적으로 문자열을 설정해야하나 ${--- } << ---이부분에 변수이름을 적용 가능
}else if(sceneInfo[i].type==='normal'){
sceneInfo[i].scrollHeight = sceneInfo[i].objs.container.style.offsetHeight;
}
sceneInfo[i].objs.container.style.height=`${sceneInfo[i].scrollHeight}px`;
}
//정확하게 한번더 선언. 재선언 가능의 LET
yOffset=window.pageYOffset;
//load이벤트와 연관지어야하는 이유.
let totalScrollHeight=0;
for(let i=0; i<sceneInfo.length; i++){
totalScrollHeight+=sceneInfo[i].scrollHeight;
if(totalScrollHeight >= yOffset){
currentScene=i;
break;
/*
*총 전체스크롤 높이가 현재 커서하고있는 페이지 스크롤 위치보다 크면,
*break를 사용하여 for 문을 탈출합니다.
*그리고 i값을 currentscene으로 세팅해줍니다.
*/
}
}
document.body.setAttribute('id',`show-scene-${currentScene}`);
}
function calcValues(values, currentYOffset){//스크롤 비율 계산
let rv;
let scrollRatio=currentYOffset/sceneInfo[currentScene].scrollHeight;
let scrollHeight=sceneInfo[currentScene].scrollHeight;
//currentYOffset은 playanimation에서 한개의 씬을 넘길때마다 초기화되는 스크롤의 값.
//scrollheight는 그 씬의 높이.
//그러므로 비율계산은 씬의 오프셋/씬의 높이
if (values.length===3){
//start~end 사이에 애니메이션 발생
const partScrollStart=values[2].start*scrollHeight;
const partScrollEnd=values[2].end*scrollHeight;
const partScrollHeight=partScrollEnd-partScrollStart;
if (currentYOffset>=partScrollStart && currentYOffset <= partScrollEnd){
rv=(currentYOffset-partScrollStart)/partScrollHeight*(values[1]-values[0])+values[0];
}
else if (currentYOffset<partScrollStart){
rv=values[0];
}
else if (currentYOffset>partScrollEnd){
rv=values[1];
}
}else{
rv=scrollRatio*(values[1]-values[0])+values[0];
}
return rv;
}
function playAnimation(){
const objs=sceneInfo[currentScene].objs;
const values=sceneInfo[currentScene].values;
const currentYOffset=yOffset-prevScrollHeight;
const scrollHeight=sceneInfo[currentScene].scrollHeight;
const scrollRatio=(yOffset-prevScrollHeight) / scrollHeight;
switch (currentScene){
case 0:
//let messageA_opacity_0=values.messageA_opacity[0];
//let messageA_opacity_1=values.messageA_opacity[1];
if(scrollRatio<=0.22){
objs.messageA.style.opacity=calcValues(values.messageA_opacity_in,currentYOffset);
objs.messageA.style.transform=`translateY(${calcValues(values.messageA_translateY_in,currentYOffset)}%)`;
}
else{
objs.messageA.style.opacity=calcValues(values.messageA_opacity_out,currentYOffset);
objs.messageA.style.transform=`translateY(${calcValues(values.messageA_translateY_out,currentYOffset)}%)`;
}
if (scrollRatio <= 0.42) {
// in
objs.messageB.style.opacity = calcValues(values.messageB_opacity_in, currentYOffset);
objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_in, currentYOffset)}%, 0)`;
} else {
// out
objs.messageB.style.opacity = calcValues(values.messageB_opacity_out, currentYOffset);
objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_out, currentYOffset)}%, 0)`;
}
if (scrollRatio <= 0.62) {
// in
objs.messageC.style.opacity = calcValues(values.messageC_opacity_in, currentYOffset);
objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_in, currentYOffset)}%, 0)`;
} else {
// out
objs.messageC.style.opacity = calcValues(values.messageC_opacity_out, currentYOffset);
objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_out, currentYOffset)}%, 0)`;
}
if (scrollRatio <= 0.82) {
// in
objs.messageD.style.opacity = calcValues(values.messageD_opacity_in, currentYOffset);
objs.messageD.style.transform = `translate3d(0, ${calcValues(values.messageD_translateY_in, currentYOffset)}%, 0)`;
} else {
// out
objs.messageD.style.opacity = calcValues(values.messageD_opacity_out, currentYOffset);
objs.messageD.style.transform = `translate3d(0, ${calcValues(values.messageD_translateY_out, currentYOffset)}%, 0)`;
}
break;
case 2:
// console.log('2 play');
if (scrollRatio <= 0.32) {
// in
objs.messageA.style.opacity = calcValues(values.messageA_opacity_in, currentYOffset);
objs.messageA.style.transform = `translate3d(0, ${calcValues(values.messageA_translateY_in, currentYOffset)}%, 0)`;
} else {
// out
objs.messageA.style.opacity = calcValues(values.messageA_opacity_out, currentYOffset);
objs.messageA.style.transform = `translate3d(0, ${calcValues(values.messageA_translateY_out, currentYOffset)}%, 0)`;
}
if (scrollRatio <= 0.67) {
// in
objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_in, currentYOffset)}%, 0)`;
objs.messageB.style.opacity = calcValues(values.messageB_opacity_in, currentYOffset);
objs.pinB.style.transform = `scaleY(${calcValues(values.pinB_scaleY, currentYOffset)})`;
} else {
// out
objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_out, currentYOffset)}%, 0)`;
objs.messageB.style.opacity = calcValues(values.messageB_opacity_out, currentYOffset);
objs.pinB.style.transform = `scaleY(${calcValues(values.pinB_scaleY, currentYOffset)})`;
}
if (scrollRatio <= 0.93) {
// in
objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_in, currentYOffset)}%, 0)`;
objs.messageC.style.opacity = calcValues(values.messageC_opacity_in, currentYOffset);
objs.pinC.style.transform = `scaleY(${calcValues(values.pinC_scaleY, currentYOffset)})`;
} else {
// out
objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_out, currentYOffset)}%, 0)`;
objs.messageC.style.opacity = calcValues(values.messageC_opacity_out, currentYOffset);
objs.pinC.style.transform = `scaleY(${calcValues(values.pinC_scaleY, currentYOffset)})`;
}
break;
case 3:
break;
}
}
function scrollLoop(){
prevScrollHeight=0;
enterNewScene=false;
for(let i = 0; i<currentScene; i++){
prevScrollHeight+=sceneInfo[i].scrollHeight;
}
if (yOffset>prevScrollHeight+sceneInfo[currentScene].scrollHeight){
enterNewScene=true;
currentScene++;
}
if (yOffset<prevScrollHeight){
enterNewScene=true;
if(currentScene===0) return;//모바일기기의 위로 올릴경우 -가 될 때를 방지
currentScene--;
}
document.body.setAttribute('id',`show-scene-${currentScene}`);
//"setAttribute 속성은 id 값을 두번재 인자값으로 줄 수 있다. 라는 의미"
console.log(currentScene);
if (enterNewScene) return ;
playAnimation();
}
window.addEventListener('resize',setLayout);
window.addEventListener('load',setLayout);
//각 스크롤 높이를 로드, 리사이즈 될 때 스크롤의 높이를 잡아줍니다.
window.addEventListener('scroll',()=>{
yOffset=window.pageYOffset;
scrollLoop();
});
setLayout();
})();
지금까지 따라 작성한 내용들인데 body요소의 id가 0 , 1,2,3 이런식으로 바뀌어야하는데 0, 1 까지만 바뀌고 2-3으로는 바뀌지가 않아서 2씬에서 핀위의 글씨가 보이지 않습니다 어딘지 잘모르겠습니다...
답변 1
0
두가지를 고치셔야 하는데요,
1. sceneInfo의 2번(3번째 씬)에 heightNum: 5 설정이 빠져있어서 #scroll-section-2의 높이가 제대로 설정되지 않고 있습니다.
2. setLayout 함수에서 'normal' 섹션의 높이 설정하는 부분에 속성값이 잘못 들어가 있습니다. offsetHeight는 style 객체의 속성이 아니라 DOM 객체의 속성이기 때문에 container.style.offsetHeight가 아닌 container.offsetHeight로 써주셔야 합니다.
이 부분을
sceneInfo[i].scrollHeight = sceneInfo[i].objs.container.offsetHeight;
이렇게 고쳐주세요^^
이미지 배경 문의
0
67
1
[크로스브라우징] safari에서 동영상 영역 미노출
0
106
1
항상 궁금했는데 크림슨 컬러 선택하셨을때 활용했던 사이트 좀 알려주세요~
0
109
2
vue강의는안하시나요?!
0
101
1
스크롤 속도에 따른 messageA_opacity_out
0
115
1
drawImage(objs.videoImages[sequence], 0, 0); error
0
89
1
선생님 캔버스 width 크기는 이미지 크기에맞게 해줘야하나요?
0
127
0
선생님 안녕하세요. 혹시 메인개발(?)분야가 뭔지 궁금합니다.
0
206
1
React에서 load 상태를 어떻게 감지할 수 있을까요?
0
678
1
[섹션7-3: 버그수정 2] tempYOffset 오류
0
195
1
스크롤할 때 캔버스로 하신 이유가 있으신가요? 그냥 성능 떄문에 캔버스로 하신건가요?
0
313
2
게속 오류떠서 글 작성해봐요....
0
506
2
Vanilla JavaScript로 SPA 만드는 자료 혹은 선택 기준을 추천해주실 수 있으신가요?
1
488
1
특정 타이밍 스크롤 애니메이션 적용하기 섹션 수강중입니다.
0
455
2
[#svg, #이미지프레임과 텍스트 싱크] 스크롤 값에 움직이는 svg path, 이미지프레임과 텍스트 싱크 맞추는 것, 2가지 질문이 있습니다.
0
451
2
페이지가 처음 로딩 되었을 때 애니메이션 처리가 되지 않는 느낌입니다
0
431
1
섹션2 번째, opacity=0 되지 않고 잔상이 남습니다.
0
533
1
원래 쿼리셀렉터에서는 띄워쓰기 하면안되나요?
0
593
2
라이브러리 질문
1
412
2
translateY대신 애플에서 사용한 것 처럼 matrix로 scale의 크기를 주려고 하는데
0
409
1
[스크롤 높이 세팅] scrollHeight값이 3990아닌 4645로만 나오는데 뭐가 문제일까요? ㅠㅠ
0
598
2
scrollLoop 함수 질문
0
476
2
도메인 웹호스팅시 이미지가 안 뜨는데 누가 좀 알려주세요ㅠㅜ
0
1235
2
load 이벤트시 첫 비디오 이미지가 뜨네요.
0
506
2





