📌  相关文章
📜  未捕获的 DOMException:无法在“CanvasRenderingContext2D”上执行“getImageData”:画布已被跨域数据污染. - Javascript(1)

📅  最后修改于: 2023-12-03 15:40:19.018000             🧑  作者: Mango

未捕获的 DOMException:无法在“CanvasRenderingContext2D”上执行“getImageData”:画布已被跨域数据污染. - Javascript

异常背景

当在CanvasRenderingContext2D对象上调用getImageData()方法时,如果画布已被跨域数据污染,就会抛出DOMException异常,导致程序无法顺利执行。

异常解析
异常原因

画布被污染后,只要在canvas画布中插入其他跟画布非同一域的图像或者使用drawImage()方法加载其他域中的图像,就会导致画布跨域污染,此时再调用getImageData()方法就会抛出该异常。

解决方案

1. 同源策略

在JS中,如果两个脚本文件位于不同的域名下,那么就存在跨域问题(Same-origin policy)。针对该问题,浏览器制定了同源策略(Same-origin policy),所有的现代浏览器都支持该策略,可以利用Document.domain、postMessage API 等跨域处理方式支持跨域数据访问。不过使用同源策略解决跨域问题,需要开发者在服务器端进行配置及部署,不是很方便。

2. 修改图片url地址

针对上述的跨域问题,开发者还可以使用一种简单的解决方法,就是修改跨域图片的url地址,使其与当前所在域名的url地址一致。

例如,如果在www.abc.com域名下,要在画布canvas上绘制一张跨域图片,则需要将跨域图片的url地址修改为www.abc.com/cross_origin_image.jpg,这样就避免了画布被跨域数据污染的问题。

异常处理

如果出现“未捕获的 DOMException:无法在“CanvasRenderingContext2D”上执行“getImageData”:画布已被跨域数据污染”的异常,可以尝试以下处理方案:

  1. 检查跨域资源是否与当前页面同源,如果不同源,则需要修改跨域资源的url地址;
  2. 根据业务需求调整跨域资源,避免或减少跨域污染问题;
  3. 如果需要绘制跨域资源,可以使用postMessage API 或者 Access-Control-Allow-Origin 等方式来解决跨域问题。

例子:

try {
    var imageDataObject = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
    if (e.name === 'SecurityError' || e.name === 'DOMException') {
        console.log('图片被跨域污染,无法使用getImageData()方法');
    } else {
        console.log('未知异常', e);
    }
}

以上代码演示了如何处理getImageData()方法抛出的SecurityError和DOMException异常,该异常通常情况下都是由画布跨域数据污染所导致的。