Using Three.js library in weweb

Hi there, has anyone managed to use the Three.js library with Weweb and be kind enough to guide me with it ? (three.js docs)

I tried various ways such as using the page workflow with the following code:

  if(!window["Three-JS-script"]) {
    window["Three-JS-script"] = true;
    let doc;
    doc = document.createElement('script');
    doc.src = 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js';
    doc.async = true;
    wwLib.getFrontDocument().body.appendChild(doc);
  }

I also tried using NPM without luck, my JS function requiring the three library always end up not finding the THREE object (THREE is not defined error)

Thank you in advance for any help on this

1 Like

Thank you for your question. Let me check with the team and see how we can assist you. I will get back to you as soon as possible.

1 Like

I used the Statechange Weweb Embedder with the following code and gave me code to add THREE to my window (e.g. wwLib.getFrontWindow() ). I apologize that I haven’t dug further at this time, but I hope it gives you a hook to start with:

<script type="module" >
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.164.1/build/three.module.js';
window.THREE = THREE;
</script>
1 Like

Nice one @raydeck
That did it ! Thank you :tada:

1 Like

I though I was good to go but I am running into another issue when trying to load addons as mentioned in the documentation

import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const controls = new OrbitControls( camera, renderer.domElement );
const loader = new GLTFLoader();

I tried the following but the libraries OrbitControls and GLTFLoader seem to rely on the main three library (three) that they can’t find

  if(!window["scp-loading-8948f848-d293-4767-926e-ea1db2fe3854"]) {
    window["scp-loading-8948f848-d293-4767-926e-ea1db2fe3854"] = true;
    let doc;
    /* Adding script from null */
    doc = document.createElement('script');
    doc.type = 'module';
    doc.innerHTML = `
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.164.1/build/three.module.min.js';
window.THREE = THREE;

import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/controls/OrbitControls.js';
window.OrbitControls = OrbitControls;

import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/loaders/GLTFLoader.js';
window.GLTFLoader = GLTFLoader;
`;
    document.body.appendChild(doc);
  }

Here is a quick video of the issue that might give you a hint, thanks again for the support

The docs indicate using an importmap. Try putting this into the weweb-embed:

<script type="importmap">
  {
    "imports": {
      "three": "https://cdn.jsdelivr.net/npm/three@0.164.1/build/three.module.js",
      "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
window.THREE = THREE;
window.OrbitControls = OrbitControls;
window.GLTFLoader = GLTFLoader;
</script>

And let’s see if that gives you access to more we can work with.
Note that sometimes there is a time factor in loading these modules. Try throwing a time delay in your workflow for setting thigsn up on mount or whatever event handler you’re using.

Here’s the source of the code I put in my mount event handler (after giving the div in question an id of dffg2):

console.log("Starting the mount call")
const THREE = wwLib.getFrontWindow().THREE;
console.log("Three is ", THREE)
const scene = new THREE.Scene();
console.log("Scene is ", scene)
const camera = new THREE.PerspectiveCamera( 75, 1, 0.1, 1000 );
const element = document.getElementById('dffg2');
console.log("Element is", element, element.innerWidth, element.innerHeight)
const renderer = new THREE.WebGLRenderer();
renderer.setSize( 400, 400 );
element.appendChild(renderer.domElement)
console.log("I added to the div, let's ride")
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
console.log("And i got all the way to the scene reference")
scene.add( cube );

camera.position.z = 5;
function animate() {
	cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
requestAnimationFrame( animate );
	renderer.render( scene, camera );
} 
animate();

This is based on instructions at: three.js docs

Gave me a rotating green cube on a black background - a beginning!

1 Like

Thank you so much for taking the time to set this up,

I did not think the importmap would work as is and edited the imports path in the first place :persevere:.

Now it’s all good, I can see that cube !! Let’s play with that :grinning: