简体   繁体   English

.appendChild和window.print();

[英].appendChild and window.print();

I have the following code: 我有以下代码:

const printString = // a long string w/ several base64 encoded images;
const printContainer = document.createElement('div');
printContainer.innerHTML = printString;
document.body.appendChild(printContainer);
window.print();

printString is a long string with several largeish base64 encoded images included. printString是一个长字符串,其中包含一些较大的base64编码图像。 The string gets set as the innerHTML of the printContainer and then the whole thing gets printed. 将该字符串设置为printContainerinnerHTML ,然后打印整个内容。

This works okay, but on the initial load of the page, it apparently takes the browser a moment to render the base64 encoded images and in that time, window.print() goes ahead and fires, before all the images have actually loaded into the DOM . 这样做可以,但是在页面的初始加载时,显然需要浏览器花一点时间来呈现base64编码的图像, 然后在所有图像实际加载到 window.print()之前, window.print()继续执行并触发。 DOM

That is, window.print() can fire before .innerHTML has finished rendering the new element. 也就是说,可以在.innerHTML完成呈现新元素之前触发window.print()

If I add a brief delay to the window.print() , then everything works fine. 如果我在window.print()添加了短暂的延迟,那么一切都会正常。 Like so: 像这样:

const printString = // a long string w/ several base64 encoded images;
const printContainer = document.createElement('div');
printContainer.innerHTML = printString;
document.body.appendChild(printContainer);
setTimeout(() => {
    window.print();
}, 100);

This isn't a great solution, however, and I would really like to find a solution along the lines of "you just wait until .innerHTML() is actually finished, window.print(); 但是,这不是一个很好的解决方案,我真的很想找到一种解决方案,例如“您只等.innerHTML()实际完成, window.print();

All of this is tested in Chrome, so far. 到目前为止,所有这些功能都已在Chrome中进行了测试。

Any ideas appreciated! 任何想法表示赞赏!

Edit: an answer 编辑:答案

This is a modest reworking of @Keith's answer below. 这是@Keith在下面的答案的适度修改。

const imgs = document.querySelectorAll('img.images-in-question');
function checkDone() {
  if (ready === imgs.length) {
    // do stuffs
  }
}
function incrementReady(){
  ready++;
  checkDone();
}
for (const img of imgs) {
  if (img.complete) ready++;
  else {
    img.addEventListener('load', incrementReady);
  }
}
checkDone();

Below is a simple script to wait for all images to load. 下面是一个等待所有图像加载的简单脚本。

It basically does a querySelectAll to get all the images, and then attaches the onload event, when the amount of images loaded is equal to the amount of images in the list, everything is then loaded. 它基本上执行querySelectAll来获取所有图像,然后附加onload事件,当加载的图像数量等于列表中的图像数量时,所有内容都将被加载。

This then will of course work with both external URL, and data uri's.. 然后,这当然可以与外部URL和数据uri一起使用。

Update, noticed a slight issue with my original image load check, in Chrome sometimes the onload is not fired, I assume it's because if it can pull the resources from cache, it might get loaded before the onload event is even attached, as such I've added a check for the complete flag first. 更新,发现我的原始图像加载检查有一个小问题,在Chrome中有时不会触发onload,我认为这是因为如果它可以从缓存中提取资源,那么它可能会在附加onload事件之前onload加载,因此我首先添加了对完成标志的检查。 This seems to fix the issue.. 这似乎解决了问题。

 const imgs = document.querySelectorAll("img"); let waiting = 0; let count = 0; function checkDone() { if (count === waiting) { console.log("all images loaded"); } } for (const img of imgs) { if (!img.complete) waiting ++; else img.addEventListener('load', () => { count ++; checkDone(); }); } checkDone(); 
 <img src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" style="width:100px;height:100px"> <img src="https://via.placeholder.com/350x150.svg"> <img src="https://via.placeholder.com/300x100.svg"> <img src="https://via.placeholder.com/200x400.svg"> 

This would be a good case to use requestAnimationFrame . 这是使用requestAnimationFrame一个好例子。

const printString = // a long string w/ several base64 encoded images;
const printContainer = document.createElement('div');
printContainer.innerHTML = printString;
document.body.appendChild(printContainer);
requestAnimationFrame(function () {
    window.print();
});

requestAnimationFrame waits for the next paint and then runs the function, thus you can be sure that window.print() won't run until just after the HTML has been rendered. requestAnimationFrame等待下一次绘制,然后运行该函数,因此可以确保window.print()直到HTML呈现后才运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM