使用blob解决canvas跨域的问题

如果想要获取一个图片上某个像素点的色值,可以使用canvas的getImageData来拿到数据,但是在canvas中,跨域图片是不能获取其图像信息的,如果取跨域的图片像素信息,就会出现跨域错误。

例如如下代码

const url = 'https://developer.mozilla.org/static/img/web-docs-sprite.22a6a085cf14.svg'
const img = new Image()
img.onload = function () {
  ctx.drawImage(img, 0, 0)
  addEventListener('click', pick)
}

img.src = url
function pick (e) {
  const data = ctx.getImageData(e.layerX, e.layerY, 1, 1).data
  console.log(data)
}

点击canvas画布,将会抛出The canvas has been tainted by cross-origin data.,这是因为url中的图片地址是跨域的。

解决这个问题,首先你要在服务端允许该资源跨域访问,另外,在img上添加一个crossOrigin属性就可以解决跨域的问题了

img.crossOrigin = ''

这个属性的介绍可以参考MDN(启用了 CORS 的图片)

除了上面这个办法,还可以使用blob来解决这个问题,关于Blob,之前的文章中也有介绍“JavaScript中的Blob对象”。

这里需要多发出一条ajax请求(同样,该资源是允许跨域的才可以),将数据返回为blob对象形式,直接上代码(代码片段)

const url = 'https://developer.mozilla.org/static/img/web-docs-sprite.22a6a085cf14.svg'

const xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.responseType = 'blob'

xhr.onload = function () {
  if (this.status === 200) {
    const blob = this.response

    const img = new Image()
    const imgObject = URL.createObjectURL(blob)
    img.onload = function () {
      ctx.drawImage(img, 0, 0)
      canvas.addEventListener('click', pick)
      document.body.removeChild(img)
      URL.revokeObjectURL(imgObject)
    }
    img.src = imgObject
    document.body.appendChild(img)
  }
}

xhr.send()

function pick (e) {
  const data = ctx.getImageData(e.layerX, e.layerY, 1, 1).data
  console.log(data)
}

记得资源使用完毕后,要手动调用URL.revokeObjectURL释放资源。

如果您觉得本文对您有用,欢迎捐赠或留言~
微信支付
支付宝

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注