跨域图片存在一些问题,希望您能为您提供帮助。
这里的行为。
例如,我有2个域:
-domain1.com
-domain2.com
在domain1上,我放置了许多html5游戏。该域只是游戏库。
Domain2是真实的网站(wordpress网站),用户可以在其中玩Domain1上托管的游戏。
为此,我对每个游戏都提出了卷曲要求。
在domain1 nginx配置文件中,我放置了以下代码行以启用跨源资源共享:
位置〜* \。(ogg | ogv | svg | svgz | eot | otf | woff | mp4 | ttf | css | rss | atom | json | js | jpg | jpeg | gif | png | ico | zip | tgz | gz | rar | bz2 | doc | xls | exe | ppt | tar | mid | midi | wav | bmp | rtf | swf | mp3 | xml | woff2)$ {
add_header“访问控制允许来源”“ *”;
access_log关闭;
log_not_found关闭;
最多到期;
}
这解决了许多游戏的一些问题,但某些游戏仍然无法正常工作,并且出现了js错误:
未捕获的DOMException:无法在“ WebGLRenderingContext”上执行“ texImage2D”:可能无法加载位于http://domain1.com/html5-games/action/candy-match/images/loadingbarbackground-sheet0.png的跨域图像。
GLWrap_.loadTexture(http://domain1.com/html5-games/action/candy-match/c2runtime.js:2618:16)
在pluginProto.Type.typeProto.loadTextures(http://domain1.com/html5-games/action/candy-match/c2runtime.js:18070:46)
在pluginProto.Instance.instanceProto.onCreate(http://domain1.com/html5-games/action/candy-match/c2runtime.js:18146:13)
在Runtime.createInstanceFromInit(http://domain1.com/html5-games/action/candy-match/c2runtime.js:4806:8)
在Layer.createInitialInstances(http://domain1.com/html5-games/action/candy-match/c2runtime.js:7541:25)
在Layout.startRunning(http://domain1.com/html5-games/action/candy-match/c2runtime.js:6715:10)
在Runtime.go_loading_finished(http://domain1.com/html5-games/action/candy-match/c2runtime.js:4067:36)
在Runtime.go(http://domain1.com/html5-games/action/candy-match/c2runtime.js:3966:9)
在http://domain1.com/html5-games/action/candy-match/c2runtime.js:4025:60
我在网上进行了一些研究,发现了类似这些的文章
https://webglfundamentals.org/webgl/lessons/webgl-cors-permission.html
Drawing images to canvas with img.crossOrigin = "Anonymous" doesn't work
但是它们并不是很有帮助。
我不想修改原始游戏文件。我正在寻找服务器端解决方案(如果存在)。如果没有,您是否有解决我问题的想法?
我的配置是否存在错误?我想念什么吗?
感谢您的帮助。
瓦列里奥
最佳答案
游戏必须请求跨源图像。仅返回正确的标头是不够的。如果游戏本身不通过设置crossOrigin
属性来请求跨源图像,则浏览器将不允许使用具有正确标题的图像。
这是一个例子
const gl = document.createElement("canvas").getContext("webgl");
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
loadImage('https://i.imgur.com/ZKMnXce.png', false);
loadImage('https://i.imgur.com/u6VI8xz.jpg', true);
function loadImage(url, crossOrigin) {
const img = new Image();
img.onload = () => { upload(img); };
if (crossOrigin) {
img.crossOrigin = '';
}
img.src = url;
}
function upload(img) {
// trap for cors error
try {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
log(img.src, "uploaded image");
} catch (e) {
log(img.src, e);
}
}
function log(...args) {
const elem = document.createElement("pre");
elem.textContent = [...args].join(' ');
document.body.appendChild(elem);
}
pre { margin: 0; }
在这里,您甚至可以看到那些第一张返回CORS标头的图片,因为未设置
crossOrigin
,该图片被禁止使用第二张图片具有相同的标题,但它起作用,因为我们设置了
crossOrigin
属性请注意,您可能可以在游戏脚本之前包含类似这样的脚本,以便在CORS支持中进行破解。
(function() {
function isSameOrigin(url) {
return (new URL(url)).origin === window.location.origin;
}
function needsCORS(url) {
// not sure all the URLs that should be checked for
return !isSameOrigin(url) && !url.startsWith("blob:") && !url.startsWith("data:");
}
const srcSetFn = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src').set;
Object.defineProperty(HTMLImageElement.prototype, 'src', {
enumerable: true,
set: function(url) {
if (needsCORS(url)) {
// Set if not already set
if (this.crossOrigin !== undefined) {
this.crossOrigin = '';
}
} else {
this.crossOrigin = undefined;
}
// Set the original attribute
srcSetFn.call(this, url);
},
});
}());