图片:hover交互效果实现后,布局与代码优化问题求助
问题解决与代码优化方案
1. 图案居中显示在衬衫图片上
当前图案未居中是因为.scale元素的原点设置偏移,且容器未做居中对齐。修改如下:
- 给
.art容器添加居中布局,确保图案处于容器中心:
.grid-container > div > .art { grid-area: 1/1; transition: .5s; display: grid; place-items: center; }
- 调整
.scale和对应动画的原点为中心:
.grid-container > div > .art > .scale { max-width: 50%; transform-origin: center; } .scale { opacity: 0; transform-origin: center; } @keyframes scale { 0%{ transform-origin: center; transform: scale(0,0); opacity: 0; } 100%{ transform-origin: center; transform: scale(1,1); opacity: 1; } }
- 移除 hover 时
.art的底部原点设置:
.grid-container div:hover .art { transform: scale(2); }
2. 限制衬衫图片不超过原始尺寸
通过给.shirt容器设置宽度限制,确保图片最大显示为原始尺寸:
.grid-container > div > .shirt { grid-area: 1/1; transition: .5s; max-width: fit-content; } .grid-container > div > .shirt > .slideup { max-width: 100%; width: 100%; }
这样容器宽度不会超出图片原始尺寸,图片也就不会被过度放大。
3. 简化JavaScript代码
将重复的IntersectionObserver实例合并为一个,通过类名匹配对应动画:
const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { const target = entry.target; let animationName = ''; let duration = '1s'; if (target.classList.contains('anim')) { animationName = 'square-animation'; duration = '.5s'; } else if (target.classList.contains('slideup')) { animationName = 'slideup'; } else if (target.classList.contains('scale')) { animationName = 'scale'; } else if (target.classList.contains('sliding')) { animationName = 'sliding'; duration = '.5s'; } if (entry.intersectionRatio > 0) { target.style.animation = `${animationName} ${duration} ${target.dataset.delay} forwards ease-out`; } else { target.style.animation = 'none'; } }); }); const elements = document.querySelectorAll('.anim, .slideup, .scale, .sliding'); elements.forEach(el => observer.observe(el));
优化后完整代码
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>HOME</title> <link rel="stylesheet" href="stylesheet.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullPage.js/4.0.11/fullpage.min.css" integrity="sha512-NGRhMiWY9pf5z8PLens7/u+LLwIPAu1dhJ7u9sHRWIo8TKrVbKiWlRdYRH3pVDCZA10zmobo+PBLGeLOREklBw==" crossorigin="anonymous" referrerpolicy="no-referrer" /> </head> <body> <div id="fullpage"> <div class="section one"> <div class="grid-title-container"> <div class="title-bar anim" data-delay=".1s"> <p class="title-text"> First Banner </p> </div> <div class="grid-container "> <div> <div class="shirt"> <img src="https://i.imgur.com/oS8QWPI.png" class="slideup" data-delay=".4s"> </div> <div class="art"> <img src="https://i.imgur.com/jeNzULX.png" class="scale" data-delay="1s"> </div> </div> <div> <div class="shirt"> <img src="https://i.imgur.com/oS8QWPI.png" class="slideup" data-delay=".6s"> </div> <div class="art"> <img src="https://i.imgur.com/jeNzULX.png" class="scale" data-delay="1.2s"> </div> </div> <div> <div class="shirt"> <img src="https://i.imgur.com/oS8QWPI.png" class="slideup" data-delay=".8s"> </div> <div class="art"> <img src="https://i.imgur.com/jeNzULX.png" class="scale" data-delay="1.4s"> </div> </div> </div> </div> </div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/fullPage.js/4.0.11/fullpage.min.js" integrity="sha512-ojnoeSkK5NDwnuW5S0ZnddobHez8Bx1yVa3RE+Cd0fGEuY/NEd4sgVF/CJ6eDtnOeLZLbTJpNFrCkUYbHS2hRA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script src="script.js"></script> <script> new fullpage('#fullpage', { autoScrolling: true, scrollHorizontally: true }); </script> </body> </html>
CSS
.section { height: 100%; width: 100%; display: block; } .section.one{ background-color: rgb(6, 65, 65); } .title-bar { display: flex; overflow: visible; width: 100vw; height: 8vh; max-width: 70vw; min-height: 1vh; margin-top: 5vh; margin-bottom: 5vh; margin-right: auto; margin-left: auto; justify-content: center; align-items: center; border-top-style: solid; border-top-width: 1vh; border-top-color: #28f7e6; border-bottom-style: solid; border-bottom-width: 1vh; border-bottom-color: #28f7e6; perspective-origin: 50% 50%; transform-origin: 50% 50%; } .title-text { text-align: center; font-size: 6vh; margin: 0px 0px; font-family: PT Serif; color: #28f7e6; } .grid-container { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; grid-column-gap: 1%; max-width:70%; margin:auto; } .grid-container > div { display: grid; place-items: center; } .grid-container > div > .shirt { grid-area: 1/1; transition: .5s; max-width: fit-content; } .grid-container > div > .art { grid-area: 1/1; transition: .5s; display: grid; place-items: center; } .grid-container > div > .shirt > .slideup { max-width: 100%; width: 100%; } .grid-container > div > .art > .scale { max-width: 50%; transform-origin: center; } .grid-container div:hover .shirt { transform: scale(0); } .grid-container div:hover .art { transform: scale(2); } .anim { opacity: 0; } .slideup { opacity: 0; } .scale { opacity: 0; transform-origin: center; } .sliding { opacity: 0; } @keyframes square-animation { 0%{ transform: scale(0, 1); opacity: 0; } 100%{ transform: scale(1, 1); opacity: 1; } } @keyframes slideup { 0%{ transform: translate(0px,50%); opacity: 0; } 100%{ transform: translate(0px,0px); opacity: 1; } } @keyframes scale { 0%{ transform-origin: center; transform: scale(0,0); opacity: 0; } 100%{ transform-origin: center; transform: scale(1,1); opacity: 1; } } @keyframes rotate { 0%{ transform: rotate(90deg); opacity: 0; } 100%{ transform: rotate(0deg); opacity: 1; } } @keyframes sliding { 0%{ transform: translate(50px,10px); opacity: 0; } 100%{ transform: translate(0px,0px); opacity: 1; } }
JavaScript
const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { const target = entry.target; let animationName = ''; let duration = '1s'; if (target.classList.contains('anim')) { animationName = 'square-animation'; duration = '.5s'; } else if (target.classList.contains('slideup')) { animationName = 'slideup'; } else if (target.classList.contains('scale')) { animationName = 'scale'; } else if (target.classList.contains('sliding')) { animationName = 'sliding'; duration = '.5s'; } if (entry.intersectionRatio > 0) { target.style.animation = `${animationName} ${duration} ${target.dataset.delay} forwards ease-out`; } else { target.style.animation = 'none'; } }); }); const elements = document.querySelectorAll('.anim, .slideup, .scale, .sliding'); elements.forEach(el => observer.observe(el));
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

