【问题标题】: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" alt="">
    <div class="image-overlay" id="overlay"></div>
  </div>
</div>

【问题讨论】:

    标签: javascript html css animation css-transitions


    【解决方案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" alt="">
        <div class="image-overlay" id="overlay"></div>
      </div>
    </div>

    【讨论】:

    • 这更好,因为 widthtopmore 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" alt="">
        <div class="image-overlay" id="overlay"></div>
        </div>
      </div>
    </div>

    【讨论】:

    • 感谢您的回答!我试过你的代码,滞后并没有消失:(
    猜你喜欢
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多