如何手动将three.js代码附加到iframe中



我最近在SO上问了这个问题,询问如何在没有文件或url的情况下将代码馈送到iframe中。这在简单的情况下有效,比如<h1>Hello World</h1>,但从长远来看,我希望将three.js实现到这些iframes中。以下是我如何尝试添加到iframe:

var iframe = document.getElementById("my-iframe");
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
iframeDocument.body.innerHTML = "<h1>Hello World</h1>";

这很好,但现在我尝试创建一个非常简单的three.js场景,只是为了拉开序幕

generatedCode = `
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js" ></script>
</head>
<body style="margin: 0;">
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(90, window.innerWidth/window.innerHeight, 0.1, 1000);

var mesh = new THREE.Mesh(
new THREE.BoxGeometry(1,1,1),
new THREE.MeshBasicMaterial({color:0xff0000})
);

scene.add(mesh);

camera.position.z = -5;
camera.lookAt(0, 0, 0);

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

function animate(){
requestAnimationFrame(animate);
renderer.render(scene, camera);
}

animate();
</script>
</body>
</html>
`

只是一个变量,如果这不是最好的做事方式,很抱歉。在定义了这个变量之后,我以相同的方式应用它:

var iframe = document.getElementById("my-iframe");
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
iframeDocument.body.innerHTML = generatedCode; //Now using the variable instead of a heading

为什么不起作用?谢谢

您的generatedCode将产生错误Unterminated template literal,您需要用</script>转义/替换变量中的</script>

因为变量以<!DOCTYPE html><html>开头,所以最好使用iframeDocument.write()写入iframe,因为iframeDocument.body.innerHTML是在<body>中写入

在jsfiddle 上运行

let generatedCode = `
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
</head>
<body style="margin: 0;">
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.1, 1000);
var mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({
color: 0xff0000
}));
scene.add(mesh);
camera.position.z = -5;
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>`;
var iframe = document.getElementById("my-iframe");
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
iframeDocument.write(generatedCode);
iframeDocument.close();
<iframe id="my-iframe"></iframe>

如果父窗口被认为是同源的,则iframe元素中的代码可以使用window.parent访问其父窗口,或者使用window.top访问一组嵌套iframe中最顶部的窗口。使用var声明的全局变量可以作为窗口属性访问。

下面的示例使用document.write,因为在没有进一步测试的情况下,它编译了写入iframe文档的脚本-可能还有其他方法。编写的脚本调用父iframe中的测试函数,该函数将文本记录在控制台上。

此代码不适用于堆栈溢出(这会触发一个非同源错误),但在浏览器中加载时测试成功:

<!DOCTYPE html>
<html><head><meta charset="utf-8">
<title>Iframe Access</title>
</head>
<body>
<h1>Parent window</h1>
<iframe id="my-iframe"></iframe>

<script>"use strict";
var test = ()=>console.log("test() call in parent window");
var iframe = document.getElementById("my-iframe");
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
iframeDocument.open();
iframeDocument.write( `
<h1>iframe Body</h1>
Check the console for output...
<script>
console.log(window.parent);
window.parent.test();
</script>`
);
iframeDocument.close();
</script>
</body>
</html>


回到问题上来,从父帧开始尝试的第一件事可能是

iframe.contentWindow.generateContent = generateContent

这将使CCD_ 19成为iframe内的窗口的属性。没有说明generateContent是否会在这种情况下运行!

最新更新