Recientemente hice esta pregunta en SO, preguntando cómo introducir código en un iframe SIN un archivo o URL. Esto funcionó en casos simples, como <h1>Hello World</h1> , pero a largo plazo, quiero implementar three.js en estos iframes . Así es como traté de agregar al iframe :
var iframe = document.getElementById("my-iframe"); var iframeDocument = iframe.contentDocument || iframe.contentWindow.document; iframeDocument.body.innerHTML = "<h1>Hello World</h1>"; Esto funciona bien, pero ahora trato de crear una escena three.js muy simple, solo para comenzar. Así es como lo probé:
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>\ `Solo una variable, lo siento si esta no es la mejor manera de hacer las cosas. Después de definir esta variable, la aplico de la misma manera:
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¿Por qué no funciona esto? ¡Gracias!
Siempre que se considere que la ventana principal tiene el mismo origen, el código en un elemento iframe puede acceder a su ventana principal usando window.parent , o la ventana superior en un grupo de iframes anidados como window.top . Y se puede acceder a las variables globales declaradas usando var como propiedades de ventana.
El siguiente ejemplo usa document.write porque, sin más pruebas, compiló el script escrito en el documento iframe; puede haber otras formas de hacerlo. El script escrito llama a una función de prueba en el iframe principal, que registra el texto en la consola.
Este código no funciona en Stack Overflow (que desencadena un error de origen diferente) pero se probó con éxito cuando se carga en un navegador:
<!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>Volviendo a la pregunta, lo primero que debe intentar desde el marco principal podría ser
iframe.contentWindow.generateContent = generateContent lo que haría de generateContent una propiedad de la ventana dentro del iframe. ¡No dice nada sobre si generateContent se ejecutará en tales circunstancias!
Su código generatedCode producirá un error Unterminated template literal no terminado que necesita escapar/reemplazar </script> en la variable con <\/script>
debido a que la variable comienza con <!DOCTYPE html><html> es mejor escribir el iframe usando iframeDocument.write() , porque el iframeDocument.body.innerHTML es escribir en <body>
ejecutar en 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>