首页 > 解决方案 > 如何使图像 blob URL 持久存在 - 将带有 blob URL 的图像附加到多个 div

问题描述

我正在尝试从远程服务器加载图像并将其显示在页面上的多个位置。我首先使用 fetch 来执行此操作,创建一个新图像,并将 blob 转换为图像 src。但是,似乎只显示了图像的第一次使用。

我在这里有什么明显的遗漏吗?

如何让下面的代码显示每个图像两次,而不是一次?

let url1 = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Wales_versus_New_Zealand_scrum_1905_-_cropped.jpg/800px-Wales_versus_New_Zealand_scrum_1905_-_cropped.jpg"
let url2 = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/46/France_versus_Wales_in_rugby_union_1922_-_cropped.jpg/800px-France_versus_Wales_in_rugby_union_1922_-_cropped.jpg"


async function getImgFromUrl(url){
  let response = await fetch(url);
  data = await response.blob();
  let image = new Image();
  image.src = URL.createObjectURL(data);
  return image;
}

document.addEventListener("DOMContentLoaded", async function(){
  let im1 = await getImgFromUrl(url1);
  let el = document.getElementById("pic1")
  el.appendChild(im1)
  el = document.getElementById("pic3")
  el.appendChild(im1)
  let im2 = await getImgFromUrl(url2);
  el = document.getElementById("pic2")
  el.appendChild(im2)
  el = document.getElementById("pic4")
  el.appendChild(im2)
})
  .grid {
          display:grid;
          grid-template: auto auto / auto auto;
          height: 100%;
          width: 100%;
          grid-gap: 5px;
          max-width:500px;
          }


  img {
    max-width:250px;
  }
  <div class = 'grid'>
    <div id = 'pic1'></div>
    <div id = 'pic2'></div>
    <div id = 'pic3'></div>
    <div id = 'pic4'></div>
  </div>

标签: javascriptimageasync-awaitfetchblob

解决方案


您可以简单地创建 img 元素的副本 2 次。下面我提供了一个函数来根据给定的 url 创建多个元素

/*url: url of the images
 *ids: array of elements to be appended with the images
 */
function append_twice(url, ...ids){
    Promise.all(ids.map(async _=>await getImgFromUrl(url)))
    .then(imgs=>{
        for(let i=0;i<ids.length;i++){
            document.getElementById(ids[i]).appendChild(imgs[i]);
        }
    })
}

并且使用它的方式就是这样

document.addEventListener("DOMContentLoaded", async function(){
  append_twice(url1,"pic1","pic3");
  append_twice(url2,"pic2","pic4");
})

编辑

为避免多次调用服务器,您可以使用dmitrydwhite的建议

function append_twice(url, ...ids){
    Promise.resolve(getData(url))
    .then(blob=>{
        return Promise.all(ids.map(async _=>await newImgFromData(blob)));
    })
    .then(imgs=>{
        for(let i=0;i<ids.length;i++){
            document.getElementById(ids[i]).appendChild(imgs[i]);
        }
    })
}

并且请求只会发生一次;)


推荐阅读