在Three.js中的CSS3DObject内创建跨源HTML iframe会出错

时间:2014-02-12 23:38:53

标签: javascript html css three.js cross-domain

index.html:

<!doctype html>
<html lang="en">
<body>

<script src="js/Three.js"></script>
<script src="js/CSS3DRenderer2.js"></script>
<script src="js/THREEx.WindowResize.js"></script>


<div id="ThreeJS" style="position: absolute; left: 0px; top: 0px"></div>
<script>
    var container, scene, camera, renderer, controls, stats;
    var rendererCSS;

    init();
    animate();

    function init() {
        scene = new THREE.Scene();
        var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
        var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
        camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
        scene.add(camera);
        camera.position.set(0, 150, 400);
        camera.lookAt(scene.position);

        renderer = new THREE.WebGLRenderer();
        renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
        container = document.getElementById('ThreeJS');
        container.appendChild(renderer.domElement);

        var planeMaterial = new THREE.MeshBasicMaterial({
            color : 0xFFFFFF,
            side : THREE.DoubleSide
        });

        var planeWidth = 360;
        var planeHeight = 120;
        var planeGeometry = new THREE.PlaneGeometry(planeWidth, planeHeight);
        var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
        planeMesh.position.y += 50;
        scene.add(planeMesh);


        cssScene = new THREE.Scene();
        var element = document.createElement('iframe')
        element.src = "moo.html";
        var elementWidth = 1024;
        // force iframe to have same relative dimensions as planeGeometry
        var aspectRatio = planeHeight / planeWidth;
        var elementHeight = elementWidth * aspectRatio;
        element.style.width  = elementWidth + "px";
        element.style.height = elementHeight + "px";

        var cssObject = new THREE.CSS3DObject(element);
        cssObject.position  = planeMesh.position;
        cssObject.rotation  = planeMesh.rotation;
        var percentBorder = 0.05;
        cssObject.scale.x /= (1 + percentBorder) * (elementWidth / planeWidth);
        cssObject.scale.y /= (1 + percentBorder) * (elementWidth / planeWidth);
        cssScene.add(cssObject);

        rendererCSS = new THREE.CSS3DRenderer();
        rendererCSS.setSize(window.innerWidth, window.innerHeight );
        document.body.appendChild(rendererCSS.domElement);

    }

    function animate() {
        requestAnimationFrame(animate);
        render();
    }

    function render() {
        rendererCSS.render(cssScene, camera);
        renderer.render(scene, camera);
    }
</script>

</body>
</html>

moo.html:

<!DOCTYPE html>
<html>
<body>
<h1>hello world!</h1>
</body>
</html>

此代码告诉我:http://i.imgur.com/nP2UYAL.jpg

但如果我改变:

 element.src = "moo.html";

 element.src = "http://www.google.com";

我得到:http://i.imgur.com/gr9GENn.jpg

受此示例的启发:http://stemkoski.github.io/Three.js/CSS3D.html

这有可能以某种方式解决这个问题,以创建跨域iframe吗?

1 个答案:

答案 0 :(得分:0)

是的,可以使用iFrame解决方案。但是,您应该考虑尝试一种替代方法,该方法比在THREEJS中对iFrame进行黑客攻击更快更有效。

您需要在localhost(或实际的开发服务器)上设置服务器才能看到成功的结果。话虽这么说,我用服务器上的代码编写了一个JSFIDDLE。

LINK: http://jsfiddle.net/vnjn6mnL/19/

这个想法很简单。从有效的JSON对象中拉出。甚至不用从远程文件中解析jQuery(当然你可以)。

然后运行for循环,迭代JSON对象:

for (var i = 0; i < json.projectData.length; i ++)

以上代码位于小提琴的第125行。循环下面的部分显示了如何从JSON对象中提取:

    // Individual Element Creation
    var element = document.createElement( 'div' );
        element.className = 'element';

    // Individual Element Picture Creation
    var logo = document.createElement( 'div' );
        logo.className = 'logo';
        logo.innerHTML = "<img src='" +json.projectData[i].projectLogo + "'>";                  

            element.appendChild( logo );

使用JSON对象可以更灵活地呈现任何数据。像图像这样的东西很简单,因为你真的直接使用CSS。

如果JSON对象看起来令人生畏,您可能会发现有用的工作流程如下:

使用:http://beta.json-generator.com/JmXmG79以编程方式生成JSON对象。该链接将带您到我为生成示例数据时使用的确切逻辑。

为确保您使用有效的JSON对象,请使用在线JSON linter。 Google“JSON Validator”和第一个选项效果很好。

确定它有效后,将其带入JS场景并将其包装在全局变量标签中。从那时起,您可以参考上面的小提琴,看看其他任何内容。