I want to be able to insert an interactive 3D background element (and possibly more). I plan to do this using Three.js for several reasons: it’s free, highly flexible, relatively fast, and easy to use for a beginner JavaScript developer.
However, when I try to import Three.js with an import map, I can’t get it to work. The canvas element does not render. Below is the code showing the import map as suggested in the Three.js documentation.
import * as THREE from 'three';
...
When I use an older module, called “TroisJS”, it does seem to work .
don't want to use that module because it is not being updated.
I've tried several approaches: importing with a bundled JS file, using older versions (R160 and R159) that include a single minified file, and using a module-type script with a CDN import. I also tested everything locally with Vite, and it worked every time—but it doesn’t seem to work in Shopify.
Can someone help me with this issue?
I actually got it working, with a build file inside the asset folder AND with the importmap.
The problem was Three JS not being able to render inside a canvas tag. Or at least it could find or make a canvas tag.
I found an old post with a (not marked) answer.
This was this person’s solution that also worked for me:
// get data from Canvas
const canvas = document.querySelector('#id3DCanvas');
// Create a basic perspective camera
// var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var camera = new THREE.PerspectiveCamera( 75, canvas.clientWidth/canvas.clientHeight, 0.1, 1000 );
camera.position.z = 4;
// Create a renderer with Antialiasing
const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
// Configure renderer clear color
renderer.setClearColor("#000000");
// Configure renderer size
// renderer.setSize( window.innerWidth/2, window.innerHeight/2);
renderer.setSize( canvas.clientWidth, canvas.clientHeight);
// Append Renderer to DOM
document.getElementById("id_canvasdiv").appendChild( renderer.domElement );
// document.body.appendChild( renderer.domElement );
#id3DCanvas { width: 500px; height: 1000px }
I don’t know what happens in the background, but it looks like Three JS couldn’t make a canvas directly.
Hey Makzy, I am trying to achieve the same, but no luck. Trying to load a .stl viewer on my store page. Could you show your liquid code and which three.js files you uploaded? My issue is getting three.js loaded in the first place, with nonsense like this:
An import map is added after module script load was triggered.
Uncaught TypeError: Failed to resolve module specifier “three”. Relative references must start with either “/”, “./”, or “../”.
Hey Esuna,
I’ve never gotten Orbit Controls working. At the moment I only import the Three.js module that is located in my assets folder.
Also importmap didn’t work for me. So underneath is the solution that worked for me.
In my theme.liquid I’ve added the three js module in the head:
In my assets folder, I directly inserted the three.module.min.js from the build (https://github.com/mrdoob/three.js/blob/dev/build/three.module.min.js_)
I also inserted the three.core.min.js in the assets folder, for good measure (never tested without it though. I noticed some imports from the core module)
With this I got the renderer working in every page. Three.js just couldn’t change my canvas tag in my case.
FYI: Orbit Controls just break my code at the moment
I actually got it all working, including OrbitControls! Uploading the entire build/ folder into assets was the key. I now have the issue that the canvas remains white/grey until I resize the window. It initiates at 0w/h.
In theme.liquid, in the tag above all the existing tags:
then in my viewer.js I do this:
import * as THREE from 'three';
import { STLLoader } from 'STLLoader';
import { OrbitControls } from 'OrbitControls';
I had to download OrbitControls.js + STLLoader.js and add it to assets/ for my viewer, so you still need to get the raw files for all the plugins into Shopify.