0

我正在尝试使用PreloadJS预加载一个图像,然后将其插入 DOM 两次。但我只能插入一张图片。

var queue = new createjs.LoadQueue();
queue.addEventListener('complete', onComplete);
queue.loadManifest([{
  id: 'img',
  type: 'image',
  src: 'https://i.imgur.com/adSrF00g.png',
}, ]);
queue.load();

function onComplete(event) {
  var img = queue.getResult('img');
  var imgSrc = img.src;

  // this code inserts image to the DOM but 404 not found error appears in console
  document.getElementById('game').innerHTML = `<img src="${imgSrc}" />`;

  // this code do the same thing and 404 also appears
  var DOM_img = document.createElement("img");
  DOM_img.src = imgSrc;
  document.getElementById('game').appendChild(DOM_img);

  // this code insert the image to the DOM succesfully
  document.getElementById('game').appendChild(img);

  // but the last line does nothing - the img tag does not appear in the DOM and nothing error in the console
  document.getElementById('game').appendChild(img);
}
<script src="https://code.createjs.com/1.0.0/preloadjs.min.js"></script>
<div id="game"></div>

截图:https ://i.imgur.com/VQwAABM.jpg

我不明白为什么只出现一张图像。我做错了什么?以及如何将图像插入两次?谢谢!

4

2 回答 2

2

这很容易解决,但首先我想向您解释一些事情。

什么是Blob URLObject-URLBlob URL/Object URL是一种伪协议,允许将 Blob 和 File 对象用作图像、二进制数据下载链接等的 URL 源。

在您的情况下,如果您尝试打开这个src="blob:https://yada.yada"作为已加载图像的 src 的 blob url,它将给您一个错误并且无法打开。

是的,我知道 Teo,但是为什么如果使用 src 标签怎么可能呢?

嗯,Blob URL只能由浏览器在内部生成。所以这些元素对 Blob 或 File 对象有特殊的引用。这些 URL 只能在浏览器的单个实例和同一会话(即页面/文档的生命周期)中本地使用。

所以在这种情况下src="blob:https://yada.yada"链接到对象img创建的标签LoadQueue

那么,如何在多个元素中使用相同的图像?

在 LoadQueue 文档中,我们可以使用该方法获取Blob 对象。getResult()因此,为了重用Blob URL,我们可以“克隆” Blob对象。根据文档,getResult (value, [rawResult=false])方法被覆盖以接收此rawResult可选参数。如果此参数是true该方法将返回原始结果作为Blob 对象,而不是格式化结果。如果没有原始结果,则将返回格式化的结果。

好的,但是如何在<img>元素中使用这个 blob?

好吧,我们可以使用URL.createObjectURL()方法。此方法创建一个 DOMString,其中包含一个新的Blob URL ,该 URL表示参数中给定的Blob 对象

正如我上面解释的,这个Blob URL生命周期与创建它的窗口中的文档相关联。

这是实现:

let queue = new createjs.LoadQueue();
queue.addEventListener('complete', onComplete);
queue.loadManifest([{
  id: 'sprite',
  type: 'image',
  src: 'https://i.imgur.com/ciIyRtu.jpg?1',
}, ]);
queue.load();

function onComplete(event) {
  // Get Blob object instead of a formatted result
  let blob = queue.getResult('sprite', true);

  // Create a Blob URL using the Blob object 
  let urls = [
    URL.createObjectURL(blob),
    URL.createObjectURL(blob),
    URL.createObjectURL(blob),
  ];

  // Create a new <img> element and assign a Blob URL
  urls.forEach(function(item, index, array) {
    let DOM_img = document.createElement('img');
    DOM_img.src = item;
    document.getElementById('game').appendChild(DOM_img);
  });
}
<script src="https://code.createjs.com/1.0.0/preloadjs.min.js"></script>
<div id="game"></div>

替代解决方案(不推荐用于大文件)

您也可以使用loadManifest()不同的 id 多次加载相同的图像。然后我们定义一个fileload事件而不是complete事件来捕获每个加载的元素,检查这个例子:

let queue = new createjs.LoadQueue();
queue.addEventListener('fileload', onFileLoad);
queue.loadManifest([{
  id: 'sprite1',
  type: 'image',
  src: 'https://i.imgur.com/ciIyRtu.jpg?1',
}, {
  id: 'sprite2',
  type: 'image',
  src: 'https://i.imgur.com/ciIyRtu.jpg?1',
}, {
  id: 'sprite3',
  type: 'image',
  src: 'https://i.imgur.com/ciIyRtu.jpg?1',
}, ]);

function onFileLoad(event) {
  // Get the image element after is successfully loaded
  let img = event.result;

  // This code insert the image to the DOM succesfully
  document.getElementById('game').appendChild(img);
}
<script src="https://code.createjs.com/1.0.0/preloadjs.min.js"></script>
<div id="game"></div>

于 2019-06-12T02:05:02.113 回答
0

刚刚找到另一个解决方案,它加载一次图像,然后将其插入 dom a 两次。

var queue = new createjs.LoadQueue();
queue.addEventListener('complete', onComplete);
queue.loadManifest([{
  id: 'img',
  type: 'image',
  src: 'https://i.imgur.com/adSrF00g.png',
}, ]);
queue.load();

function onComplete(event) {
    // get loading results as blob (second argument is set to true)
    var blob = queue.getResult('img', true);
    
    // create two blob urls from one blob image source
    var blobUrl = URL.createObjectURL(blob);
    var blobUrl2 = URL.createObjectURL(blob);
    
    // create new IMG tag and set src as first blob url
    var DOM_img = document.createElement("img");
    DOM_img.src = blobUrl;
    document.getElementById('game').appendChild(DOM_img);

    // create new IMG tag and set src as second blob url
    var DOM_img2 = document.createElement("img");
    DOM_img2.src = blobUrl2;
    document.getElementById('game').appendChild(DOM_img2);
}
<script src="https://code.createjs.com/1.0.0/preloadjs.min.js"></script>
<div id="game"></div>

于 2019-06-12T21:40:33.277 回答