Canvas调用getImageData触发跨源污染DOMException问题咨询
Canvas跨源数据污染异常解决方案
问题场景
运行MDN的Canvas绿幕抠图示例时,代码中let frame = this.ctx1.getImageData(0, 0, this.width, this.height);一行触发如下DOMException:
processor.js:29 Uncaught DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. at Object.computeFrame (file:///tmp/dom-examples/canvas/chroma-keying/processor.js:29:29) at Object.timerCallback (file:///tmp/dom-examples/canvas/chroma-keying/processor.js:6:12) at HTMLVideoElement.<anonymous> (file:///tmp/dom-examples/canvas/chroma-keying/processor.js:23:16) computeFrame @ processor.js:29 timerCallback @ processor.js:6 (anonymous) @ processor.js:23
示例核心代码如下:
let processor = { timerCallback: function() { if (this.video.paused || this.video.ended) { return; } this.computeFrame(); let self = this; setTimeout(function () { self.timerCallback(); }, 0); }, doLoad: function() { this.video = document.getElementById("video"); this.c1 = document.getElementById("c1"); this.ctx1 = this.c1.getContext("2d"); this.c2 = document.getElementById("c2"); this.ctx2 = this.c2.getContext("2d"); let self = this; this.video.addEventListener("play", function() { self.width = self.video.videoWidth / 2; self.height = self.video.videoHeight / 2; self.timerCallback(); }, false); }, computeFrame: function() { this.ctx1.drawImage(this.video, 0, 0, this.width, this.height); let frame = this.ctx1.getImageData(0, 0, this.width, this.height); let l = frame.data.length / 4; for (let i = 0; i < l; i++) { let r = frame.data[i * 4 + 0]; let g = frame.data[i * 4 + 1]; let b = frame.data[i * 4 + 2]; if (g > 100 && r > 100 && b < 43) frame.data[i * 4 + 3] = 0; } this.ctx2.putImageData(frame, 0, 0); return; } }; document.addEventListener("DOMContentLoaded", () => { processor.doLoad(); });
原因分析
浏览器同源策略限制:当视频通过file://本地协议加载,或来自其他未配置跨源许可的域名时,将视频绘制到Canvas后,Canvas会被标记为"污染"状态,禁止读取像素数据(如getImageData),以此防止跨源数据泄露。
解决方法
1. 本地开发用HTTP服务器运行
不要直接打开file://协议的本地文件,启动本地HTTP服务器托管项目:
# Python 3 python -m http.server 8000 # Python 2 python -m SimpleHTTPServer 8000
之后在浏览器访问http://localhost:8000打开示例页面,即可避免file://协议带来的跨源限制。
2. 配置视频资源的跨源许可
如果视频来自外部域名:
- 确保视频所在服务器配置CORS响应头:
Access-Control-Allow-Origin: *(或指定你的域名) - 给HTML中的
<video>标签添加crossorigin="anonymous"属性,告知浏览器以匿名模式请求视频:
<video id="video" crossorigin="anonymous" controls></video>
注意:只有服务器返回对应CORS头时,该属性才会生效,否则浏览器会拒绝加载视频。
内容的提问来源于stack exchange,提问作者Alex44
相关产品推荐
相关产品推荐

