Kur*_*urt 36 javascript cross-domain three.js
我知道以前曾经问过这个问题,而且我已经读过我能找到的问题和答案,但没有任何效果.
我在本地服务器(IIS)上运行它.我正在尝试从imgur加载图像,然后使用代码将其用作对象的纹理:
var savedImage = /[^?]*$/.exec(location.search)[0];
if (savedImage != "") { savedImageLoad("http://i.imgur.com/" + savedImage + ".jpg"); };
function savedImageLoad(image) {
var mapOverlay = new THREE.ImageUtils.loadTexture(image);
sphere.material = new THREE.MeshBasicMaterial({map: mapOverlay, needsUpdate: true});;
sphere.geometry.buffersNeedUpdate = true;
sphere.geometry.uvsNeedUpdate = true;
}
Run Code Online (Sandbox Code Playgroud)
但它给出了错误:
Uncaught SecurityError: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image at http://i.imgur.com/uBD0g95.jpg may not be loaded.
Run Code Online (Sandbox Code Playgroud)
我已尝试THREE.ImageUtils.crossOrigin = "anonymous";在我的代码开头,最后和其他各个方面放置或改变一些.我添加了一个web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
Run Code Online (Sandbox Code Playgroud)
但那没用.这也不适用于bitbucket.org上托管的网站,我说我在代码中遗漏了一些东西.
这似乎是失败的sphere.material = new THREE.MeshBasicMaterial({map: mapOverlay, needsUpdate: true});;,就好像我评论那样没有错误(但是网格没有更新).
我真的不知道在这里尝试什么,任何帮助将不胜感激.
gma*_*man 53
在较新版本的THREE.js中,默认处理交叉原始图像.THREE.ImageUtils.loadTexture已弃用.它很常见TextureLoader
const loader = new THREE.TextureLoader();
const mapOverlay = loader.load('http://i.imgur.com/3tU4Vig.jpg');
Run Code Online (Sandbox Code Playgroud)
这有效
THREE.ImageUtils.crossOrigin = '';
var mapOverlay = THREE.ImageUtils.loadTexture('http://i.imgur.com/3tU4Vig.jpg');
Run Code Online (Sandbox Code Playgroud)
这是一个样本
var canvas = document.getElementById("c");
var renderer = new THREE.WebGLRenderer({canvas: canvas});
var camera = new THREE.PerspectiveCamera( 20, 1, 1, 10000 );
var scene = new THREE.Scene();
var sphereGeo = new THREE.SphereGeometry(40, 16, 8);
var light = new THREE.DirectionalLight(0xE0E0FF, 1);
light.position.set(200, 500, 200);
scene.add(light);
var light = new THREE.DirectionalLight(0xFFE0E0, 0.5);
light.position.set(-200, -500, -200);
scene.add(light);
camera.position.z = 300;
THREE.ImageUtils.crossOrigin = '';
var texture = THREE.ImageUtils.loadTexture('http://i.imgur.com/3tU4Vig.jpg');
var material = new THREE.MeshPhongMaterial({
map: texture,
specular: 0xFFFFFF,
shininess: 30,
shading: THREE.FlatShading,
});
var mesh = new THREE.Mesh(sphereGeo, material);
scene.add(mesh);
function resize() {
var width = canvas.clientWidth;
var height = canvas.clientHeight;
if (canvas.width != width ||
canvas.height != height) {
renderer.setSize(canvas.clientWidth, canvas.clientHeight, false); // don't update the style. Why does three.js fight CSS? It should respect CSS :(
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
}
function render(time) {
time *= 0.001; // seconds
resize();
mesh.rotation.y = time;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);Run Code Online (Sandbox Code Playgroud)
body {
margin: 0;
}
#c {
width: 100vw;
height: 100vh;
display: block;
}Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/84/three.min.js"></script>
<canvas id="c"></canvas>Run Code Online (Sandbox Code Playgroud)
注意:不要使用new与THREE.ImageUtils.loadTexture
为了将图像跨源加载到WebGL中,发送图像的服务器必须使用正确的标头进行响应.仅仅说你想要使用图像交叉来源是不够的.所有这一切都告诉服务器您正在请求使用该映像的权限.
您可以设置img.crossOrigin,或在三个的情况下THREE.ImageUtils.crossOrigin,要么'','anonymous'这是一样的'',也可以将其设置为'use-credentials'它发送到服务器甚至更多的信息.浏览器会看到您设置crossOrigin并向服务器发送某些标头.服务器读取这些标头,决定您的域是否有权使用该图像,如果您有权限,它会将某些标头发送回浏览器.浏览器,如果它看到这些标题将允许您使用该图像.
最重要的一点就是服务器必须发送标题.大多数服务器不发送这些标头.imgur.com显然.我怀疑bitlocker没有,但我没有测试它.
你也必须设置crossOrigin.如果你不这样做,浏览器将不允许你以你不应该的方式使用img,即使服务器发送了正确的标题.
小智 25
更新:不推荐使用的方法
我遇到了这个问题并从答案中应用了解决方案,因为在THREE.js的新版本中已弃用的方法,因此找不到它.我发布这个答案,万一有人得到同样的问题.尽管弃用,gman在原始答案中提供的信息是最有帮助的,我建议阅读它.
THREE.ImageUtils.loadTexture()
Run Code Online (Sandbox Code Playgroud)
方法因原始问答而被弃用.
当前加载纹理的方法:
// instantiate a loader
var loader = new THREE.TextureLoader();
//allow cross origin loading
loader.crossOrigin = '';
// load a resource
loader.load('textures/land_ocean_ice_cloud_2048.jpg',
// Function when resource is loaded
function ( texture ) {},
// Function called when download progresses
function ( xhr ) {},
// Function called when download errors
function ( xhr ) {}
);
Run Code Online (Sandbox Code Playgroud)