Hey there! I want to use the three.js library with a web builder platform similar to Webflow (I must load it via CDN). However, it seems like I can’t load the script type=importmap and script type=module on this platform’s site. How can I resolve this issue? (I checked the network tab in Chrome DevTools, and there doesn’t seem to be any problem with the MIME type, which is set to application/javascript.)
occured errors:
'Uncaught SyntaxError: Unexpected token ‘:’ (at importmap script)
'Uncaught SyntaxError: Cannot use import statement outside a module (at GLTFLoader.js:1:1)
'Uncaught SyntaxError: Cannot use import statement outside a module ’ ‘Uncaught TypeError: Failed to resolve module specifier “three”. Relative references must start with either “/”, “./”, or “…/”.’
<!DOCTYPE html>
<head>
<style>
html,
body {
margin: 0;
padding: 0;
font-family: "Courier New", Courier, monospace;
}
#webgl {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: -1;
}
section {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
color: white;
}
</style>
</head>
<body>
<main>
<section>
<h2>Hello</h2>
</section>
<section>
<h2>Sweet</h2>
</section>
<section>
<h2>Child</h2>
</section>
</main>
<!-- WEBFLOW EMBED START -->
<canvas id="webgl"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/gsap.min.js"></script>
<script
async
src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"
></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.149.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.149.0/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader";
class Experience {
isHovering = false;
mouse = { x: 0, y: 0 };
scrollPos = 0;
constructor() {
this.windowResize = this.windowResize.bind(this);
this.windowScroll = this.windowScroll.bind(this);
this.mouseMove = this.mouseMove.bind(this);
this.animate = this.animate.bind(this);
this.setScene();
this.setCanvas();
this.setCameras();
this.setRenderer();
this.createBox();
this.loadFox();
this.addLights();
this.setEvents();
this.clock = new THREE.Clock();
this.animate();
}
setScene() {
this.scene = new THREE.Scene();
}
setCanvas() {
this.canvas = document.getElementById("webgl");
}
setCameras() {
this.camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
this.camera.position.z = 5;
this.scrollPos = this.camera.position.y;
this.scene.add(this.camera);
}
setRenderer() {
this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas });
this.renderer.setPixelRatio(Math.min(2, window.devicePixelRatio));
this.renderer.setSize(window.innerWidth, window.innerHeight);
}
addLights() {
const ambientLight = new THREE.AmbientLight();
this.scene.add(ambientLight);
}
createBox() {
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
this.box = new THREE.Mesh(geometry, material);
this.group = new THREE.Group();
this.group.position.y = -2.5;
this.group.add(this.box);
this.scene.add(this.group);
}
windowResize(e) {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
}
windowScroll(e) {
this.scrollPos =
(window.pageYOffset || document.scrollTop) -
(document.clientTop || 0) || 0;
}
mouseMove(e) {
this.mouse.x = e.clientX / window.innerWidth - 0.5;
this.mouse.y = e.clientY / window.innerHeight - 0.5;
}
setEvents() {
window.addEventListener("resize", this.windowResize);
window.addEventListener("scroll", this.windowScroll);
window.addEventListener("mousemove", this.mouseMove);
const titles = Array.from(document.querySelectorAll("h2"));
titles.forEach((title) => {
title.addEventListener("mouseover", () => {
this.fadeToAction(this.action2);
this.isHovering = true;
});
title.addEventListener("mouseleave", () => {
this.fadeToAction(this.action1);
this.isHovering = false;
});
});
}
fadeToAction(newAction, duration = 0.2) {
const previousAction = this.activeAction;
this.activeAction = newAction;
if (previousAction !== this.activeAction) {
previousAction.fadeOut(duration);
}
this.activeAction
.reset()
.setEffectiveTimeScale(1)
.setEffectiveWeight(1)
.fadeIn(duration)
.play();
}
loadFox() {
const gltfLoader = new GLTFLoader();
gltfLoader.load(
"https://webflow-and-code.s3.amazonaws.com/glTF/Fox.gltf",
(gltf) => {
console.log("success");
console.log(gltf);
gltf.scene.scale.set(0.03, 0.03, 0.03);
gltf.scene.position.y = 0.5;
this.group.add(gltf.scene);
this.mixer = new THREE.AnimationMixer(gltf.scene);
this.action1 = this.mixer.clipAction(gltf.animations[0]);
this.action2 = this.mixer.clipAction(gltf.animations[1]);
this.activeAction = this.action1;
this.activeAction.play();
}
);
}
animate() {
this.camera.position.y = -this.scrollPos * 0.005;
gsap.to(this.group.rotation, {
x: this.mouse.y * 0.5,
y: this.mouse.x * 0.5
});
if (this.mixer) {
this.mixer.update(this.clock.getDelta());
}
this.box.material.color = this.isHovering
? new THREE.Color(0.0, 1.0, 0.0)
: new THREE.Color(1.0, 0.0, 0.0);
this.renderer.render(this.scene, this.camera);
window.requestAnimationFrame(this.animate);
}
}
const experience = new Experience();
</script>
<!-- WEBFLOW EMBED END -->
</body>
</html>
</body>
</html>```