如何将图像从固定大小动画化为全屏?

How to animate image from fixed size to fullscreen?

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

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

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

所以,我想制作动画。我向 max-widthtoptransform 属性添加了过渡,但它很慢。我知道这是由于 topmax-width 属性导致的,因为浏览器的计算量很大。但是我不知道怎么用其他方式。

欢迎任何帮助!

P.S。当我写这个问题时,我发现这个实现在 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" alt="">
    <div class="image-overlay" id="overlay"></div>
  </div>
</div>

因此,我尝试了多种方法,例如不同的 css 属性、@keyframes 动画等。其中 None 有效。但是我发现当图像格式为SVG时,冻结消失了。我知道,并非所有图像都可以转换为 SVG,但看看你能做些什么。

我改变了顶部并用 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" alt="">
    <div class="image-overlay" id="overlay"></div>
    </div>
  </div>
</div>

似乎对过渡反应良好的一种方法是改变比例,而不是尝试重新定位和改变宽度等。

此代码段使图像居中并计算从初始宽度移动到 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" alt="">
    <div class="image-overlay" id="overlay"></div>
  </div>
</div>