main page
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Interactive Animation Sequence with Auto Scrolling Images</title> <style> body, html { margin: 0; padding: 0; width: 100%; height: 100%; background-color: white; overflow: hidden; } .main-container { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; position: relative; } .cassette-container { width: 180px; height: 120px; position: relative; cursor: pointer; } .cassette { width: 100%; height: 100%; background: url('img/ha.png') no-repeat center center; background-size: contain; position: relative; } .reel { position: absolute; width: 39px; height: 39px; background: url('img/haha.png') no-repeat center center; background-size: contain; top: 36px; animation: spin 3s linear infinite; } .reel.left { left: 33.5px; } .reel.right { right: 32px; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .glitch__layers { position: absolute; z-index: 2; left: 0; right: 0; top: 0; bottom: 0; display: none; } .glitch__layer { position: absolute; left: 0; right: 0; top: 0; bottom: 0; background-image: url('img/ha.png'); background-repeat: no-repeat; background-position: center; background-size: contain; } .glitch__layer:nth-child(1) { transform: translateX(-5%); animation: glitch-anim-1 0.7s infinite linear alternate; } .glitch__layer:nth-child(2) { transform: translateX(3%) translateY(3%); animation: glitch-anim-2 0.7s -.8s infinite linear alternate; } .glitch__layer:nth-child(3) { transform: translateX(5%); animation: glitch-anim-flash 0.7s infinite linear; } @keyframes glitch-anim-1 { 0% { clip-path: polygon(0 0%, 100% 0%, 100% 5%, 0 5%); } 100% { clip-path: polygon(0 60%, 100% 60%, 100% 70%, 0 70%); } } @keyframes glitch-anim-2 { 0% { clip-path: polygon(0 15%, 100% 15%, 100% 30%, 0 30%); } 100% { clip-path: polygon(0 11%, 100% 11%, 100% 15%, 0 15%); } } @keyframes glitch-anim-flash { 0% { opacity: .2; } 30%, 100% { opacity: 0; } } .frame-container { position: absolute; width: 100px; height: 50px; display: none; transition: transform 12s linear; } .frame { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 0.1s ease-in-out; background-size: contain; background-position: center; background-repeat: no-repeat; } .tv-off { animation: tv-off 0.2s linear forwards; } @keyframes tv-off { 0% { transform: scale(1, 1) translateY(0); } 60% { transform: scale(1, 0.001) translateY(0); } 100% { transform: scale(0, 0.001) translateY(50%); } } .fade-in { animation: fade-in 2s forwards; } @keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } #image-container { position: absolute; width: 100%; height: 12000px; /* 전체 컨텐츠 높이에 맞게 조정 */ top: 200%; /* 100%에서 200%로 변경 */ transition: none; will-change: scroll-position; will-change: transform; } .media { position: absolute; transition: transform 0.4s; will-change: scroll-position; will-change: transform; } .image { box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5); /* 그림자 설정 */ z-index: 2; content-visibility: auto; will-change: scroll-position; will-change: transform; transform: translateZ(0); } .image:hover { transform: scale(2.0) rotate(0deg) translateZ(0) !important; /* 이미지 확대와 회전을 동시에 설정, important는 명시적 지정 */ z-index: 2; will-change: scroll-position; will-change: transform; } .picture { transform: rotate(0deg); transform-origin: right center; z-index: 1; box-shadow: 0 0 0 12px white, 0 0 0 16px black; /* 여기에 추가 */ content-visibility: auto; } .center-image { position: absolute; width: 20%; height: auto; left: 50%; top: 50%; transform: translate(-50%, -50%); display: none; } </style> </head> <body> <div class="main-container"> <div class="cassette-container" id="cassetteContainer"> <div class="cassette"> <div class="reel left"></div> <div class="reel right"></div> </div> <div class="glitch__layers"> <div class="glitch__layer"></div> <div class="glitch__layer"></div> <div class="glitch__layer"></div> </div> </div> <div class="frame-container"> <div id="frame1" class="frame" style="background-image: url('img/프레임1.JPG');"></div> <div id="frame2" class="frame" style="background-image: url('img/프레임2.jpg');"></div> <div id="frame3" class="frame" style="background-image: url('img/프레임3.jpg');"></div> <div id="frame4" class="frame" style="background-image: url('img/프레임4.jpg');"></div> <div id="frame5" class="frame" style="background-image: url('img/프레임5.jpg');"></div> </div> <div id="image-container"> <!--picture--> <img src="images/picture1.webp" class="media picture" loading="lazy" decoding="async" style="left: 25%; top: 10%; width:70%; height: auto;"> <img src="images/picture2.webp" class="media picture" loading="lazy" decoding="async" style="left: 10%; top: 20%; width:70%; height: auto;"> <img src="images/picture3.webp" class="media picture" loading="lazy" decoding="async" style="left: 25%; top: 30%; width:70%; height: auto;"> <img src="images/picture4.webp" class="media picture" loading="lazy" decoding="async" style="left: 10%; top: 40%; width:70%; height: auto;"> <img src="images/picture5.webp" class="media picture" loading="lazy" decoding="async" style="left: 25%; top: 50%; width:70%; height: auto;"> <img src="images/picture6.webp" class="media picture" loading="lazy" decoding="async" style="left: 10%; top: 60%; width:70%; height: auto;"> <img src="images/picture7.webp" class="media picture" loading="lazy" decoding="async" style="left: 25%; top: 70%; width:70%; height: auto;"> <!--image--> <img src="images/image1.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 2%; width: 20%; height: auto; transform: rotate(20deg); transform-origin: left center"> <img src="images/image2.webp" class="media image" loading="lazy" decoding="async" style="right: 10%; top: 5%; width: 19%; height: auto; transform: rotate(-18deg); transform-origin: right center"> <img src="images/image3.webp" class="media image" loading="lazy" decoding="async" style="left: 19%; top: 8%; width: 16%; height: auto; transform: rotate(10deg); transform-origin: left center"> <img src="images/image4.webp" class="media image" loading="lazy" decoding="async" style="left: 17%; top: 13%; width: 20%; height: auto; transform: rotate(35deg); transform-origin: left center"> <img src="images/image5.webp" class="media image" loading="lazy" decoding="async" style="right: 10%; top: 15%; width: 20%; height: auto; transform: rotate(-10deg); transform-origin: right center"> <img src="images/image6.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 18%; width: 22%; height: auto; transform: rotate(-7deg); transform-origin: left center"> <img src="images/image7.webp" class="media image" loading="lazy" decoding="async" style="right: 15%; top: 19%; width: 13%; height: auto; transform: rotate(0deg); transform-origin: right center"> <img src="images/image8.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 24%; width: 15%; height: auto; transform: rotate(5deg); transform-origin: left center"> <img src="images/image9.webp" class="media image" loading="lazy" decoding="async" style="right: 5%; top: 23%; width: 17%; height: auto; transform: rotate(-5deg); transform-origin: right center"> <!--2차 수정 완--> <img src="images/image10.webp" class="media image" loading="lazy" decoding="async" style="left: 15%; top: 28%; width: 15%; height: auto; transform: rotate(20deg); transform-origin: left center"> <img src="images/image11.webp" class="media image" loading="lazy" decoding="async" style="right: 3%; top: 29%; width: 23%; height: auto; transform: rotate(-15deg); transform-origin: right center"> <img src="images/image12.webp" class="media image" loading="lazy" decoding="async" style="right: 2%; top: 34%; width: 25%; height: auto; transform: rotate(0deg); transform-origin: right center"> <img src="images/image13.webp" class="media image" loading="lazy" decoding="async" style="left: 7%; top: 34%; width: 19%; height: auto; transform: rotate(10deg); transform-origin: left center"> <img src="images/image14.webp" class="media image" loading="lazy" decoding="async" style="right: 10%; top: 39%; width: 23%; height: auto; transform: rotate(0deg); transform-origin: right center"> <img src="images/image15.webp" class="media image" loading="lazy" decoding="async" style="left: 15%; top: 43%; width: 23%; height: auto; transform: rotate(5deg); transform-origin: left center"> <!--2차 수정 완--> <img src="images/image16.webp" class="media image" loading="lazy" decoding="async" style="left: 5%; top: 47%; width: 20%; height: auto; transform: rotate(0deg); transform-origin: left center"> <img src="images/image17.webp" class="media image" loading="lazy" decoding="async" style="right: 10%; top: 50%; width: 17%; height: auto; transform: rotate(-16deg); transform-origin: right center"> <!-- <img src="images/image18.webp" class="media image" style="right: 20%; top: 54%; width: 18%; height: auto; transform: rotate(-5deg); transform-origin: right center"> --> <!--2차 수정 완--> <img src="images/image19.webp" class="media image" loading="lazy" decoding="async" style="left: 2%; top: 55%; width: 20%; height: auto; transform: rotate(20deg); transform-origin: left center"> <!-- <img src="images/image20.webp" class="media image" style="left: 50%; top: 56%; width: 15%; height: auto; transform: rotate(0deg); transform-origin: right center"> --> <img src="images/image21.webp" class="media image" loading="lazy" decoding="async" style="right: 1%; top: 58%; width: 20%; height: auto; transform: rotate(3deg); transform-origin: right center"> <!--2차 수정 완--> <img src="images/image22.webp" class="media image" loading="lazy" decoding="async" style="left: 1%; top: 61%; width: 20%; height: auto; transform: rotate(-2deg); transform-origin: left center"> <img src="images/image23.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 67%; width: 16%; height: auto; transform: rotate(0deg); transform-origin: left center"> <img src="images/image24.webp" class="media image" loading="lazy" decoding="async" style="right: 5%; top: 69%; width: 25%; height: auto; transform: rotate(10deg); transform-origin: right center"> <img src="images/image25.webp" class="media image" loading="lazy" decoding="async" style="right: 3%; top: 73%; width: 20%; height: auto; transform: rotate(-3deg); transform-origin: right center"> <img src="images/image26.webp" class="media image" loading="lazy" decoding="async" style="left: 5%; top: 75%; width: 16%; height: auto; transform: rotate(10deg); transform-origin: left center"> <img src="images/image27.webp" class="media image" loading="lazy" decoding="async" style="right: 10%; top: 79%; width: 20%; height: auto; transform: rotate(10deg); transform-origin: right center"> </div> <img src="images/button.png" class="center-image" id="centerImage"> </div> <audio id="cdplAudio" src="cdpl.mp3"></audio> <audio id="crazyAudio" src="Crazy.mp3"></audio> <script> const cassetteContainer = document.getElementById('cassetteContainer'); const glitchLayers = cassetteContainer.querySelector('.glitch__layers'); const reels = document.querySelectorAll('.reel'); const frameContainer = document.querySelector('.frame-container'); const frames = document.querySelectorAll('.frame'); const imageContainer = document.getElementById('image-container'); const centerImage = document.getElementById('centerImage'); let isAnimating = false; let currentFrame = 0; function showFrame(index) { frames.forEach(frame => frame.style.opacity = '0'); frames[index].style.opacity = '1'; } function animate() { if (!isAnimating) return; showFrame(currentFrame); currentFrame = (currentFrame + 1) % frames.length; setTimeout(animate, 130); } function startScrolling() { const totalHeight = imageContainer.offsetHeight - window.innerHeight; const duration = 80000; // 80초 동안 스크롤 (필요에 따라 조정) const startTime = Date.now(); function smoothScroll() { const elapsedTime = Date.now() - startTime; const progress = Math.min(elapsedTime / duration, 1); const scrollY = progress * totalHeight; // transition 대신 transform으로 직접 위치 조정 imageContainer.style.transform = `translateY(${-scrollY - window.innerHeight}px)`; if (progress < 1) { requestAnimationFrame(smoothScroll); } else { setTimeout(showCenterImage, 0); // 스크롤이 끝난 후 2초 후 중앙 이미지 표시 } } requestAnimationFrame(smoothScroll); } function showCenterImage() { centerImage.style.display = 'block'; centerImage.classList.add('fade-in'); } cassetteContainer.addEventListener('click', () => { document.getElementById('cdplAudio').play(); reels.forEach(reel => reel.style.animationPlayState = 'paused'); glitchLayers.style.display = 'block'; setTimeout(() => { glitchLayers.style.display = 'none'; cassetteContainer.classList.add('tv-off'); setTimeout(() => { cassetteContainer.style.display = 'none'; setTimeout(() => { frameContainer.style.display = 'block'; isAnimating = true; animate(); document.getElementById('cdplAudio').onended = () => { document.getElementById('crazyAudio').play(); setTimeout(() => { frameContainer.style.transform = 'translateY(-100vh)'; setTimeout(() => { imageContainer.style.transform = 'translateY(-200%)'; // 초기 위치 설정 startScrolling(); }, 3000); // 3초 동안 흰 공백을 보여줍니다. }, 3000); // 스톱모션이 중앙에 머무는 시간 }; }, 5800); }, 200); }, 700); }); // document.querySelectorAll('.video').forEach(video => { // video.addEventListener('mouseover', () => { // video.play(); // }); // video.addEventListener('mouseout', () => { // video.pause(); // video.currentTime = 0; // }); // }); showFrame(0); // Lazy Loading with Intersection Observer const images = document.querySelectorAll('img[loading="lazy"]'); const options = { root: null, rootMargin: '0px', threshold: 1.5 }; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; // console.log('Loading image:', img.src); img.src = img.getAttribute('data-src'); observer.unobserve(img); } }); }, options); images.forEach(image => { observer.observe(image); }); </script> </body> </html>
가장 좋은 최적화 방법은 이미지 해상도를 낮추는 것이었다..
ToDo
ending page 디자인 → 아직 폰트 적용 X
배경 색 코드: #97F5FF
프레임 맞추고, 멈추는 거 10초, 1분 40초
→ 시작 속도를 다르게 인식한다. 이어폰 스피커..
→ 노래가 시작하는 시간을 기준점으로 잡아야 한다
CSS에서의 단위의 종류!!
Keep
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Interactive Animation Sequence with Auto Scrolling Images</title> <style> body, html { margin: 0; padding: 0; width: 100%; height: 100%; background-color: #97F5FF; /* 배경 색상 변경 */ overflow: hidden; display: flex; justify-content: center; align-items: center; flex-direction: column; color: black; /* 텍스트 색상 설정 */ font-family: Arial, sans-serif; /* 폰트 설정 */ } .main-container { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; position: relative; } .frame-container { position: absolute; width: 100%; height: 100%; display: none; transition: transform 12s linear; } .frame { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 0.1s ease-in-out; background-size: cover; background-position: center; background-repeat: no-repeat; } #image-container { position: absolute; width: 100%; height: 12000px; /* 전체 컨텐츠 높이에 맞게 조정 */ top: 200%; /* 100%에서 200%로 변경 */ transition: none; will-change: scroll-position; will-change: transform; } .media { position: absolute; transition: transform 0.4s; will-change: scroll-position; will-change: transform; } .image { box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5); /* 그림자 설정 */ z-index: 2; content-visibility: auto; will-change: scroll-position; will-change: transform; transform: translateZ(0); } .image:hover { transform: scale(1.5) rotate(0deg) translateZ(0) !important; /* 이미지 확대와 회전을 동시에 설정, important는 명시적 지정 */ z-index: 3; will-change: scroll-position; will-change: transform; } .picture { transform: rotate(0deg); transform-origin: right center; z-index: 1; content-visibility: auto; } .video { box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5); /* 그림자 설정 */ width: 800px; height: auto; z-index: 2; transform-origin: left center; will-change: scroll-position; will-change: transform; } .video:hover { transform: scale(1.5) rotate(0deg) translateZ(0) !important;; will-change: scroll-position; will-change: transform; z-index: 3; } @font-face { font-family: 'font1'; src: url('font/font1.ttf') format('truetype'); /* format 값을 올바르게 설정 */ } .text-container { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; font-family: 'font1', sans-serif; /* font-family에서 중복 제거 및 대체 폰트 추가 */ font-size: 24px; /* 기본 폰트 크기 설정 */ color: #FFFFFF; /* 기본 텍스트 색상 설정 */ position: absolute; top: 5%; /* 텍스트 상단 위치 설정 */ left: 50%; transform: translateX(-50%); width: 80%; /* 텍스트 너비 설정 */ } .text-container p { margin: 5px 0; /* 각 텍스트 항목 간격 설정 */ } </style> </head> <body> <div class="main-container"> <div class="frame-container"> <div id="frame1" class="frame" style="background-image: url('img/outro1.png');"></div> <div id="frame2" class="frame" style="background-image: url('img/outro2.png');"></div> <div id="frame3" class="frame" style="background-image: url('img/outro3.png');"></div> <div id="frame4" class="frame" style="background-image: url('img/outro4.png');"></div> <div id="frame5" class="frame" style="background-image: url('img/outro5.png');"></div> <div id="frame6" class="frame" style="background-image: url('img/outro6.png');"></div> <div id="frame7" class="frame" style="background-image: url('img/outro7.png');"></div> <div id="frame8" class="frame" style="background-image: url('img/outro8.png');"></div> </div> <div id="image-container"> <div class="text-container"> <p style="font-size: 35px; color: #FFFFFF;">출연</p> <br> <p style="font-size: 30px; color: #FFFFFF;">공진우</p> <p style="font-size: 30px; color: #FFFFFF;">김동근</p> <p style="font-size: 30px; color: #FFFFFF;">김진영</p> <p style="font-size: 30px; color: #FFFFFF;">김문정</p> <p style="font-size: 30px; color: #FFFFFF;">김민영</p> <p style="font-size: 30px; color: #FFFFFF;">문재혁</p> <p style="font-size: 30px; color: #FFFFFF;">백승주</p> <p style="font-size: 30px; color: #FFFFFF;">오세연</p> <p style="font-size: 30px; color: #FFFFFF;">송종찬</p> <p style="font-size: 30px; color: #FFFFFF;">이동건</p> <p style="font-size: 30px; color: #FFFFFF;">이은영</p> <p style="font-size: 30px; color: #FFFFFF;">이은재</p> <p style="font-size: 30px; color: #FFFFFF;">이재희</p> <p style="font-size: 30px; color: #FFFFFF;">이현호</p> <p style="font-size: 30px; color: #FFFFFF;">임지민</p> <p style="font-size: 30px; color: #FFFFFF;">장지원</p> <p style="font-size: 30px; color: #FFFFFF;">조민주</p> <p style="font-size: 30px; color: #FFFFFF;">최정민</p> <p style="font-size: 30px; color: #FFFFFF;">하도현</p> <p style="font-size: 30px; color: #FFFFFF;">홍바다</p> <p style="font-size: 30px; color: #FFFFFF;">하준학</p> <br> <br> <p style="font-size: 35px; color: #FFFFFF;">제작</p> <br> <p style="font-size: 30px; color: #FFFFFF;">장지원</p> <p style="font-size: 30px; color: #FFFFFF;">백승주</p> </div> <img src="outro_images/image1.webp" class="media image" loading="lazy" decoding="async" style="right: 10%; top: 6%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: right center"> <img src="outro_images/image2.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 7%; width: 15%; height: auto; transform: rotate(7deg); transform-origin: left center"> <img src="outro_images/image3.webp" class="media image" loading="lazy" decoding="async" style="right: 9%; top: 12%; width: 18%; height: auto; transform: rotate(6deg); transform-origin: right center"> <img src="outro_images/image4.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 13%; width: 16%; height: auto; transform: rotate(-8deg); transform-origin: left center"> <img src="outro_images/image5.webp" class="media image" loading="lazy" decoding="async" style="right: 9%; top: 15%; width: 19%; height: auto; transform: rotate(-8deg); transform-origin: right center"> <img src="outro_images/image6.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 17%; width: 17%; height: auto; transform: rotate(10deg); transform-origin: left center"> <img src="outro_images/image7.webp" class="media image" loading="lazy" decoding="async" style="right:10%; top: 20%; width: 18%; height: auto; transform: rotate(10deg); transform-origin: right center"> <img src="outro_images/image8.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 23%; width: 17%; height: auto; transform: rotate(-9deg); transform-origin: left center"> <img src="outro_images/image9.webp" class="media image" loading="lazy" decoding="async" style="right:8%; top: 24%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: right center"> <img src="outro_images/image10.webp" class="media image" loading="lazy" decoding="async" style="left: 7%; top: 28%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: left center"> <img src="outro_images/image11.webp" class="media image" loading="lazy" decoding="async" style="right:9%; top: 30%; width: 18%; height: auto; transform: rotate(8deg); transform-origin: right center"> <video src="outro_images/image12.mp4" class="media video" loading="lazy" decoding="async" style="left: 10%; top: 34%; width: 17%; height: auto; transform: rotate(-7deg); transform-origin: left center"></video> <video src="outro_images/image13.mp4" class="media video" loading="lazy" decoding="async" style="right:10%; top: 34%; width: 25%; height: auto; transform: rotate(-10deg); transform-origin: right center"></video> <img src="outro_images/image14.webp" class="media image" loading="lazy" decoding="async" style="left: 8%; top: 40%; width: 17%; height: auto; transform: rotate(8deg); transform-origin: left center"> <!-- 2차 수정 완!--> <img src="outro_images/image15.webp" class="media image" loading="lazy" decoding="async" style="right:8%; top: 38%; width: 18%; height: auto; transform: rotate(4deg); transform-origin: right center"> <video src="outro_images/image16.mp4" class="media video" loading="lazy" decoding="async" style="left: 40%; top: 42%; width: 14%; height: auto; transform: rotate(3deg); transform-origin: center"></video> <img src="outro_images/image17.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 45%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <video src="outro_images/image18.mp4" class="media video" loading="lazy" decoding="async" style="right: 10%; top: 45%; width: 15%; height: auto; transform: rotate(-7deg); transform-origin: right center"></video> <!-- 2차 수정 완!--> <img src="outro_images/image19.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 47%; width: 18%; height: auto; transform: rotate(15deg); transform-origin: left center"> <img src="outro_images/image20.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 52%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <img src="outro_images/image21.webp" class="media image" loading="lazy" decoding="async" style="right: 7%; top: 51%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: right center"> <img src="outro_images/image22.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 53%; width: 18%; height: auto; transform: rotate(5deg); transform-origin: left center"> <img src="outro_images/image23.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 58%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <img src="outro_images/image24.webp" class="media image" loading="lazy" decoding="async" style="right: 7%; top: 59%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: right center"> <img src="outro_images/image25.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 59%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <!--마지막 컷!--> <img src="outro_images/image26.png" class="media picture" loading="lazy" decoding="async" style="left: 0%; top: 73%; width: 100%; height: auto";> </div> </div> <audio id="openAudio" src="open.mp3"></audio> <script> const frameContainer = document.querySelector('.frame-container'); const frames = document.querySelectorAll('.frame'); const imageContainer = document.getElementById('image-container'); let isAnimating = false; let currentFrame = 0; const frameTimes = [ 11755, 11964, 12129, 12315, 12507, 12692, 12886, 13071 ]; function showFrame(index) { frames.forEach(frame => frame.style.opacity = '0'); frames[index].style.opacity = '1'; } function animate(timestamp, startTime) { if (!isAnimating) return; const elapsed = timestamp - startTime; for (let i = 0; i < frameTimes.length-1; i++) { if (elapsed >= frameTimes[i]) { showFrame(i+1); } } if (elapsed < frameTimes[frameTimes.length - 1]) { requestAnimationFrame((ts) => animate(ts, startTime)); } } function startScrolling() { const totalHeight = imageContainer.offsetHeight - window.innerHeight; // 높이 변경 시 다시 계산 const duration = 80000; // 80초 동안 스크롤 (필요에 따라 조정) const startTime = Date.now(); function smoothScroll() { const elapsedTime = Date.now() - startTime; const progress = Math.min(elapsedTime / duration, 1); const scrollY = progress * totalHeight; // transition 대신 transform으로 직접 위치 조정 imageContainer.style.transform = `translateY(${-scrollY - window.innerHeight}px)`; if (progress < 1) { requestAnimationFrame(smoothScroll); } } requestAnimationFrame(smoothScroll); } function startSequence() { frameContainer.style.display = 'block'; isAnimating = true; const startTime = performance.now(); requestAnimationFrame((timestamp) => animate(timestamp, startTime)); setTimeout(() => { isAnimating = false; setTimeout(() => { frameContainer.style.transform = 'translateY(-100vh)'; setTimeout(() => { imageContainer.style.transform = 'translateY(-200%)'; startScrolling(); }, 0); }, 6000); }, 13071); } window.onload = () => { startSequence(); document.getElementById('openAudio').play(); } showFrame(0); document.querySelectorAll('.video').forEach(video => { video.addEventListener('mouseover', () => { video.play(); }); video.addEventListener('mouseout', () => { video.pause(); video.currentTime = 0; }); }); const images = document.querySelectorAll('img[loading="lazy"]'); const options = { root: null, rootMargin: '0px', threshold: 1.5 }; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.getAttribute('data-src'); observer.unobserve(img); } }); }, options); images.forEach(image => { observer.observe(image); }); </script> </div> </body> </html>
아
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Interactive Animation Sequence with Auto Scrolling Images</title> <style> body, html { margin: 0; padding: 0; width: 100%; height: 100%; background-color: #97F5FF; /* 배경 색상 변경 */ overflow: hidden; display: flex; justify-content: center; align-items: center; flex-direction: column; color: black; /* 텍스트 색상 설정 */ font-family: Arial, sans-serif; /* 폰트 설정 */ } .main-container { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; position: relative; } .frame-container { position: absolute; width: 100%; height: 100%; display: none; transition: transform 12s linear; } .frame { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 0.1s ease-in-out; background-size: cover; background-position: center; background-repeat: no-repeat; } #image-container { position: absolute; width: 100%; height: 12000px; /* 전체 컨텐츠 높이에 맞게 조정 */ top: 200%; /* 100%에서 200%로 변경 */ transition: none; will-change: scroll-position; will-change: transform; } .media { position: absolute; transition: transform 0.4s; will-change: scroll-position; will-change: transform; } .image { box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5); /* 그림자 설정 */ z-index: 2; content-visibility: auto; will-change: scroll-position; will-change: transform; transform: translateZ(0); } .image:hover { transform: scale(1.5) rotate(0deg) translateZ(0) !important; /* 이미지 확대와 회전을 동시에 설정, important는 명시적 지정 */ z-index: 3; will-change: scroll-position; will-change: transform; } .picture { transform: rotate(0deg); transform-origin: right center; z-index: 1; content-visibility: auto; } .video { box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5); /* 그림자 설정 */ width: 800px; height: auto; z-index: 2; transform-origin: left center; will-change: scroll-position; will-change: transform; } .video:hover { transform: scale(1.5) rotate(0deg) translateZ(0) !important;; will-change: scroll-position; will-change: transform; z-index: 3; } @font-face { font-family: 'font1'; src: url('font/font1.ttf') format('truetype'); /* format 값을 올바르게 설정 */ } .text-container { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; font-family: 'font1', sans-serif; /* font-family에서 중복 제거 및 대체 폰트 추가 */ font-size: 24px; /* 기본 폰트 크기 설정 */ color: #FFFFFF; /* 기본 텍스트 색상 설정 */ position: absolute; top: 5%; /* 텍스트 상단 위치 설정 */ left: 50%; transform: translateX(-50%); width: 80%; /* 텍스트 너비 설정 */ } .text-container p { margin: 5px 0; /* 각 텍스트 항목 간격 설정 */ } </style> </head> <body> <div class="main-container"> <div class="frame-container"> <div id="frame1" class="frame" style="background-image: url('img/outro1.png');"></div> <div id="frame2" class="frame" style="background-image: url('img/outro2.png');"></div> <div id="frame3" class="frame" style="background-image: url('img/outro3.png');"></div> <div id="frame4" class="frame" style="background-image: url('img/outro4.png');"></div> <div id="frame5" class="frame" style="background-image: url('img/outro5.png');"></div> <div id="frame6" class="frame" style="background-image: url('img/outro6.png');"></div> <div id="frame7" class="frame" style="background-image: url('img/outro7.png');"></div> <div id="frame8" class="frame" style="background-image: url('img/outro8.png');"></div> </div> <div id="image-container"> <div class="text-container"> <p style="font-size: 35px; color: #FFFFFF;">출연</p> <br> <p style="font-size: 30px; color: #FFFFFF;">공진우</p> <p style="font-size: 30px; color: #FFFFFF;">김동근</p> <p style="font-size: 30px; color: #FFFFFF;">김진영</p> <p style="font-size: 30px; color: #FFFFFF;">김문정</p> <p style="font-size: 30px; color: #FFFFFF;">김민영</p> <p style="font-size: 30px; color: #FFFFFF;">문재혁</p> <p style="font-size: 30px; color: #FFFFFF;">백승주</p> <p style="font-size: 30px; color: #FFFFFF;">오세연</p> <p style="font-size: 30px; color: #FFFFFF;">송종찬</p> <p style="font-size: 30px; color: #FFFFFF;">이동건</p> <p style="font-size: 30px; color: #FFFFFF;">이은영</p> <p style="font-size: 30px; color: #FFFFFF;">이은재</p> <p style="font-size: 30px; color: #FFFFFF;">이재희</p> <p style="font-size: 30px; color: #FFFFFF;">이현호</p> <p style="font-size: 30px; color: #FFFFFF;">임지민</p> <p style="font-size: 30px; color: #FFFFFF;">장지원</p> <p style="font-size: 30px; color: #FFFFFF;">조민주</p> <p style="font-size: 30px; color: #FFFFFF;">최정민</p> <p style="font-size: 30px; color: #FFFFFF;">하도현</p> <p style="font-size: 30px; color: #FFFFFF;">홍바다</p> <p style="font-size: 30px; color: #FFFFFF;">하준학</p> <br> <br> <p style="font-size: 35px; color: #FFFFFF;">제작</p> <br> <p style="font-size: 30px; color: #FFFFFF;">장지원</p> <p style="font-size: 30px; color: #FFFFFF;">백승주</p> </div> <img src="outro_images/image1.webp" class="media image" loading="lazy" decoding="async" style="right: 10%; top: 6%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: right center"> <img src="outro_images/image2.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 7%; width: 15%; height: auto; transform: rotate(7deg); transform-origin: left center"> <img src="outro_images/image3.webp" class="media image" loading="lazy" decoding="async" style="right: 9%; top: 12%; width: 18%; height: auto; transform: rotate(6deg); transform-origin: right center"> <img src="outro_images/image4.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 13%; width: 16%; height: auto; transform: rotate(-8deg); transform-origin: left center"> <img src="outro_images/image5.webp" class="media image" loading="lazy" decoding="async" style="right: 9%; top: 15%; width: 19%; height: auto; transform: rotate(-8deg); transform-origin: right center"> <img src="outro_images/image6.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 17%; width: 17%; height: auto; transform: rotate(10deg); transform-origin: left center"> <img src="outro_images/image7.webp" class="media image" loading="lazy" decoding="async" style="right:10%; top: 20%; width: 18%; height: auto; transform: rotate(10deg); transform-origin: right center"> <img src="outro_images/image8.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 23%; width: 17%; height: auto; transform: rotate(-9deg); transform-origin: left center"> <img src="outro_images/image9.webp" class="media image" loading="lazy" decoding="async" style="right:8%; top: 24%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: right center"> <img src="outro_images/image10.webp" class="media image" loading="lazy" decoding="async" style="left: 7%; top: 28%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: left center"> <img src="outro_images/image11.webp" class="media image" loading="lazy" decoding="async" style="right:9%; top: 30%; width: 18%; height: auto; transform: rotate(8deg); transform-origin: right center"> <video src="outro_images/image12.mp4" class="media video" loading="lazy" decoding="async" style="left: 10%; top: 34%; width: 17%; height: auto; transform: rotate(-7deg); transform-origin: left center"></video> <video src="outro_images/image13.mp4" class="media video" loading="lazy" decoding="async" style="right:10%; top: 34%; width: 25%; height: auto; transform: rotate(-10deg); transform-origin: right center"></video> <img src="outro_images/image14.webp" class="media image" loading="lazy" decoding="async" style="left: 8%; top: 40%; width: 17%; height: auto; transform: rotate(8deg); transform-origin: left center"> <!-- 2차 수정 완!--> <img src="outro_images/image15.webp" class="media image" loading="lazy" decoding="async" style="right:8%; top: 38%; width: 18%; height: auto; transform: rotate(4deg); transform-origin: right center"> <video src="outro_images/image16.mp4" class="media video" loading="lazy" decoding="async" style="left: 40%; top: 42%; width: 14%; height: auto; transform: rotate(3deg); transform-origin: center"></video> <img src="outro_images/image17.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 45%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <video src="outro_images/image18.mp4" class="media video" loading="lazy" decoding="async" style="right: 10%; top: 45%; width: 15%; height: auto; transform: rotate(-7deg); transform-origin: right center"></video> <!-- 2차 수정 완!--> <img src="outro_images/image19.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 47%; width: 18%; height: auto; transform: rotate(15deg); transform-origin: left center"> <img src="outro_images/image20.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 52%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <img src="outro_images/image21.webp" class="media image" loading="lazy" decoding="async" style="right: 7%; top: 51%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: right center"> <img src="outro_images/image22.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 53%; width: 18%; height: auto; transform: rotate(5deg); transform-origin: left center"> <img src="outro_images/image23.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 58%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <img src="outro_images/image24.webp" class="media image" loading="lazy" decoding="async" style="right: 7%; top: 59%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: right center"> <img src="outro_images/image25.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 59%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <!--마지막 컷!--> <img src="outro_images/image26.png" class="media picture" loading="lazy" decoding="async" style="left: 0%; top: 73%; width: 100%; height: auto";> </div> </div> <audio id="openAudio" src="open.mp3"></audio> <script> const frameContainer = document.querySelector('.frame-container'); const frames = document.querySelectorAll('.frame'); const imageContainer = document.getElementById('image-container'); const audio = document.getElementById('openAudio'); let isAnimating = false; let currentFrame = 0; let startTime = 0; // startTime을 초기화합니다. const frameTimes = [ 11755, 11964, 12129, 12315, 12507, 12692, 12886, 13071 ]; function animate() { const elapsed = audio.currentTime - startTime; frameTimes.forEach((time, index) => { if (Math.abs(elapsed - time) < 50) { showFrame(index); } }); if (elapsed < frameTimes[frameTimes.length - 1] + 1000) { requestAnimationFrame(animate); } } function showFrame(index) { frames.forEach(frame => frame.style.opacity = '0'); frames[index].style.opacity = '1'; } function startScrolling() { const totalHeight = imageContainer.offsetHeight - window.innerHeight; // 높이 변경 시 다시 계산 const duration = 100000; // 80초 동안 스크롤 (필요에 따라 조정) const startTime = Date.now(); function smoothScroll() { const elapsedTime = Date.now() - startTime; const progress = Math.min(elapsedTime / duration, 1); const scrollY = progress * totalHeight; // transition 대신 transform으로 직접 위치 조정 imageContainer.style.transform = `translateY(${-scrollY - window.innerHeight}px)`; if (progress < 1) { requestAnimationFrame(smoothScroll); } } requestAnimationFrame(smoothScroll); } function startSequence() { frameContainer.style.display = 'block'; isAnimating = true; const startTime = performance.now(); requestAnimationFrame((timestamp) => animate(timestamp, startTime)); setTimeout(() => { isAnimating = false; setTimeout(() => { frameContainer.style.transform = 'translateY(-100vh)'; setTimeout(() => { imageContainer.style.transform = 'translateY(-200%)'; startScrolling(); }, 0); }, 6000); }, 13071); } window.onload = () => { startSequence(); document.getElementById('openAudio').play(); } showFrame(0); document.querySelectorAll('.video').forEach(video => { video.addEventListener('mouseover', () => { video.play(); }); video.addEventListener('mouseout', () => { video.pause(); video.currentTime = 0; }); }); const images = document.querySelectorAll('img[loading="lazy"]'); const options = { root: null, rootMargin: '0px', threshold: 1.5 }; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.getAttribute('data-src'); observer.unobserve(img); } }); }, options); images.forEach(image => { observer.observe(image); }); </script> </div> </body> </html>
- cd 돌아가게
- 링크 보여지게
- 클릭하면 뒤 돌아보게
- down scaling 방법?
keep
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Cassette Tape Animation</title> <style> body { display: flex; justify-content: center; /* Center horizontally */ align-items: center; /* Center vertically */ height: 100vh; background-color: #ffffff; margin: 0; position: relative; } .reel { width: 70vw; height: 70vh; position: absolute; left: 50%; top: 40vh; transform: translate(-50%, -50%) rotate(0deg); /* Combine both translate and initial rotation */ background: url('cd/지원cd.png') no-repeat center center; background-size: contain; animation: spin 3s linear infinite; z-index: 1; } @keyframes spin { 0% { transform: translate(-50%, -50%) rotate(0deg); /* Keep the initial transform */ } 100% { transform: translate(-50%, -50%) rotate(360deg); /* Spin with the center transformation */ } } .button-container { position: absolute; bottom: 0px; /* Adjust this value to move the button higher or lower */ left: 50%; transform: translateX(-50%); z-index: 2; background: none; border: none; outline: none; } .button-container img { width: 30vw; /* Set the width of the button image to 30% of the viewport width */ height: auto; cursor: pointer; background: none; border: none; outline: none; } .side-images { position: absolute; width: 100%; height: 100%; top: 0; left: 0; display: flex; justify-content: space-between; align-items: center; z-index: 2; } .side-images a { position: absolute; cursor: pointer; } .side-images a img { width: 100%; /* Make sure the images take up the full width of the link */ height: auto; } .image1 { top: 10%; /* Adjust the position as needed */ left: 10%; /* Adjust the position as needed */ width: 10vw; /* Adjust the size as needed */ } .image2 { top: 10%; /* Adjust the position as needed */ right: 10%; /* Adjust the position as needed */ width: 10vw; /* Adjust the size as needed */ } .image3 { bottom: 10%; /* Adjust the position as needed */ left: 10%; /* Adjust the position as needed */ width: 10vw; /* Adjust the size as needed */ } .image4 { bottom: 10%; /* Adjust the position as needed */ right: 10%; /* Adjust the position as needed */ width: 10vw; /* Adjust the size as needed */ } </style> </head> <body> <div class="reel"></div> <div class="side-images"> <a href="https://github.com/JANGJIWONEDA/MadCamp_Project1.git" class="image1"> <img src="image1.png" alt="Image 1"> </a> <a href="link2.html" class="image2"> <img src="image2.png" alt="Image 2"> </a> <a href="link3.html" class="image3"> <img src="image3.png" alt="Image 3"> </a> <a href="link4.html" class="image4"> <img src="image4.png" alt="Image 4"> </a> </div> <div class="button-container"> <img id="toggleButton" src="back/지원.png" alt="Start Button"> </div> <script> const toggleButton = document.getElementById('toggleButton'); toggleButton.addEventListener('click', () => { toggleButton.src = 'back/지원1.png'; setTimeout(() => { toggleButton.src = 'back/지원.png'; window.location.href = 'opening.html'; }, 1000); }); </script> </body> </html>
ToDo
- Back url 고치기
- 산출물 넣기
- down sizing하기
- 연결 하기
또 다른 최적화 → 이미지 다운 스케일링
소장용 ending keep..
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Interactive Animation Sequence with Auto Scrolling Images</title> <style> body, html { margin: 0; padding: 0; width: 100%; height: 100%; background-color: #97F5FF; /* 배경 색상 변경 */ overflow: hidden; display: flex; justify-content: center; align-items: center; flex-direction: column; color: black; /* 텍스트 색상 설정 */ font-family: Arial, sans-serif; /* 폰트 설정 */ } .main-container { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; position: relative; } .frame-container { position: absolute; width: 100%; height: 100%; display: none; transition: transform 12s linear; } .frame { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 0.1s ease-in-out; background-size: cover; background-position: center; background-repeat: no-repeat; } #image-container { position: absolute; width: 100%; height: 12000px; /* 전체 컨텐츠 높이에 맞게 조정 */ top: 200%; /* 100%에서 200%로 변경 */ transition: none; will-change: scroll-position; will-change: transform; } .media { position: absolute; transition: transform 0.4s; will-change: scroll-position; will-change: transform; } .image { box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5); /* 그림자 설정 */ z-index: 2; content-visibility: auto; will-change: scroll-position; will-change: transform; transform: translateZ(0); } .image:hover { transform: scale(1.5) rotate(0deg) translateZ(0) !important; /* 이미지 확대와 회전을 동시에 설정, important는 명시적 지정 */ z-index: 3; will-change: scroll-position; will-change: transform; } .picture { transform: rotate(0deg); transform-origin: right center; z-index: 1; content-visibility: auto; } .video { box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5); /* 그림자 설정 */ width: 800px; height: auto; z-index: 2; transform-origin: left center; will-change: scroll-position; will-change: transform; } .video:hover { transform: scale(1.5) rotate(0deg) translateZ(0) !important;; will-change: scroll-position; will-change: transform; z-index: 3; } @font-face { font-family: 'font1'; src: url('font/font1.ttf') format('truetype'); /* format 값을 올바르게 설정 */ } .text-container { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; font-family: 'font1', sans-serif; /* font-family에서 중복 제거 및 대체 폰트 추가 */ font-size: 24px; /* 기본 폰트 크기 설정 */ color: #FFFFFF; /* 기본 텍스트 색상 설정 */ position: absolute; top: 5%; /* 텍스트 상단 위치 설정 */ left: 50%; transform: translateX(-50%); width: 80%; /* 텍스트 너비 설정 */ } .text-container p { margin: 5px 0; /* 각 텍스트 항목 간격 설정 */ } .typing-animation { position: absolute; top: 68%; left: 50%; transform: translateX(-50%); font-size: 17ㅋ0px; /* 원하는 글씨 크기로 설정 */ color: #FFFFFF; /* 원하는 글씨 색으로 설정 */ font-family: 'font1', sans-serif; /* 원하는 폰트로 설정 */ white-space: nowrap; overflow: hidden; border-right: .15em solid orange; /* 커서 효과 추가 */ animation: typing 3.5s steps(40, end), blink-caret .75s step-end infinite; } @keyframes typing { from { width: 0 } to { width: 100% } } @keyframes blink-caret { from, to { border-color: transparent } 50% { border-color: black; } } </style> </head> <body> <div class="main-container"> <div class="frame-container"> <div id="frame1" class="frame" style="background-image: url('img/outro1.png');"></div> <div id="frame2" class="frame" style="background-image: url('img/outro2.png');"></div> <div id="frame3" class="frame" style="background-image: url('img/outro3.png');"></div> <div id="frame4" class="frame" style="background-image: url('img/outro4.png');"></div> <div id="frame5" class="frame" style="background-image: url('img/outro5.png');"></div> <div id="frame6" class="frame" style="background-image: url('img/outro6.png');"></div> <div id="frame7" class="frame" style="background-image: url('img/outro7.png');"></div> <div id="frame8" class="frame" style="background-image: url('img/outro8.png');"></div> </div> <div id="image-container"> <div class="text-container"> <p style="font-size: 35px; color: #FFFFFF;">출연</p> <br> <p style="font-size: 30px; color: #FFFFFF;">공진우</p> <p style="font-size: 30px; color: #FFFFFF;">김동근</p> <p style="font-size: 30px; color: #FFFFFF;">김진영</p> <p style="font-size: 30px; color: #FFFFFF;">김문정</p> <p style="font-size: 30px; color: #FFFFFF;">김민영</p> <p style="font-size: 30px; color: #FFFFFF;">문재혁</p> <p style="font-size: 30px; color: #FFFFFF;">백승주</p> <p style="font-size: 30px; color: #FFFFFF;">오세연</p> <p style="font-size: 30px; color: #FFFFFF;">송종찬</p> <p style="font-size: 30px; color: #FFFFFF;">이동건</p> <p style="font-size: 30px; color: #FFFFFF;">이은영</p> <p style="font-size: 30px; color: #FFFFFF;">이은재</p> <p style="font-size: 30px; color: #FFFFFF;">이재희</p> <p style="font-size: 30px; color: #FFFFFF;">이현호</p> <p style="font-size: 30px; color: #FFFFFF;">임지민</p> <p style="font-size: 30px; color: #FFFFFF;">장지원</p> <p style="font-size: 30px; color: #FFFFFF;">조민주</p> <p style="font-size: 30px; color: #FFFFFF;">최정민</p> <p style="font-size: 30px; color: #FFFFFF;">하도현</p> <p style="font-size: 30px; color: #FFFFFF;">홍바다</p> <p style="font-size: 30px; color: #FFFFFF;">하준학</p> <br> <br> <p style="font-size: 35px; color: #FFFFFF;">제작</p> <br> <p style="font-size: 30px; color: #FFFFFF;">장지원</p> <p style="font-size: 30px; color: #FFFFFF;">백승주</p> </div> <img src="outro_images/image1.webp" class="media image" loading="lazy" decoding="async" style="right: 10%; top: 6%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: right center"> <img src="outro_images/image2.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 7%; width: 15%; height: auto; transform: rotate(7deg); transform-origin: left center"> <img src="outro_images/image3.webp" class="media image" loading="lazy" decoding="async" style="right: 9%; top: 12%; width: 18%; height: auto; transform: rotate(6deg); transform-origin: right center"> <img src="outro_images/image4.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 13%; width: 16%; height: auto; transform: rotate(-8deg); transform-origin: left center"> <img src="outro_images/image5.webp" class="media image" loading="lazy" decoding="async" style="right: 9%; top: 15%; width: 19%; height: auto; transform: rotate(-8deg); transform-origin: right center"> <img src="outro_images/image6.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 17%; width: 17%; height: auto; transform: rotate(10deg); transform-origin: left center"> <img src="outro_images/image7.webp" class="media image" loading="lazy" decoding="async" style="right:10%; top: 20%; width: 18%; height: auto; transform: rotate(10deg); transform-origin: right center"> <img src="outro_images/image8.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 23%; width: 17%; height: auto; transform: rotate(-9deg); transform-origin: left center"> <img src="outro_images/image9.webp" class="media image" loading="lazy" decoding="async" style="right:8%; top: 24%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: right center"> <img src="outro_images/image10.webp" class="media image" loading="lazy" decoding="async" style="left: 7%; top: 28%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: left center"> <img src="outro_images/image11.webp" class="media image" loading="lazy" decoding="async" style="right:9%; top: 30%; width: 18%; height: auto; transform: rotate(8deg); transform-origin: right center"> <video src="outro_images/image12.mp4" class="media video" loading="lazy" decoding="async" style="left: 10%; top: 34%; width: 17%; height: auto; transform: rotate(-7deg); transform-origin: left center"></video> <video src="outro_images/image13.mp4" class="media video" loading="lazy" decoding="async" style="right:10%; top: 34%; width: 25%; height: auto; transform: rotate(-10deg); transform-origin: right center"></video> <img src="outro_images/image14.webp" class="media image" loading="lazy" decoding="async" style="left: 8%; top: 40%; width: 17%; height: auto; transform: rotate(8deg); transform-origin: left center"> <!-- 2차 수정 완!--> <img src="outro_images/image15.webp" class="media image" loading="lazy" decoding="async" style="right:8%; top: 38%; width: 18%; height: auto; transform: rotate(4deg); transform-origin: right center"> <video src="outro_images/image16.mp4" class="media video" loading="lazy" decoding="async" style="left: 40%; top: 42%; width: 14%; height: auto; transform: rotate(3deg); transform-origin: center"></video> <img src="outro_images/image17.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 45%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <video src="outro_images/image18.mp4" class="media video" loading="lazy" decoding="async" style="right: 10%; top: 45%; width: 15%; height: auto; transform: rotate(-7deg); transform-origin: right center"></video> <!-- 2차 수정 완!--> <img src="outro_images/image19.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 47%; width: 18%; height: auto; transform: rotate(15deg); transform-origin: left center"> <img src="outro_images/image20.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 52%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <img src="outro_images/image21.webp" class="media image" loading="lazy" decoding="async" style="right: 7%; top: 51%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: right center"> <img src="outro_images/image22.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 53%; width: 18%; height: auto; transform: rotate(5deg); transform-origin: left center"> <img src="outro_images/image23.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 58%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <img src="outro_images/image24.webp" class="media image" loading="lazy" decoding="async" style="right: 7%; top: 59%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: right center"> <img src="outro_images/image25.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 59%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <!--마지막 컷!--> <img src="outro_images/image26.png" class="media picture" loading="lazy" decoding="async" style="left: 0%; top: 73%; width: 100%; height: auto";> <!-- 타이핑 애니메이션 컨테이너 --> <div class="typing-animation">한 달 동안 수고 많았어!</div> </div> </div> <audio id="openAudio" src="open.mp3"></audio> <script> const frameContainer = document.querySelector('.frame-container'); const frames = document.querySelectorAll('.frame'); const imageContainer = document.getElementById('image-container'); const audio = document.getElementById('openAudio'); let isAnimating = false; let currentFrame = 0; let startTime = 0; const frameTimes = [ 11.755, 11.964, 12.129, 12.315, 12.507, 12.692, 12.886, 13.071 ]; function showFrame(index) { frames.forEach(frame => frame.style.opacity = '0'); frames[index].style.opacity = '1'; } function animate() { const elapsed = audio.currentTime; // 초 단위 시간 계산 frameTimes.forEach((time, index) => { if (elapsed >= time && elapsed < time + 0.05) { // 각 프레임 시간에 해당하면 showFrame(index); } }); if (elapsed < frameTimes[frameTimes.length - 1] + 1) { requestAnimationFrame(animate); } } function startScrolling() { const totalHeight = imageContainer.offsetHeight - window.innerHeight; const duration = 100000; // 100초 동안 스크롤 const scrollStartTime = Date.now(); function smoothScroll() { const elapsedTime = Date.now() - scrollStartTime; const progress = Math.min(elapsedTime / duration, 1); const scrollY = progress * totalHeight; imageContainer.style.transform = `translateY(${-scrollY - window.innerHeight}px)`; if (progress < 1) { requestAnimationFrame(smoothScroll); } } requestAnimationFrame(smoothScroll); } function startSequence() { frameContainer.style.display = 'block'; isAnimating = true; startTime = audio.currentTime; // 전역 변수 startTime을 설정 requestAnimationFrame(animate); setTimeout(() => { isAnimating = false; setTimeout(() => { frameContainer.style.transform = 'translateY(-100vh)'; setTimeout(() => { imageContainer.style.transform = 'translateY(-200%)'; startScrolling(); }, 0); }, 6000); }, (frameTimes[frameTimes.length - 1] + 1) * 1000); // 프레임 시간이 모두 끝난 후에 실행되도록 수정 } window.onload = () => { audio.currentTime = 0; audio.play(); startSequence(); } showFrame(1); document.querySelectorAll('.video').forEach(video => { video.addEventListener('mouseover', () => { video.play(); }); video.addEventListener('mouseout', () => { video.pause(); video.currentTime = 0; }); }); const images = document.querySelectorAll('img[loading="lazy"]'); const options = { root: null, rootMargin: '0px', threshold: 1.5 }; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.getAttribute('data-src'); observer.unobserve(img); } }); }, options); images.forEach(image => { observer.observe(image); }); </script> </div> </body> </html>
.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Interactive Animation Sequence with Auto Scrolling Images</title> <style> body, html { margin: 0; padding: 0; width: 100%; height: 100%; background-color: #97F5FF; /* 배경 색상 변경 */ overflow: hidden; display: flex; justify-content: center; align-items: center; flex-direction: column; color: black; /* 텍스트 색상 설정 */ font-family: Arial, sans-serif; /* 폰트 설정 */ } .main-container { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; position: relative; } .frame-container { position: absolute; width: 100%; height: 100%; display: none; transition: transform 12s linear; } .frame { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 0.1s ease-in-out; background-size: cover; background-position: center; background-repeat: no-repeat; } #image-container { position: absolute; width: 100%; height: 12000px; /* 전체 컨텐츠 높이에 맞게 조정 */ top: 200%; /* 100%에서 200%로 변경 */ transition: none; will-change: scroll-position; will-change: transform; } .media { position: absolute; transition: transform 0.4s; will-change: scroll-position; will-change: transform; } .image { box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5); /* 그림자 설정 */ z-index: 2; content-visibility: auto; will-change: scroll-position; will-change: transform; transform: translateZ(0); } .image:hover { transform: scale(1.5) rotate(0deg) translateZ(0) !important; /* 이미지 확대와 회전을 동시에 설정, important는 명시적 지정 */ z-index: 3; will-change: scroll-position; will-change: transform; } .picture { transform: rotate(0deg); transform-origin: right center; z-index: 1; content-visibility: auto; } .video { box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5); /* 그림자 설정 */ width: 800px; height: auto; z-index: 2; transform-origin: left center; will-change: scroll-position; will-change: transform; } .video:hover { transform: scale(1.5) rotate(0deg) translateZ(0) !important;; will-change: scroll-position; will-change: transform; z-index: 3; } @font-face { font-family: 'font1'; src: url('font/font1.ttf') format('truetype'); /* format 값을 올바르게 설정 */ } .text-container { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; font-family: 'font1', sans-serif; /* font-family에서 중복 제거 및 대체 폰트 추가 */ font-size: 24px; /* 기본 폰트 크기 설정 */ color: #FFFFFF; /* 기본 텍스트 색상 설정 */ position: absolute; top: 5%; /* 텍스트 상단 위치 설정 */ left: 50%; transform: translateX(-50%); width: 80%; /* 텍스트 너비 설정 */ } .text-container p { margin: 5px 0; /* 각 텍스트 항목 간격 설정 */ } </style> </head> <body> <div class="main-container"> <div class="frame-container"> <div id="frame1" class="frame" style="background-image: url('img/outro1.png');"></div> <div id="frame2" class="frame" style="background-image: url('img/outro2.png');"></div> <div id="frame3" class="frame" style="background-image: url('img/outro3.png');"></div> <div id="frame4" class="frame" style="background-image: url('img/outro4.png');"></div> <div id="frame5" class="frame" style="background-image: url('img/outro5.png');"></div> <div id="frame6" class="frame" style="background-image: url('img/outro6.png');"></div> <div id="frame7" class="frame" style="background-image: url('img/outro7.png');"></div> <div id="frame8" class="frame" style="background-image: url('img/outro8.png');"></div> </div> <div id="image-container"> <div class="text-container"> <p style="font-size: 35px; color: #FFFFFF;">출연</p> <br> <p style="font-size: 30px; color: #FFFFFF;">공진우</p> <p style="font-size: 30px; color: #FFFFFF;">김동근</p> <p style="font-size: 30px; color: #FFFFFF;">김진영</p> <p style="font-size: 30px; color: #FFFFFF;">김문정</p> <p style="font-size: 30px; color: #FFFFFF;">김민영</p> <p style="font-size: 30px; color: #FFFFFF;">문재혁</p> <p style="font-size: 30px; color: #FFFFFF;">백승주</p> <p style="font-size: 30px; color: #FFFFFF;">오세연</p> <p style="font-size: 30px; color: #FFFFFF;">송종찬</p> <p style="font-size: 30px; color: #FFFFFF;">이동건</p> <p style="font-size: 30px; color: #FFFFFF;">이은영</p> <p style="font-size: 30px; color: #FFFFFF;">이은재</p> <p style="font-size: 30px; color: #FFFFFF;">이재희</p> <p style="font-size: 30px; color: #FFFFFF;">이현호</p> <p style="font-size: 30px; color: #FFFFFF;">임지민</p> <p style="font-size: 30px; color: #FFFFFF;">장지원</p> <p style="font-size: 30px; color: #FFFFFF;">조민주</p> <p style="font-size: 30px; color: #FFFFFF;">최정민</p> <p style="font-size: 30px; color: #FFFFFF;">하도현</p> <p style="font-size: 30px; color: #FFFFFF;">홍바다</p> <p style="font-size: 30px; color: #FFFFFF;">하준학</p> <br> <br> <p style="font-size: 35px; color: #FFFFFF;">제작</p> <br> <p style="font-size: 30px; color: #FFFFFF;">장지원</p> <p style="font-size: 30px; color: #FFFFFF;">백승주</p> </div> <img src="outro_images/image1.webp" class="media image" loading="lazy" decoding="async" style="right: 10%; top: 6%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: right center"> <img src="outro_images/image2.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 7%; width: 15%; height: auto; transform: rotate(7deg); transform-origin: left center"> <img src="outro_images/image3.webp" class="media image" loading="lazy" decoding="async" style="right: 9%; top: 12%; width: 18%; height: auto; transform: rotate(6deg); transform-origin: right center"> <img src="outro_images/image4.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 13%; width: 16%; height: auto; transform: rotate(-8deg); transform-origin: left center"> <img src="outro_images/image5.webp" class="media image" loading="lazy" decoding="async" style="right: 9%; top: 15%; width: 19%; height: auto; transform: rotate(-8deg); transform-origin: right center"> <img src="outro_images/image6.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 17%; width: 17%; height: auto; transform: rotate(10deg); transform-origin: left center"> <img src="outro_images/image7.webp" class="media image" loading="lazy" decoding="async" style="right:10%; top: 20%; width: 18%; height: auto; transform: rotate(10deg); transform-origin: right center"> <img src="outro_images/image8.webp" class="media image" loading="lazy" decoding="async" style="left: 10%; top: 23%; width: 17%; height: auto; transform: rotate(-9deg); transform-origin: left center"> <img src="outro_images/image9.webp" class="media image" loading="lazy" decoding="async" style="right:8%; top: 24%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: right center"> <img src="outro_images/image10.webp" class="media image" loading="lazy" decoding="async" style="left: 7%; top: 28%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: left center"> <img src="outro_images/image11.webp" class="media image" loading="lazy" decoding="async" style="right:9%; top: 30%; width: 18%; height: auto; transform: rotate(8deg); transform-origin: right center"> <video src="outro_images/image12.mp4" class="media video" loading="lazy" decoding="async" style="left: 10%; top: 34%; width: 17%; height: auto; transform: rotate(-7deg); transform-origin: left center"></video> <video src="outro_images/image13.mp4" class="media video" loading="lazy" decoding="async" style="right:10%; top: 34%; width: 25%; height: auto; transform: rotate(-10deg); transform-origin: right center"></video> <img src="outro_images/image14.webp" class="media image" loading="lazy" decoding="async" style="left: 8%; top: 40%; width: 17%; height: auto; transform: rotate(8deg); transform-origin: left center"> <!-- 2차 수정 완!--> <img src="outro_images/image15.webp" class="media image" loading="lazy" decoding="async" style="right:8%; top: 38%; width: 18%; height: auto; transform: rotate(4deg); transform-origin: right center"> <video src="outro_images/image16.mp4" class="media video" loading="lazy" decoding="async" style="left: 40%; top: 42%; width: 14%; height: auto; transform: rotate(3deg); transform-origin: center"></video> <img src="outro_images/image17.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 45%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <video src="outro_images/image18.mp4" class="media video" loading="lazy" decoding="async" style="right: 10%; top: 45%; width: 15%; height: auto; transform: rotate(-7deg); transform-origin: right center"></video> <!-- 2차 수정 완!--> <img src="outro_images/image19.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 47%; width: 18%; height: auto; transform: rotate(15deg); transform-origin: left center"> <img src="outro_images/image20.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 52%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <img src="outro_images/image21.webp" class="media image" loading="lazy" decoding="async" style="right: 7%; top: 51%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: right center"> <img src="outro_images/image22.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 53%; width: 18%; height: auto; transform: rotate(5deg); transform-origin: left center"> <img src="outro_images/image23.webp" class="media image" loading="lazy" decoding="async" style="left:8%; top: 58%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <img src="outro_images/image24.webp" class="media image" loading="lazy" decoding="async" style="right: 7%; top: 59%; width: 17%; height: auto; transform: rotate(9deg); transform-origin: right center"> <img src="outro_images/image25.webp" class="media image" loading="lazy" decoding="async" style="left:40%; top: 59%; width: 18%; height: auto; transform: rotate(-10deg); transform-origin: left center"> <!--마지막 컷!--> <img src="outro_images/image26.png" class="media picture" loading="lazy" decoding="async" style="left: 0%; top: 73%; width: 100%; height: auto";> </div> </div> <audio id="openAudio" src="open.mp3"></audio> <script> const frameContainer = document.querySelector('.frame-container'); const frames = document.querySelectorAll('.frame'); const imageContainer = document.getElementById('image-container'); const audio = document.getElementById('openAudio'); let isAnimating = false; let currentFrame = 0; let startTime = 0; const frameTimes = [ 11.605,11.814,11.979,12.165,12.357,12.542,12.736,12.921 ]; function showFrame(index) { frames.forEach(frame => frame.style.opacity = '0'); frames[index].style.opacity = '1'; } function animate() { const elapsed = audio.currentTime; // 초 단위 시간 계산 frameTimes.forEach((time, index) => { if (elapsed >= time && elapsed < time + 0.05) { // 각 프레임 시간에 해당하면 showFrame(index); } }); if (elapsed < frameTimes[frameTimes.length - 1] + 1) { requestAnimationFrame(animate); } } function startScrolling() { const totalHeight = imageContainer.offsetHeight - window.innerHeight; const duration = 100000; // 100초 동안 스크롤 const scrollStartTime = Date.now(); function smoothScroll() { const elapsedTime = Date.now() - scrollStartTime; const progress = Math.min(elapsedTime / duration, 1); const scrollY = progress * totalHeight; imageContainer.style.transform = `translateY(${-scrollY - window.innerHeight}px)`; if (progress < 1) { requestAnimationFrame(smoothScroll); } } requestAnimationFrame(smoothScroll); } function startSequence() { frameContainer.style.display = 'block'; isAnimating = true; startTime = audio.currentTime; // 전역 변수 startTime을 설정 requestAnimationFrame(animate); setTimeout(() => { isAnimating = false; setTimeout(() => { frameContainer.style.transform = 'translateY(-100vh)'; setTimeout(() => { imageContainer.style.transform = 'translateY(-200%)'; startScrolling(); }, 1000); }, 1000); }, (frameTimes[frameTimes.length - 1] + 1) * 1000); // 프레임 시간이 모두 끝난 후에 실행되도록 수정 } window.onload = () => { // 로딩 화면 요소 생성 const loadingScreen = document.createElement('div'); loadingScreen.id = 'loading-screen'; loadingScreen.style.position = 'fixed'; loadingScreen.style.top = '0'; loadingScreen.style.left = '0'; loadingScreen.style.width = '100%'; loadingScreen.style.height = '100%'; loadingScreen.style.backgroundColor = 'white'; loadingScreen.style.zIndex = '1000'; document.body.appendChild(loadingScreen); audio.currentTime = 0; audio.play(); startSequence(); // 로딩 화면 숨기기 setTimeout(() => { loadingScreen.style.opacity = '0'; setTimeout(() => { document.body.removeChild(loadingScreen); }, 1000); // 페이드 아웃 시간 }, 11650); // 로딩 화면 유지 시간 } showFrame(1); document.querySelectorAll('.video').forEach(video => { video.addEventListener('mouseover', () => { video.play(); }); video.addEventListener('mouseout', () => { video.pause(); video.currentTime = 0; }); }); </script> </div> </body> </html>
