如何使图像Blob URL保持不变-将具有Blob URL的图像附加到多个div

时间:2019-12-05 16:26:23

标签: javascript image async-await fetch blob

我正在尝试从远程服务器加载图像并将其显示在页面上的多个位置。我首先使用获取,创建一个新的Image并将blob转换为image 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>

2 个答案:

答案 0 :(得分:2)

您可以简单地两次创建img元素的副本。 下面我提供了一个函数,可以在给定的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]);
        }
    })
}

,该请求只会出现一次;)

答案 1 :(得分:1)

我的建议是将获得src网址并创建图像元素本身的关注点分开。您似乎有一个单例图像元素,您试图将其附加到多个父级。像

async function getData(url) {
  const response = await fetch(url);
  const data = await response.blob();

  return data;
}

function newImgFromData(data) {
  const new_img = new Image();

  new_img.src = URL.createObjectURL(data);

  return new_img;
}

然后使用这些功能,可以添加任意数量的新图像:

document.addEventListener("DOMContentLoaded", async function(){
  const im1 = await getData(url1);
  const im2 = await getData(url2); // These only need to be retrieved once

  // But you can use them to append children to both parent elements:
  let el = document.getElementById("pic1");
  el.appendChild(newImgFromData(im1));
  el = document.getElementById("pic3");
  el.appendChild(newImgFromData(im1));
  el = document.getElementById("pic2");
  el.appendChild(newImgFromData(im2));
  el = document.getElementById("pic4");
  el.appendChild(newImgFromData(im2));

  // You can even use the same image source as many times as you want:
  const another_el = document.getElementById("pic56");
  another_el.appendChild(newImgFromData(im1));

  const yet_another_el = document.getElementById("pic78");
  yet_another_el.appendChild(newImgFromData(im2));
});