报这样的错误:
caught DOMException: Failed to execute 'texSubImage2D' on 'WebGL2RenderingContext': Tainted canvases may not be loaded.
或者报这样的错误:
caught DOMException: Failed to execute 'texImage2D' on 'WebGL2RenderingContext': Tainted canvases may not be loaded.
这是由于跨域直接使用Image对象加载图片作为纹理的时候报错的。
解决方案:
用 blob 以二进制文件的方式加载图像纹理数据,然后在生成Image对象,可以直接使用下面的TypeScript代码获取跨域的Image图像数据:
type LoadFunc = (img: HTMLImageElement, imgUrl: string) => void;
class ImgUint {
private m_listeners: LoadFunc[] = [];
url: string = "";
img: HTMLImageElement = null;
loaded = false;
constructor() { }
addListener(listener: LoadFunc): void {
let ls = this.m_listeners;
let i = 0;
for (; i < ls.length; ++i) {
if (ls[i] == listener) {
break;
}
}
if (i >= ls.length) {
ls.push(listener);
}
}
removeListener(listener: LoadFunc): void {
let ls = this.m_listeners;
for (let i = 0; i < ls.length; ++i) {
if (ls[i] == listener) {
ls.splice(i, 1);
break;
}
}
}
dispatch(): void {
if(this.loaded) {
let ls = this.m_listeners;
this.m_listeners = [];
for (let i = 0; i < ls.length; ++i) {
ls[i](this.img, this.url);
}
}
}
}
export default class ImageResLoader {
private m_map: Map<string, ImgUint> = new Map();
constructor() { }
load(url: string, onload: LoadFunc): void {
if (url != "") {
let initUrl = url;
let map = this.m_map;
url = url != "" ? url : "static/assets/box.jpg";
if (map.has(initUrl)) {
let punit = map.get(url);
if (punit.loaded) {
onload(punit.img, punit.url);
} else {
punit.addListener(onload);
}
}
let img = new Image();
let unit = new ImgUint();
unit.img = img;
unit.url = initUrl;
unit.addListener(onload);
map.set(initUrl, unit);
const request = new XMLHttpRequest();
request.open("GET", url, true);
request.responseType = "blob";
request.onload = (e) => {
img.onload = (evt: any): void => {
unit.loaded = true;
unit.dispatch();
}
let pwin: any = window;
img.src = (pwin.URL || pwin.webkitURL).createObjectURL(request.response);
};
request.onerror = e => {
console.error("load error binary image buffer request.status: ", request.status, "url:", url);
};
request.send(null);
}
}
}
当然你也可以用其他数据流的方式,例如socket直接度数据流。