为什么 getComputedStyle() 没有获取实际的宽度和高度是否存在任何回调或事件

skB*_*ore 11 html javascript css

我处于这种情况,我需要等待图像加载,一旦图像加载,我需要获取其计算的高度,以便我可以相应地设置黄色选择器。

问题:根据计算的图像高度,我设置黄色颜色选择器。它随机与 setTimeout() 一起使用,但我不想要这种方法。

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);
Run Code Online (Sandbox Code Playgroud)
.box{
   width:100%;
   height:auto;
   border:1px solid red;
   position:relative;
}
Run Code Online (Sandbox Code Playgroud)
<div id="content">

</div>
Run Code Online (Sandbox Code Playgroud)

使用 setTimeout 它可以工作,但我不想要这种方法,我想要callback或一些event一旦元素准备好

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);
Run Code Online (Sandbox Code Playgroud)
.box{
   width:100%;
   height:auto;
   border:1px solid red;
   position:relative;
}
Run Code Online (Sandbox Code Playgroud)
<div id="content">

</div>
Run Code Online (Sandbox Code Playgroud)

请帮助我提前谢谢!

Spe*_*ric 7

当您检索高度和宽度时,图像尚未完成加载。要解决此问题,您需要先等待图像加载,然后获取它们的高度和宽度。

侦听windowload事件,该事件将在所有资源(包括图像)完全加载时触发:

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'));

});
Run Code Online (Sandbox Code Playgroud)
.box {
  width: 100%;
  height: auto;
  border: 1px solid red;
  position: relative;
}
Run Code Online (Sandbox Code Playgroud)
<div id="content">

</div>
Run Code Online (Sandbox Code Playgroud)


onk*_*kar 6

要指示选择,您可以使用 CSS轮廓属性。这样您就不必自己管理选择维度。
以下是演示代码。由于您想要在多个图像上执行此操作,因此我添加了 3 个图像。并且您可以选择多个图像。

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();
}
Run Code Online (Sandbox Code Playgroud)
#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;
}
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html lang="en">

<body onload="init()">
  <button onclick="changeImages()">Change Images</button>

  <div id="content"></div>
</body>

</html>
Run Code Online (Sandbox Code Playgroud)

单击图像可切换选择。


onk*_*kar 5

如果您想要更大的灵活性,那么您可以使用Resize Observer。这样,当您更改src图像标签的属性时,您就可以更改选择大小。

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);
}
Run Code Online (Sandbox Code Playgroud)
<!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>
Run Code Online (Sandbox Code Playgroud)


注意:使用相同的 ResizeObserver 您可以观察多个图像:

var images = document.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
  imageObserver.observe(images[i]);
}
Run Code Online (Sandbox Code Playgroud)

编辑:根据要求,演示从父 div 元素观察 img 大小调整。这里图像被包裹在 div #box 中。在调整大小时,img 会调度一个自定义事件,并由父级处理它。

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);
}
Run Code Online (Sandbox Code Playgroud)
<!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>
Run Code Online (Sandbox Code Playgroud)


小智 4

您可以考虑添加“load”事件侦听器作为图像加载的回调。请检查示例:

const image = document.getElementById('image');
const handler = () => {
  alert(image.height);
};

image.addEventListener('load', handler);
Run Code Online (Sandbox Code Playgroud)
<img src="https://image.shutterstock.com/z/stock-vector-sample-stamp-grunge-texture-vector-illustration-1389188336.jpg" id="image" />
Run Code Online (Sandbox Code Playgroud)