해결된 질문
작성
·
237
0
해당 강의를 바탕으로 따로 페이지 하나를 제작하고 있는데 사진은 지정이 되지만 사진이 출력되지 않네요 ㅠ
그리고 Uncaught TypeError : Cannot read properties of undefined (reading @@@)
에러가 length랑 style에 뜨는데 원인과 해결방법을 알 수 있을까요?
-> 이 부분은 해결했습니다.
main.js 코드입니다
+ canvas를 통해 (머그컵과 같은) video 모션 이미지들이 들어가는 곳은 section 2,3,4 입니다.
(() => {
// 변수 모음
let yOffset = 0; // window.pageYOffset 대신 쓸 변수
let prevScrollHeight; // 현재 스크롤 위치 이전의 섹션들의 높이 합
let currentScene = 0; // 현재 보고 있는 씬 scroll-section 몇 번째인지
let enterNewScene = false; // 새로운 세션 시작된 순간 true
const sceneInfo = [
{
// section 0 - 인트로
type: "sticky",
heightNum: 5, // 브라우저 높이의 5배로 세팅
scrollHeight: 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 }],
},
},
{
// section 1 - 서비스 리스트
type: "normal",
// heightNum: 5, // type normal에서는 필요 없음
scrollHeight: 0,
objs: {
container: document.querySelector("#scroll-section-1"),
content: document.querySelector("#scroll-section-1 .description"),
},
},
{
// section 2 - 공개행정
type: "sticky",
heightNum: 5,
scrollHeight: 0,
objs: {
container: document.querySelector("#scroll-section-2"),
// messageABCD
canvas: document.querySelector("#video-canvas-2"),
context: document.querySelector("#video-canvas-2").getContext("2d"),
videoImages: [],
},
values: {
videoImageCount: 14,
imageSequence: [0, 13],
canvas_opacity: [1, 0, { start: 0.9, end: 1 }],
canvas_opacity_out: [1, 0, { start: 0.95, end: 1 }],
// ,assage opacity, translate
},
},
{
// section 3 - 참여행정
type: "sticky",
heightNum: 5,
scrollHeight: 0,
objs: {
container: document.querySelector("#scroll-section-3"),
// messageABCD
canvas: document.querySelector("#video-canvas-3"),
//content: document.querySelector("#scroll-section-3 .description"),
context: document.querySelector("#video-canvas-3").getContext("2d"),
videoImages: [],
},
values: {
videoImageCount: 15,
imageSequence: [0, 14],
canvas_opacity: [1, 0, { start: 0.9, end: 1 }],
canvas_opacity_out: [1, 0, { start: 0.95, end: 1 }],
// ,assage opacity, translate
},
},
{
// section 4 - 능률행정
type: "sticky",
heightNum: 5,
scrollHeight: 0,
objs: {
container: document.querySelector("#scroll-section-4"),
// messageABCD
canvas: document.querySelector("#video-canvas-4"),
//content: document.querySelector("#scroll-section-4 .description"),
//context: document.querySelector("#video-canvas-4").getContext("2d"),
videoImages: [],
},
values: {
videoImageCount: 12,
imageSequence: [0, 11],
canvas_opacity: [1, 0, { start: 0.9, end: 1 }],
canvas_opacity_out: [1, 0, { start: 0.95, end: 1 }],
// ,assage opacity, translate
},
},
{
// section 5 - 마무리
type: "sticky",
heightNum: 5, // 브라우저 높이의 5배로 세팅
scrollHeight: 0,
objs: {
container: document.querySelector("#scroll-section-5"),
messageA: document.querySelector("#scroll-section-5 .main-message.a"),
messageB: document.querySelector("#scroll-section-5 .main-message.b"),
messageC: document.querySelector("#scroll-section-5 .main-message.c"),
messageD: document.querySelector("#scroll-section-5 .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 }],
},
},
];
function setCanvasImages() {
let imgElem1;
for (let i = 0; i < sceneInfo[2].values.videoImageCount; i++) {
imgElem1 = new Image();
imgElem1.src = `./video/section2_file/section2IMG_${i}.JPG`;
sceneInfo[2].objs.videoImages.push(imgElem1);
}
let imgElem2;
for (let i = 0; i < sceneInfo[3].values.videoImageCount; i++) {
imgElem2 = new Image();
imgElem2.src = `./video/section3_file/section3IMG_${i}.JPG`;
sceneInfo[3].objs.videoImages.push(imgElem2);
}
let imgElem3;
for (let i = 0; i < sceneInfo[4].values.videoImageCount; i++) {
imgElem3 = new Image();
imgElem3.src = `./video/section4_file/section4IMG_${i}.JPG`;
sceneInfo[4].objs.videoImages.push(imgElem3);
}
}
function setLayout() {
// 각 스크롤 섹션의 높이 세팅
for (let i = 0; i < sceneInfo.length; i++) {
if (sceneInfo[i].type === "sticky") {
sceneInfo[i].scrollHeight = sceneInfo[i].heightNum * window.innerHeight;
} else if (sceneInfo[i].type === "normal") {
sceneInfo[i].scrollHeight = sceneInfo[i].objs.container.offsetHeight;
}
// 섹션의 높이를 html에 세팅
sceneInfo[
i
].objs.container.style.height = `${sceneInfo[i].scrollHeight}px`;
}
yOffset = window.pageYOffset;
let totalScrollHeight = 0;
for (let i = 0; i < sceneInfo.length; i++) {
totalScrollHeight += sceneInfo[i].scrollHeight;
if (totalScrollHeight >= yOffset) {
currentScene = i;
break;
}
}
document.body.setAttribute("id", `show-scene-${currentScene}`);
const heightRatio = window.innerHeight / 1080;
sceneInfo[2].objs.canvas.style.transform = `translate3d(-50%, -50%, 0) scale(${heightRatio})`;
}
// 값이 변화되는 걸 계산
// currentYOffset - 현재 섹션에서 얼마나 scroll되었는지 비율 계산
function calcValues(values, currentYOffset) {
let rv; // return value
const scrollHeight = sceneInfo[currentScene].scrollHeight;
const scrollRatio = currentYOffset / 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]; // 0~1 -> 범위 확장 return rv;
}
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 = currentYOffset / scrollHeight;
//console.log(currentScene, currentYOffset);
switch (currentScene) {
case 0: // 인트로
// console.log('0 play');
// let sequence = Math.round(calcValues(values.imageSequence, currentYOffset));
// objs.context.drawImage(objs.videoImages[sequence], 0, 0);
if (scrollRatio <= 0.22) {
// 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.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 1: // 리스트
break;
case 2: // 공개행정
objs.canvas.style.opacity = calcValues(
values.canvas_opacity,
currentYOffset
);
if (scrollRatio <= 0.5) {
// in
objs.canvas.style.opacity = calcValues(
values.canvas_opacity_in,
currentYOffset
);
} else {
// out
objs.canvas.style.opacity = calcValues(
values.canvas_opacity_out,
currentYOffset
);
}
if (scrollRatio <= 0.25) {
// 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.57) {
// 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.83) {
// 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: // 참여행정
objs.canvas.style.opacity = calcValues(
values.canvas_opacity,
currentYOffset
);
if (scrollRatio <= 0.25) {
// 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.57) {
// 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.83) {
// 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 4: // 능률 행정
objs.canvas.style.opacity = calcValues(
values.canvas_opacity,
currentYOffset
);
if (scrollRatio <= 0.25) {
// 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.57) {
// 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.83) {
// 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 5: // 마무리
if (scrollRatio <= 0.22) {
// 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.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;
}
}
// "현재 활성시킬 스크롤 씬(세션) 결정하기"
// 몇 번째 스크롤 섹션 진행중인지 check
// 앞파트 스크롤 섹션의 height 합으로 계산 가능
function scrollLoop() {
enterNewScene = false;
prevScrollHeight = 0; // 값 누적 방지용 초기화
for (let i = 0; i < currentScene; i++) {
prevScrollHeight += sceneInfo[i].scrollHeight;
}
if (yOffset > prevScrollHeight + sceneInfo[currentScene].scrollHeight) {
enterNewScene = true;
currentScene++;
document.body.setAttribute("id", `show-scene-${currentScene}`);
// currentScene에 맞춰서 body에 하나씩 세팅된다
}
if (yOffset < prevScrollHeight) {
enterNewScene = true;
if (currentScene == 0) return; // 브라우저 바운스 효과로 음수 에러 방지
currentScene--;
document.body.setAttribute("id", `show-scene-${currentScene}`);
// currentScene에 맞춰서 body에 하나씩 세팅된다
}
if (enterNewScene) return;
playAnimation();
//console.log(currentScene); // 몇 번째 섹션인지
}
//window.addEventListener("resize", setLayout); // height에러 check
window.addEventListener("scroll", () => {
yOffset = window.pageYOffset;
//console.log(yOffset); // 스크롤 페이지 값
scrollLoop();
});
// 새로고침
window.addEventListener("load", setLayout);
window.addEventListener("resize", setLayout);
setLayout();
setCanvasImages();
})();