웹 로딩 에러 줄이는 방법
- Lazy loading이란?
: 사용자가 보지 않을 수도 있기 때문에 발생하는 메모리를 줄이기 위한 방법
: 사용자가 볼 때 로드 한다!
Lazy Loading 이란? | hello, scarlett ! enjoy your life
이를 통해 브라우저는 웹페이지를 캐시할 수 있지만 사용자가 다운로드한 모든 콘텐츠를 실제로 볼 수 있다는 보장은 없습니다.
- lazy loading의 반대: eager loading → js에서는 preloading을 사용한다.
view port 근처에 있을 때만 로딩!! // Lazy Loading with Intersection Observer const images = document.querySelectorAll('img[loading="lazy"]'); const options = { root: null, rootMargin: '0px', threshold: 10 }; 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); });
- image down scaling
08. Downsampling
이번 주제에서는 DownSampling과 그 과정에서 사용되는 filter 이야기를 해보고자 한다. 이미지의 사이즈를 줄이는 것을 Downsampling이라고 하는데(반대는 Upsampling), 사이즈를 줄이는 것은 생각보다 간단하지 않다. 결과를 먼저 보자. 위는 low pass filter를 사용하지 않고 downSampling을 한 것이며, 아래는 사용 후 진행한 것이다. 위의 영상에서는 image의 quality가 좋지 않다. (자연스럽지 않고, pixel간 차이가 너무 커서 경계가 있어 보인다. 아래는 blur해보이지만, 둘 중 한 가지를 선택한다면 아래를 선택하는 것이 원본의 신호를 그나마 더 잘 표현하였다.) Low pass filter를 사용하지 않고 downsampling을 진행하면 왜..
그 외의 지피티가 알려준 최적화 방법
- 이미지 최적화: 사용되는 이미지 파일 크기를 줄입니다. 가능하다면, 이미지 형식을 WebP와 같은 더 효율적인 형식으로 변경합니다.
- 애니메이션 최적화: CSS 애니메이션 대신, 성능이 더 좋은 Web Animations API를 사용합니다.
- 쓰로틀링 및 디바운싱: 애니메이션과 스크롤 이벤트를 더 효율적으로 처리합니다.
- Lazy Loading: 이미지를 필요할 때 로드하도록 설정합니다.
- 하드웨어 가속: CSS 애니메이션에
will-change속성을 추가하여 하드웨어 가속을 활성화합니다.
New 가설: 이미지 커지는 데 load가 크다!
→ 지금 threshold 줄이기, 시간 지연, 크기 줄이기 → 시간 지연이 영향이 큰 듯
will contain
→ 스크롤 지연
- 파일 형식
- time → 너무 많이 지연되면 이상해 진다…
- lazy
→ hover 지연
- will change
근본적인 문제!? : 랜더링 최적화?
스크린 기기는 1초에 60번을 그리는데, 브라우저에서 이를 따라잡지 못하면 애니메이션이 자연스럽지 못하고 버벅거린다.
plan
- 고르는 페이지: 떡볶이 리모컨 구현
- 프로필 페이지: cd 넣을 자리 있으면 cd 넣기(cd는 그 사람 배경 음악을 표지로 하기) + 산출물
→ page 12에 내꺼 있다.
keep.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Auto Scrolling Images and Videos with Hover Effect</title> <style> body { margin: 0; padding: 0; overflow: hidden; height: 800vh; /* 스크롤을 위해 페이지 높이 설정 */ visibility: hidden; /* 페이지 숨기기 */ } #image-container { position: relative; width: 100%; height: 100%; } .media { position: absolute; transition: transform 0.4s; /* 이미지 확대되는 속도 */ } .image { box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5); /* 그림자 설정 */ } .image:hover { transform: scale(2.0) rotate(0deg) !important; /* 이미지 확대와 회전을 동시에 설정, important는 명시적 지정 */ } .picture { transform: rotate(0deg); transform-origin: right center; /* 확대 중심을 오른쪽 중앙으로 설정 */ } .video { width: 800px; height: auto; transform-origin: left center; } .video:hover { transform: scale(2); } </style> </head> <body> <button id="startButton" style="position: fixed; top: 20px; left: 20px; z-index: 1000;">Start</button> <div id="image-container"> <!--left/right: 왼쪽/오른쪽에서 얼마나 떨어질 지, top: 위에서 얼마나 떨어질 지, --> <!--height는 auto로 맞추면 될 것 같다. --> <!--left랑 top도 상대적으로 어느정도 맞추면 될 듯 --> <img src="images/image1.png" class="media image" style="left: 20%; top: 200px; width: 20%; height: auto; transform: rotate(20deg); transform-origin: left center"> <img src="images/picture1.png" class="media picture" style="left: 40%; top: 1700px; width:60%; height: auto;"> <img src="images/image2.png" class="media image" style="right: 20%; top: 1000px; width: 20%; height: auto; transform: rotate(-20deg); transform-origin: right center"> <img src="images/image3.png" class="media image" style="left: 20%; top: 1450px; width: 20%; height: auto; transform: rotate(18deg); transform-origin: left center"> <!-- <video src="videos/video1.mp4" class="media video" style="left: 20%; top: 3300px;"></video> --> <img src="images/picture2.png" class="media picture" style="left: 10%; top: 3800px; width:60%; height: auto;"> <img src="images/image5.png" class="media image" style="left: 70%; top: 2950px; width: 20%; height: auto; transform: rotate(-15deg); transform-origin: right center"> <img src="images/picture3.png" class="media picture" style="left: 38%; top: 5600px; width:60%; height: auto;"> <img src="images/picture4.png" class="media picture" style="left: 9%; top: 7600px; width:60%; height: auto;"> <img src="images/picture5.png" class="media picture" style="left: 36%; top: 9600px; width:60%; height: auto;"> <img src="images/picture6.png" class="media picture" style="left: 20%; top: 11700px; width:40%; height: auto;"> </div> <script> window.onload = function() { document.body.style.visibility = 'visible'; } document.getElementById('startButton').addEventListener('click', () => { let scrollY = 0; function smoothScroll() { window.scrollTo(0, scrollY); scrollY += 4; // 스크롤 속도 조절 하는 부분 if (scrollY < document.body.scrollHeight) { requestAnimationFrame(smoothScroll); } } requestAnimationFrame(smoothScroll); }); // 비디오 확대 시 재생, 축소 시 일시 정지 하는 코드 document.querySelectorAll('.video').forEach(video => { video.addEventListener('mouseover', () => { video.play(); }); video.addEventListener('mouseout', () => { video.pause(); video.currentTime = 0; }); }); </script> </body> </html>
keep2.
<!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%); } } #image-container { position: absolute; width: 100%; height: 25000px; /* 전체 컨텐츠 높이에 맞게 조정 */ top: 200%; /* 100%에서 200%로 변경 */ transition: none; } .media { position: absolute; transition: transform 0.4s; } .image { box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5); /* 그림자 설정 */ z-index: 2; } .image:hover { transform: scale(2.0) rotate(0deg) !important; /* 이미지 확대와 회전을 동시에 설정, important는 명시적 지정 */ z-index: 2; } .picture { transform: rotate(0deg); transform-origin: right center; z-index: 1; box-shadow: 0 0 0 12px white, 0 0 0 16px black; /* 여기에 추가 */ } </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.png" class="media picture" loading="lazy" style="left: 25%; top: 10%; width:70%; height: auto;"> <img src="images/picture2.png" class="media picture" loading="lazy" style="left: 10%; top: 20%; width:70%; height: auto;"> <img src="images/picture3.png" class="media picture" loading="lazy" style="left: 25%; top: 30%; width:70%; height: auto;"> <img src="images/picture4.png" class="media picture" loading="lazy" style="left: 10%; top: 40%; width:70%; height: auto;"> <img src="images/picture5.png" class="media picture" loading="lazy" style="left: 25%; top: 50%; width:70%; height: auto;"> <img src="images/picture6.png" class="media picture" loading="lazy" style="left: 10%; top: 60%; width:70%; height: auto;"> <img src="images/picture7.png" class="media picture" loading="lazy" style="left: 25%; top: 70%; width:70%; height: auto;"> <!--image--> <img src="images/image1.png" class="media image" loading="lazy" style="left: 10%; top: 5%; width: 20%; height: auto; transform: rotate(20deg); transform-origin: left center"> <img src="images/image2.png" class="media image" loading="lazy" style="right: 10%; top: 7%; width: 19%; height: auto; transform: rotate(-18deg); transform-origin: right center"> <img src="images/image3.png" class="media image" loading="lazy" style="left: 19%; top: 10%; width: 16%; height: auto; transform: rotate(10deg); transform-origin: left center"> <img src="images/image4.png" class="media image" loading="lazy" style="left: 17%; top: 13%; width: 20%; height: auto; transform: rotate(35deg); transform-origin: left center"> <img src="images/image5.png" class="media image" loading="lazy" style="right: 10%; top: 15%; width: 20%; height: auto; transform: rotate(-10deg); transform-origin: right center"> <img src="images/image6.png" class="media image" loading="lazy" style="left: 10%; top: 18%; width: 22%; height: auto; transform: rotate(-7deg); transform-origin: left center"> <img src="images/image7.png" class="media image" loading="lazy" style="right: 15%; top: 19%; width: 13%; height: auto; transform: rotate(0deg); transform-origin: right center"> <img src="images/image8.png" class="media image" loading="lazy" style="left: 10%; top: 24%; width: 15%; height: auto; transform: rotate(5deg); transform-origin: left center"> <img src="images/image9.png" class="media image" loading="lazy" style="right: 5%; top: 23%; width: 17%; height: auto; transform: rotate(-5deg); transform-origin: right center"> <!--2차 수정 완--> <img src="images/image10.png" class="media image" loading="lazy" style="left: 15%; top: 28%; width: 15%; height: auto; transform: rotate(20deg); transform-origin: left center"> <img src="images/image11.png" class="media image" loading="lazy" style="right: 3%; top: 29%; width: 23%; height: auto; transform: rotate(-15deg); transform-origin: right center"> <img src="images/image12.png" class="media image" loading="lazy" style="right: 2%; top: 34%; width: 25%; height: auto; transform: rotate(0deg); transform-origin: right center"> <img src="images/image13.png" class="media image" loading="lazy" style="left: 7%; top: 34%; width: 19%; height: auto; transform: rotate(10deg); transform-origin: left center"> <img src="images/image14.png" class="media image" loading="lazy" style="right: 10%; top: 39%; width: 23%; height: auto; transform: rotate(0deg); transform-origin: right center"> <img src="images/image15.png" class="media image" loading="lazy" style="left: 15%; top: 43%; width: 23%; height: auto; transform: rotate(5deg); transform-origin: left center"> <!--2차 수정 완--> <img src="images/image16.png" class="media image" loading="lazy" style="left: 5%; top: 47%; width: 20%; height: auto; transform: rotate(0deg); transform-origin: left center"> <img src="images/image17.png" class="media image" loading="lazy" style="right: 10%; top: 50%; width: 17%; height: auto; transform: rotate(-16deg); transform-origin: right center"> <!-- <img src="images/image18.png" class="media image" style="right: 20%; top: 54%; width: 18%; height: auto; transform: rotate(-5deg); transform-origin: right center"> --> <!--2차 수정 완--> <img src="images/image19.png" class="media image" loading="lazy" style="left: 2%; top: 55%; width: 20%; height: auto; transform: rotate(20deg); transform-origin: left center"> <!-- <img src="images/image20.png" class="media image" style="left: 50%; top: 56%; width: 15%; height: auto; transform: rotate(0deg); transform-origin: right center"> --> <img src="images/image21.png" class="media image" loading="lazy" style="right: 1%; top: 58%; width: 20%; height: auto; transform: rotate(3deg); transform-origin: right center"> <!--2차 수정 완--> <img src="images/image22.png" class="media image" loading="lazy" style="left: 1%; top: 61%; width: 20%; height: auto; transform: rotate(-2deg); transform-origin: left center"> <img src="images/image23.png" class="media image" loading="lazy" style="left: 10%; top: 67%; width: 16%; height: auto; transform: rotate(0deg); transform-origin: left center"> <img src="images/image24.png" class="media image" loading="lazy" style="right: 5%; top: 69%; width: 25%; height: auto; transform: rotate(10deg); transform-origin: right center"> <img src="images/image25.png" class="media image" loading="lazy" style="right: 3%; top: 73%; width: 20%; height: auto; transform: rotate(-3deg); transform-origin: right center"> <img src="images/image26.png" class="media image" loading="lazy" style="left: 5%; top: 75%; width: 16%; height: auto; transform: rotate(10deg); transform-origin: left center"> <img src="images/image27.png" class="media image" loading="lazy" style="right: 10%; top: 77%; width: 20%; height: auto; transform: rotate(10deg); transform-origin: right center"> </div> </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'); 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 = 90000; // 60초 동안 스크롤 (필요에 따라 조정) 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); } cassetteContainer.addEventListener('click', () => { 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(); cdplAudio.onended = () => { 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); </script> </body> </html>
