如何将图像从固定尺寸动画到全屏?
Posted
技术标签:
【中文标题】如何将图像从固定尺寸动画到全屏?【英文标题】:How to animate image from fixed size to fullscreen? 【发布时间】:2021-12-28 04:45:03 【问题描述】:有一个网站页面,其高度和宽度等于浏览器视口的 100%(100vw 和 100vh)。
在页面中心绝对定位的包装内有一张高质量的图片 (3000x2857px)。图像包装器具有以像素为单位的最大宽度(例如 300 像素)。
此外,图像具有叠加层。我通过单击叠加将.active
类添加到图像包装器中。此类使图像包装器的最大宽度等于 100vw。
所以,我想对此进行动画处理。我添加了对max-width
、top
、transform
属性的转换,但它很滞后。我知道这是由于浏览器的大量计算导致的top
和max-width
属性。但我不知道如何以其他方式做到这一点。
欢迎任何帮助!
附:当我写这个问题时,我发现这个实现在 Safari 中是错误的。我认为转换转换在这个浏览器中不起作用,所以如果你建议在其中工作的代码会很棒:(
演示:https://codepen.io/ghettojezuz/pen/ExvGwJB
const imageWrapper = document.getElementById("image-wrapper");
const overlay = document.getElementById("overlay");
function toggleImageWrapper()
if (imageWrapper.classList.contains('active'))
imageWrapper.classList.remove('active');
else
imageWrapper.classList.add('active');
overlay.addEventListener("click", () =>
toggleImageWrapper();
)
body
min-height: 100vh;
overflow-x: hidden;
img
width: 100%;
height: auto;
.wrapper
width: 100vw;
min-height: 100vh;
height: 100%;
.image-wrapper
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
max-width: 300px;
width: 100%;
transition: max-width .8s ease, top .8s ease, transform .8s ease;
.image-wrapper.active
max-width: 100vw;
left: 50%;
top: 0;
transform: translate(-50%, 0);
.image-overlay
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
opacity: .7;
transition: background-color .3s ease;
cursor: pointer;
.image-overlay:hover
background-color: #000000;
<div class="wrapper">
<div class="image-wrapper" id="image-wrapper">
<img src="https://via.placeholder.com/3000x2857.webp" >
<div class="image-overlay" id="overlay"></div>
</div>
</div>
【问题讨论】:
【参考方案1】:似乎对过渡反应良好的一种方法是改变比例,而不是尝试重新定位和改变宽度等。
这个 sn-p 保持图像居中并计算从初始宽度移动到 100vw 所需的比例。
注意:它会删除元素上的边距以确保覆盖视口的整个宽度。
const imageWrapper = document.querySelector('.image-wrapper');
const overlay = document.querySelector('.image-overlay');
function toggleImageWrapper()
if (imageWrapper.classList.contains('active'))
imageWrapper.classList.remove('active');
else
imageWrapper.classList.add('active');
overlay.addEventListener("click", () =>
toggleImageWrapper();
)
function init()
const w = window.innerWidth;
const scale = w / imageWrapper.offsetWidth;
imageWrapper.style.setProperty('--scale', scale);
window.onload = init;
window.onresize = init;
*
padding: 0;
margin: 0;
body
min-height: 100vh;
overflow-x: hidden;
img
width: 100%;
height: auto;
.wrapper
width: 100vw;
min-height: 100vh;
height: 100%;
.image-wrapper
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
max-width: 300px;
width: 100%;
transition: .8s ease;
.image-wrapper.active
transform: translate(-50%, -50%) scale(var(--scale));
.image-overlay
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
opacity: .7;
transition: scale .3s ease;
cursor: pointer;
.image-overlay:hover
background-color: #000000;
<div class="wrapper">
<div class="image-wrapper" id="image-wrapper">
<img src="https://via.placeholder.com/3000x2857.webp" >
<div class="image-overlay" id="overlay"></div>
</div>
</div>
【讨论】:
这更好,因为width
和 top
是 more expensive 转换然后 transform
。虽然我会使用addEventListener 来防止覆盖现有的onload
和onresize
函数
同意,但这只是一个简单的独立 sn-p - 不打算只是剪切和粘贴。
感谢您的回答,解决了我的问题!我试图找到使用 scale() 的方法,但结果比我想象的要容易:) 另外我将 transform: translate(-50%, -50%) scale(var(--scale));
更改为 transform: translate(-50%, 50%) scale(var(--scale));
以不在顶部裁剪图像【参考方案2】:
所以,我尝试了多种方法,例如不同的 css 属性、@keyframes
动画等,但都没有奏效。但是我发现当图像格式为SVG时,冻结消失了。我知道,并非所有图像都可以转换为 SVG,但看看你能做些什么。
【讨论】:
感谢您的回答,但是是的,我不能使用 SVG :(【参考方案3】:我更改顶部并使用 flex 进行变换,现在当您单击时仅更改宽度,但我猜在变换动画情况下有时会发生延迟
const imageWrapper = document.getElementById("image-wrapper");
const overlay = document.getElementById("overlay");
function toggleImageWrapper()
if (imageWrapper.classList.contains('active'))
imageWrapper.classList.remove('active');
else
imageWrapper.classList.add('active');
overlay.addEventListener("click", () =>
toggleImageWrapper();
)
body
min-height: 100vh;
overflow-x: hidden;
img
width: 100%;
height: auto;
.img_container
max-width:300px;
transition: .5s;
position:relative;
.wrapper
width: 100vw;
min-height: 100vh;
height: 100%;
.image-wrapper
position: absolute;
left: 0;
top: 0;
bottom:0;
right:0;
display:flex;
align-items:center;
justify-content:center;
width: 100%;
transition: .5s;
.image-wrapper.active .img_container
max-width: 100vw;
.image-overlay
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
opacity: .7;
transition: background-color .3s ease;
cursor: pointer;
.image-overlay:hover
background-color: #000000;
<div class="wrapper">
<div class="image-wrapper" id="image-wrapper">
<div class="img_container">
<img src="https://via.placeholder.com/3000x2857.webp" >
<div class="image-overlay" id="overlay"></div>
</div>
</div>
</div>
【讨论】:
感谢您的回答!我试过你的代码,滞后并没有消失:(以上是关于如何将图像从固定尺寸动画到全屏?的主要内容,如果未能解决你的问题,请参考以下文章
在 UICollectionView 中选择时将单元格扩展到全屏