D3.js вытягивает и встраивает изображения DataURI с Promises - PullRequest
0 голосов
/ 21 февраля 2019

Я создаю визуализацию данных, которая опирается на множество небольших растровых изображений, предоставляемых в виде URL-адресов AWS через JSON API.

Это работает довольно хорошо, пока я не попытаюсь реализовать мой следующий шаг - визуализация данных в виде 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 в любом месте :

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

, что приводит к возвращению Promise при вызове base64 для любого из объектов вcompanies_base64, [[PromiseValue]] - это, конечно, то, что я ищу.Как я должен убедиться, что это то, что возвращается, чтобы я мог, в конечном счете, поместить его в атрибуты xlink:href <image> s в моих <svg>?

Я думаю, что как только это сработаети я могу позвонить imageToBase64 куда угодно, это то, что я хочу сделать, только когда пользователь нажимает Download .Я полагаю, что могу сделать это, используя D3, перебирая <image> s и меняя их xlink:href.Или я должен пойти по-другому?

Я также попытался получить изображения в виде объектов и затем преобразовать их в base64 в моем бэкэнде RoR, чтобы они были упакованы с JSON, с помощью метода Image#to_base64,Это работает, но это A) чувствует себя очень неправильно и B) очевидно очень медленно при начальной загрузке.

Спасибо за ваше время и, пожалуйста, потерпите меня, поскольку я новичок.

1 Ответ

0 голосов
/ 22 февраля 2019

Ваша функция imageToBase64 возвращает обещание, а не 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))
...