如何将图像从固定尺寸动画到全屏?

Posted

技术标签:

【中文标题】如何将图像从固定尺寸动画到全屏?【英文标题】:How to animate image from fixed size to fullscreen? 【发布时间】:2021-12-28 04:45:03 【问题描述】:

有一个网站页面,其高度和宽度等于浏览器视口的 100%(100vw 和 100vh)。

在页面中心绝对定位的包装内有一张高质量的图片 (3000x2857px)。图像包装器具有以像素为单位的最大宽度(例如 300 像素)。

此外,图像具有叠加层。我通过单击叠加将.active 类添加到图像包装器中。此类使图像包装器的最大宽度等于 100vw。

所以,我想对此进行动画处理。我添加了对max-widthtoptransform 属性的转换,但它很滞后。我知道这是由于浏览器的大量计算导致的topmax-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>

【讨论】:

这更好,因为 widthtop 是 more expensive 转换然后 transform。虽然我会使用addEventListener 来防止覆盖现有的onloadonresize 函数 同意,但这只是一个简单的独立 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>

【讨论】:

感谢您的回答!我试过你的代码,滞后并没有消失:(

以上是关于如何将图像从固定尺寸动画到全屏?的主要内容,如果未能解决你的问题,请参考以下文章

将图像从缩略图动画到全屏

如何将collectionview单元格扩展到全屏[关闭]

在 UICollectionView 中选择时将单元格扩展到全屏

Qt Creator,全屏视图

DIV+CSS,怎样将背景图片拉伸到全屏!! 谢谢各位了 急呀~~~

如何使用 SwiftUI 将详细视图扩展到全屏?