Estoy en una situación en la que necesito esperar hasta que la imagen se cargue una vez que la imagen se carga, necesito obtener su altura calculada para poder configurar el selector de color amarillo en consecuencia.
Pregunta: según la altura calculada de la imagen, estoy configurando el selector de color amarillo. funciona con setTimeout() aleatoriamente pero no quiero ese enfoque.
let images = ['https://via.placeholder.com/150','https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com','https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com']; let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>` document.getElementById('content').innerHTML = `<div class="box">${image}</div>`; //actual code let height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height'); let imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width'); console.log('height',height,'width',imageWidth); wrapImage = `<div style="width:calc(${imageWidth} + 10px);height:calc(${height} + 10px);position:absolute;left:0;top:0;border:1px solid yellow;"></div>`; document.querySelector('.box').insertAdjacentHTML('beforeend',wrapImage); .box{ width:100%; height:auto; border:1px solid red; position:relative; } <div id="content"> </div> con setTimeout funciona pero no quiero ese enfoque , quiero callback de llamada o algún event una vez que el elemento esté listo
let images = ['https://via.placeholder.com/150','https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com','https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com']; let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>` document.getElementById('content').innerHTML = `<div class="box">${image}</div>`; //actual code setTimeout(() => { let height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height'); let imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width'); console.log('height',height,'width',imageWidth); wrapImage = `<div class="select" style="width:calc(${imageWidth} + 10px);height:${height};position:absolute;left:0;top:0;border:1px solid yellow;"></div>`; document.querySelector('.box').insertAdjacentHTML('beforeend',wrapImage); document.querySelector('.select').height = document.querySelector('.select').height + 10; console.log('after computed height and added 10px',window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height')); },700); .box{ width:100%; height:auto; border:1px solid red; position:relative; } <div id="content"> </div>Por favor ayúdenme gracias de antemano!!!
Podría considerar agregar el detector de eventos 'cargar' como una devolución de llamada para la carga de imágenes. Por favor revise el ejemplo:
const image = document.getElementById('image'); const handler = () => { alert(image.height); }; image.addEventListener('load', handler); <img src="https://image.shutterstock.com/z/stock-vector-sample-stamp-grunge-texture-vector-illustration-1389188336.jpg" id="image" />La imagen no ha terminado de cargarse cuando recuperó el alto y el ancho. Para resolver esto, primero deberá esperar a que se carguen las imágenes y luego obtener su alto y ancho.
Escuche el evento de load de la ventana , que se activará cuando todos los recursos (incluidas las imágenes) se hayan cargado por completo:
let images = ['https://via.placeholder.com/150', 'https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com', 'https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com']; let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>` document.getElementById('content').innerHTML = `<div class="box">${image}</div>`; //actual code window.addEventListener('load', function() { let height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height'); let imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width'); console.log('height', height, 'width', imageWidth); wrapImage = `<div class="select" style="width:calc(${imageWidth} + 10px);height:${height};position:absolute;left:0;top:0;border:1px solid yellow;"></div>`; document.querySelector('.box').insertAdjacentHTML('beforeend', wrapImage); document.querySelector('.select').height = document.querySelector('.select').height + 10; console.log('after computed height and added 10px', window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height')); }); .box { width: 100%; height: auto; border: 1px solid red; position: relative; } <div id="content"> </div>Para indicar la selección, puede usar la propiedad de contorno CSS. De esa forma, no tendrá que administrar las dimensiones de la selección usted mismo.
A continuación se muestra el código de demostración. Como desea hacerlo en varias imágenes, he agregado 3 imágenes. Y puede seleccionar varias imágenes.
function changeImages() { var images = document.getElementsByTagName('img'); for (var i = 0; i < images.length; i++) { images[i].src = "https://via.placeholder.com/" + Math.floor(Math.random() * 50 + 50).toString() + "/0a0a0a/ffffff"; } } function setClickEvents() { var images = document.getElementsByTagName('img'); for (var i = 0; i < images.length; i++) { images[i].addEventListener("click", function(event) { event.target.classList.toggle("selected"); });; } } function init() { document.getElementById('content').innerHTML = `<div id="box"></div>`; var box = document.getElementById('box'); var img = document.createElement("img"); img.classList.add("selected"); box.appendChild(img); box.appendChild(document.createElement("img")); box.appendChild(document.createElement("img")); setClickEvents(); changeImages(); } #content { padding: 15px; margin: 10px; } #box { width: 100%; height: 120px; border: 1px dotted red; position: relative; } img { margin: 15px; } /* use this class for marking selected elements */ .selected { outline: thick double #f7d205; outline-offset: 7px; } <!DOCTYPE html> <html lang="en"> <body onload="init()"> <button onclick="changeImages()">Change Images</button> <div id="content"></div> </body> </html>Haga clic en la imagen para alternar la selección.
Si desea más flexibilidad, puede utilizar Resize Observer . Con esto, cuando cambie el atributo src de la etiqueta de imagen, podrá cambiar el tamaño de la selección.
const imageObserver = new ResizeObserver(function(entries) { for (let entry of entries) { var img = entry.target; let height = img.height + 10; let width = img.width + 10; console.log('Added 10px. height:', height, ' width:', width); wrapImage = `<div class="select" style="width:${width}px;height:${height}px;position:absolute;left:0;top:0;border:1px solid #f7d205;"></div>`; document.querySelector('.box').insertAdjacentHTML('beforeend', wrapImage); } }); function init() { document.getElementById('content').innerHTML = `<div id="box" class="box"></div>`; var box = document.getElementById('box'); var img = document.createElement("img"); img.src = "https://via.placeholder.com/" + Math.floor(Math.random() * 50 + 80).toString() + "/0a0a0a/ffffff"; box.appendChild(img); imageObserver.observe(img); } <!DOCTYPE html> <html lang="en"> <style> #box { width: 100%; border: 1px dotted red; position: relative; } </style> <body onload="init()"> <div id="content"></div> </body> </html>Nota: Usando el mismo ResizeObserver puede observar múltiples imágenes:
var images = document.getElementsByTagName('img'); for (var i = 0; i < images.length; i++) { imageObserver.observe(images[i]); }Editar: según lo solicitado, demostrando observar el cambio de tamaño de img desde el elemento div principal. Aquí la imagen está envuelta en div #box. Al cambiar el tamaño, img envía un evento personalizado y el padre lo maneja.
function handleChildResize(event) { console.log('parent: got it! handling it.. ') var img = event.data; let height = img.offsetHeight + 10; let width = img.offsetWidth + 10; console.log('Added 10px. height:', height, ' width:', width); wrapImage = `<div class="select" style="width:${width}px;height:${height}px;position:absolute;left:0;top:0;border:2px solid #f7d205;"></div>`; if (document.querySelector('.box > .select')) { document.querySelector('.box > .select').remove(); } document.querySelector('.box').insertAdjacentHTML('beforeend', wrapImage); event.stopPropagation(); } const imgObserver = new ResizeObserver(function(entries) { for (let entry of entries) { var img = entry.target; var event = new Event('childResized'); event.data = img; console.log("img: i am resized. Raising an event."); img.dispatchEvent(event); } }); function init() { var box = document.getElementById('box'); box.addEventListener('load', (event) => { console.log('The page has fully loaded'); }); var img = document.createElement("img"); img.src = "https://via.placeholder.com/" + Math.floor(Math.random() * 50 + 80).toString() + "/0a0a0a/ffffff"; box.appendChild(img); imgObserver.observe(img); box.addEventListener('childResized', handleChildResize, true); } <!DOCTYPE html> <html> <head> <style> #box { width: 100%; padding: 10px; border: 1px solid red; position: relative; } </style> </head> <body onload="init()"> <div id="content"> <div id="box" class="box"></div> </div> </body> </html>Veo que está creando su imgNode sobre la marcha usando ternario, lo que significa que no lo tiene creado previamente en su HTML. Entonces, para eso, puede usar la solución que se muestra a continuación creando un constructor de imágenes.
const images = [ "https://via.placeholder.com/150", "https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com", "https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com" ]; const img = new Image(); img.addEventListener("load", (ev) => { console.log(ev); document.getElementById( "content" ).innerHTML = `<div class="box">${ev.target}</div>`; const height = window .getComputedStyle(document.querySelector(".box"), null) .getPropertyValue("height"); const imageWidth = window .getComputedStyle(document.querySelector(".box img"), null) .getPropertyValue("width"); console.log("height", height, "width", imageWidth); const wrapImage = `<div style="width:calc(${imageWidth} + 10px);height:calc(${height} + 10px);position:absolute;left:0;top:0;border:1px solid yellow;"></div>`; document.querySelector(".box").insertAdjacentHTML("beforeend", wrapImage); }); img.src = `${images[Math.floor(Math.random() * images.length)]}`;Veo que desea calcular el valor final del estilo de cálculo que ve. Lo que pasa es que getComputedStyle no se actualiza. ¡Así que solo haz una función para hacerlo!
let images = ['https://via.placeholder.com/150','https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com','https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com'];' let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>` document.getElementById('content').innerHTML = `<div class="box">${image}</div>`; //actual code setTimeout(() => { let height; let imageWidth; function calculateHeightAndWidth() { height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height'); imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width'); } calculateHeightAndWidth() console.log('height',height,'width',imageWidth); wrapImage = `<div class="select" style="width:calc(${imageWidth} + 10px);height:${height};position:absolute;left:0;top:0;border:1px solid yellow;"></div>`; document.querySelector('.box').insertAdjacentHTML('beforeend',wrapImage); document.querySelector('.select').height = document.querySelector('.select').height + 10; calculateHeightAndWidth() console.log('after computed height and added 10px',window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height')); },700); .box{ width:100%; height:auto; border:1px solid red; position:relative; } <div id="content"> </div>