Hay una página de sitio web cuya altura y ancho son iguales al 100% de la ventana gráfica del navegador (100vw y 100vh).
Hay una imagen de alta calidad (3000x2857px) dentro de un envoltorio absolutamente posicionado en el centro de la página. El envoltorio de imagen tiene un ancho máximo en píxeles (por ejemplo, 300 px).
Además, la imagen tiene una superposición. Agrego la clase .active al envoltorio de la imagen haciendo clic en la superposición. Esta clase hace que el ancho máximo del envoltorio de imagen sea igual a 100vw.
Entonces, quiero animar esto. Agregué transición a max-width , top , transform properties, pero es lento. Sé que se debe a las propiedades top y max-width debido a los pesados cálculos del navegador. Pero no sé cómo hacerlo de otra manera.
¡Cualquier ayuda sera bienvenida!
PD Mientras escribía esta pregunta, descubrí que esta implementación tiene errores en Safari. Creo que la transición de transformación no funciona en este navegador, por lo que sería genial si sugiere un código que funcione en él :(
Demostración: 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>Un método que parece reaccionar bien a la transición es alterar la escala en lugar de intentar reposicionar y alterar el ancho, etc.
Este fragmento mantiene la imagen centrada y calcula la escala necesaria para pasar del ancho inicial a 100vw.
Nota: elimina el margen de los elementos para garantizar que se cubra todo el ancho de la ventana gráfica.
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>Por lo tanto, probé varias cosas, como diferentes propiedades css, animaciones @keyframes , etc. Ninguna de ellas funcionó. Pero descubrí que cuando el formato de imagen es SVG, el congelamiento desaparece. Lo sé, no todas las imágenes se pueden convertir a SVG, pero vea qué puede hacer al respecto.
Cambio la parte superior y transformo con flex, ahora cuando haces clic solo cambia el ancho, pero supongo que el retraso ocurrirá en algún momento en el caso de transformación de animación
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>