javascript - 迭代时动态获取图像数据 URL

标签 javascript

假设我有一个包含多个图像 URL 的数组

const imgs = [
    'https://placehold.it/120x120&text=image1',
    'https://placehold.it/120x120&text=image2',
    'https://placehold.it/120x120&text=image3'
  ]

我想动态获取这些图像作为 Base 64 字符串,为网络请求做准备。我需要做什么才能使用 javascript 完成此任务?

我目前尝试过:

const getDataUrl = (url) => {
    return new Promise((resolve, reject) => {
    let img = new Image()
    let canvas = document.createElement('canvas')
    img.setAttribute('crossOrigin', 'anonymous')
    img.onload = function(){
        canvas.height = img.height
        canvas.width = img.width
        canvas.getContext('2d').drawImage(img, 0, 0)
        resolve(canvas.toDataUrl('png'))
    }
    img.src = url
  })
}

let dataUrls = []

for(let img of imgs){
    getDataUrl(img).then(res => {
    dataUrls.push(res)
  })
  console.log(dataUrls)
}

但是 promise 不会等待图像加载和解析,我得到一个空数组

所以我尝试了递归解决方案:

let dataUrl = ''

const getDataUrl = (url) => {
  let img = new Image()
  let canvas = document.createElement('canvas')
  img.setAttribute('crossOrigin', 'anonymous')
  img.onload = function(){
    canvas.height = img.height
    canvas.width = img.width
    canvas.getContext('2d').drawImage(img, 0, 0)
    dataUrl = canvas.toDataUrl('png')
  }
  img.src = url
  if(checkIntegrity()) return dataUrl
}

const checkIntegrity = () => {
  if(dataUrl.length > 0){
    return true
  }else{
    return checkIntegrity()
  }
}

这是令人讨厌的,因为我必须依赖于全局范围内的 dataUrl 并且无论如何都不起作用,因为当我运行它时,我得到了太多的递归错误。

最后,我想我可以尝试预定义 onLoad 函数并将解析函数作为参数传递给它:

const onLoad = (img, resolve) => {
  let canvas = document.createElement('canvas')
  canvas.height = img.height
  canvas.width = img.width
  canvas.getContext('2d').drawImage(img, 0, 0)
  resolve(canvas.toDataURL('png'))
}

const getDataUrl = (url) => {
    return new Promise((resolve, reject) => {
    let img = new Image()
    img.setAttribute('crossOrigin', 'anonymous')
    img.onload = onLoad(img, resolve)
    img.src = url
  })
}

for(let img of imgs){
    getDataUrl(img).then(res => {
    console.log(res)
    dataUrls.push(res)
  })
}

console.log(dataUrls)

这是我最成功的尝试,但它最终会从每次调用中返回data:,,因此它也不起作用。这是该代码的 fiddle : https://jsfiddle.net/5o4Lq3bh/34/

除此之外,我已经无计可施了。我还尝试操作 dom 安装的图像而不是 javascript 图像对象,并使用带有加载检查和不同递归函数的计数器,但我得到了相同的错误,递归太多。

我的主要问题似乎是迭代。我非常确定 for/of 是同步的,所以我猜测问题是我无法将解析传递给其他函数并期望获得有效的结果。

这在加载时很容易完成,但它必须动态发生,我们将不胜感激。

最佳答案

您共享的第一个片段和第三个片段存在一些问题。

第一个片段,您的 console.log 将始终打印一个空数组,因为它位于 then 语句之外。

for(let img of imgs){
    getDataUrl(img).then(res => {
    dataUrls.push(res)
  })
  console.log(dataUrls) // will always print [] because this statement should be within then function 
} 

第三个片段,您正在调用 onLoad 函数,而不是将其作为事件处理程序传递

img.onload = onLoad(img, resolve) // this will call onLoad, this is not an event handler

下面的代码可以工作,但这并没有利用 Promise 的全部功能

const getDataUrl = (url) => {
    return new Promise((resolve, reject) => {
    let img = new Image()
    img.setAttribute('crossOrigin', 'anonymous')
    img.onload =  function(){
      let canvas = document.createElement('canvas')
      canvas.height = img.height
      canvas.width = img.width
      canvas.getContext('2d').drawImage(img, 0, 0)
      let b64String = canvas.toDataURL('png');
      resolve(b64String)
    }
    img.src = url
  })
}

for(let img of imgs){
    getDataUrl(img).then(res => {
    dataUrls.push(res)
    console.log(dataUrls.length)
  })
}

如果您想要更清晰的方法,请使用下面的

const imgs = [
    'https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/pie.png',
    'https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/pie.png',
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/pie.png'
]    

let dataUrls = []
let images = [];

for(let imgUrl of imgs){
  images.push(new Promise((resolve, reject) => {
    let img = new Image();
    img.setAttribute('crossOrigin', 'anonymous')
    img.onload =  function(){
      let canvas = document.createElement('canvas')
      canvas.height = img.height
      canvas.width = img.width
      canvas.getContext('2d').drawImage(img, 0, 0)
      let b64String = canvas.toDataURL('png');
      dataUrls.push(b64String);
      resolve(b64String)
    }
    img.src = imgUrl
  }));
}


Promise.all(images).then(function(){
    console.log(dataUrls)
})

https://jsfiddle.net/karthick6891/5o4Lq3bh/52/

注意:仅供引用,你的 fiddle 对我也不起作用,我遇到了与每个人都发布的相同的跨源问题。

关于javascript - 迭代时动态获取图像数据 URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51505784/

相关文章:

javascript - 神秘的 html 在 iPhone 上闪烁

javascript - 为什么Apache服务器每天都会自动启动并且它会停止nodeJs?

javascript - 在 D3.js 中使用字典绘制图表

javascript - 有没有办法用 Jest 模拟私有(private)函数?

javascript - typescript :上下文保存。这样做是个好主意吗?

javascript - 元素 css 遵循 jquery 声明,而不是样式表

javascript - 使用 Comet 进行 Angular 工作

javascript - 如何传递对 aframe 组件的引用?

javascript - 遍历数组的最后几个条目

javascript - JavaScript 中的全局变量,没有 var 定义的变量