【问题标题】:How to make image blob URL persist - append image with blob URL to multiple divs如何使图像 blob URL 持久存在 - 将带有 blob URL 的图像附加到多个 div
【发布时间】:2019-12-06 11:24:10
【问题描述】:

我正在尝试从远程服务器加载图像并将其显示在页面上的多个位置。我首先使用 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>

【问题讨论】:

    标签: javascript image async-await fetch blob


    【解决方案1】:

    您可以简单地创建一个 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]);
            }
        })
    }
    

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

    【讨论】:

    • 谢谢,它看起来很整洁,但有一个小缺点,它会为每个图像副本额外调用服务器。
    • 是的,您可以结合dmitrydwhite 提供的答案,针对每个img url 进行单个请求
    【解决方案2】:

    我的建议是将获取src url 和创建图像元素本身的关注点分开。看起来您有一个单例图像元素,您正试图将其附加到多个父级。类似的东西

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-11
      • 2020-11-12
      • 2021-07-12
      • 2019-06-14
      • 1970-01-01
      • 2019-11-18
      • 2021-11-05
      相关资源
      最近更新 更多