D3.js 使用 Promises 拉取和嵌入 DataURI 图像

D3.js pulling and embedding DataURI images with Promises

我正在构建一个依赖于大量小光栅图像的数据可视化,这些图像通过 JSON API 作为 AWS URL 提供。

这工作得相当好,直到我尝试实施我的下一步,即将数据可视化呈现为 PNG 以供下载。在 PNG 中,光栅图像已损坏。

我知道要解决这个问题,我需要将图像嵌入为数据 URL。

这是我目前得到的:

const companies_base64 = companies.map(c => {
  var o = Object.assign({}, c)
  o.base64 = imageToBase64(c.mimetype, c.logo)
  return o
})

其中 companies 是一个对象数组。这是 imageToBase64,Heroku 应用程序是 CORS anywhere 的克隆:

function imageToBase64(mimetype, logo) {
  var url = 'https://example.herokuapp.com/' + logo
  return d3.blob(url)
           .then(blob => blobToBase64(blob))
           .then(base64 => mimetype + base64)
           .catch(error => console.error(error))
}

function blobToBase64(blob) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader()
    reader.onload = () => {
      let dataUrl = reader.result
      let base64 = dataUrl.split(',')[1]
      resolve(base64)
    }
    reader.onerror = () => {
      reject("Error")
    }
    reader.readAsDataURL(blob)
  })
}

这导致在 companies_base64 中的任何对象上调用 base64 时返回 Promise[[PromiseValue]] 当然是我所追求的。我应该如何确保它是返回的内容,以便我最终可以将它放在 <svg><image>xlink:href 属性中?

我认为一旦它工作并且我可以在任何地方调用 imageToBase64,这是我只想在用户按下 下载 时做的事情。我想我可以使用 D3 来做到这一点,迭代 <image>s 并换出它们的 xlink:href。还是我应该换一种方式?

我还尝试将图像作为对象获取,然后在我的 RoR 后端将它们转换为 base64,以便它们通过 Image#to_base64 方法与 JSON 打包在一起。这确实有效,但 A) 感觉很不对,B) 在初始加载时显然很慢。

感谢您的宝贵时间,我是初学者,请多多包涵。

您的 imageToBase64 函数 returns 一个承诺,而不是已解析的数据 URL。这意味着您必须等待才能将它们附加到 companies_base64 成员。您可以选择在单个 base64 字符串准备好后立即执行此操作,或者等待所有字符串:

Promise.all(companies.map(c => {
     return imageToBase64(c.mimetype, c.logo)
         .then(u => Object.assign({ base64: u }, c))
         .then(/* change the image reference here one by one... */)
}))
.then(companies_base64 => /* ...or here, in a loop over the array */)
.catch(error => console.error(error))