i'm very new to npms and i'm trying to import three.js into my scene but it is coming up with this error despite stating the type = "module" in my script tag in my html
I installed it through an npm and here is my javascript:
var $ = require('jquery');
var three = require('three');
import * as THREE from 'three';
import OrbitControls from 'three/examples/jsm/controls/OrbitControls';
var camera, scene, renderer;
var geometry, material, mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;
scene = new THREE.Scene();
geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
Here is my html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="#"/>
<title>Document</title>
<script type = "module" src="/bundle.js"></script>
</head>
<body>
</body>
</html>
Sorry if the answer is obvious, using browserify and module files is very new territory for me.
Edit: So in the official documentation, it says to do this :
var THREE = require('three');
var scene = new THREE.Scene();
...
which works except I want to use
import { MapControls } from 'three/examples/jsm/controls/OrbitControls.js';
which is only available through extracting it from the orbitcontrols library. Is there a way to do this without ES6 imports and using require() instead?
Related
I'm just trying to prototype something quickly (typically use React), dumping some JS code into an html file. I don't get why this import doesn't work.
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>three.js app</title>
<h1>Some app:</h1>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script src="/threeCode.js"></script>
</body>
</html
Then my JS code would live here:
threeCode.js:
import * as THREE from './three';
console.log("hellow world")
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
function animate() {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
But then I get:
Uncaught SyntaxError: import declarations may only appear at top level of a module
Three is a node module (three.js) via npm install.
EDIT: serving using http-server -o -cors
I installed three.js through npm with the command: npm install --save three
I'm currently using VS-Code & have two files : index.html and index.js
By copying a simple example from threejs.org I can't seem to get three.js to work,because i only get a blank screen after running a live server,instead of a rotating cube.
Here's the code to both files:
import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight,
0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material);
scene.add(cube);
camera.position.z = 5;
function animate() {
requestAnimationFrame(animate)
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera )
}
animate();
<!DOCTYPE html>
<html>
<head>
<link rel = "stylesheet" href = "index.css">
<script src = "index.js"></script>
<title >Title</title>
</head>
<body style = "margin: 0px;">
</body>
</html>
If you open the page in a browser and take a look at the dev tools menu, you'll find the following error:.
If you modify the script tag with type="module" to resolve this error, you get a new error: Failed to resolve module specifier "three". Relative references must start with either "/", "./", or "../".
Basically, the browser isn't able to find the three.js JavaScript library.
One easy fix is to just tell the browser to load the library from a web url when the page loads instead of installing it through npm and then loading those installed npm files into the web page:
<!DOCTYPE html>
<html>
<head>
<link rel = "stylesheet" href = "index.css">
<!-- This script tag loads the three.js library via url -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<title >Title</title>
</head>
<body style = "margin: 0px;">
<script src = "index.js"></script>
</body>
</html>
// import is no longer needed since the added script tag loads the library and adds the global THREE variable into the page
// import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight,
0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material);
scene.add(cube);
camera.position.z = 5;
function animate() {
requestAnimationFrame(animate)
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera )
}
animate();
Also note that document.body.appendChild will only work once the document has loaded (which doesn't necessarily happen before your script is executed). This issue was fixed by adding your <script> tag below the <body> tag in the html.
When looking for a way to create a three.js line with a changed width I came across this article which suggests to use a THREE.MeshLine class from here. However, when trying to follow the documentation on how to use it in my script I got an error:
require.js:5 Uncaught Error: Module name "three" has not been loaded yet for context: _. Use require([])
http://requirejs.org/docs/errors.html#notloaded
at makeError (require.js:5)
at Object.o [as require] (require.js:5)
at requirejs (require.js:5)
at test_line.html:13
Here are the lines of code I used in my script:
<html>
<head>
<script src="https://requirejs.org/docs/release/2.3.5/minified/require.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r119/three.min.js"></script>
<script src="https://raw.githubusercontent.com/spite/THREE.MeshLine/master/src/THREE.MeshLine.js"></script>
<title>Test</title>
</head>
<body>
<script>
var THREE = require( 'three' );
var MeshLine = require( 'three.meshline' );
...
Do I miss something? (Hint: I am a beginner with javascript)
I also tried to follow the suggestions HERE, but as soon as I added type="module" in the script part I got an error container is not defined.
Here is a complete, stand-alone, static, easy, direct working html example of a single line in a browser window. I'd appreciate if the answer could contain a complete, stand-alone, static, easy, direct working example of the code fixed!
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r119/three.min.js"></script>
<title>Test</title>
</head>
<body>
<script>
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 0, 150);
scene = new THREE.Scene();
scene.add(camera);
renderer = new THREE.WebGLRenderer({
clearAlpha: 1
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xcaffee, 1);
document.body.appendChild(renderer.domElement);
var material = new THREE.LineBasicMaterial( { color: 0xff0000, linewidth: 10000000 } );
var points = [];
points.push( new THREE.Vector3(-50, 0, 0 ) );
points.push( new THREE.Vector3( 50, 0, 0 ) );
var geometry = new THREE.BufferGeometry().setFromPoints( points );
var line = new THREE.Line( geometry, material );
scene.add( line );
renderer.render( scene, camera );
animate();
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
</script>
</body>
</html>
Edit 2: As #user2589273 mentioned in the comment, this answer is no longer relevant, as the original repository (https://github.com/spite/THREE.MeshLine) has merged the below fork into the main repo. I will leave the answer below for posterity.
The Meshline repository you linked is not maintained any more and does not work with current three.js releases.
Here is the maintained fork that I currently use:
https://github.com/ryanking1809/threejs-meshline
It should work if you replace the link in your question with:
https://unpkg.com/threejs-meshline#2.0.11/src/index.js
Edit: with full working example:
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r119/three.min.js"></script>
<script src="https://unpkg.com/threejs-meshline#2.0.11/src/index.js"></script>
<title>Test</title>
</head>
<body>
<script>
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 0, 150);
scene = new THREE.Scene();
scene.add(camera);
renderer = new THREE.WebGLRenderer({
clearAlpha: 1
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xcaffee, 1);
document.body.appendChild(renderer.domElement);
let points = [];
points.push( new THREE.Vector3(-50, 0, 0 ) );
points.push( new THREE.Vector3( 50, 0, 0 ) );
const line = new MeshLine();
line.setVertices(points);
const material = new MeshLineMaterial();
const mesh = new THREE.Mesh( line, material );
scene.add( mesh );
renderer.render( scene, camera );
animate();
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
</script>
</body>
</html>
I'm trying to upload a 3D model to my scene in three.js however I have trouble doing this.
I decided to recreate an example to practice which is shown below but I still get error and it doesn't work.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Website first attempt</title>
<script src="js/three.min.js"></script>
<script type = "module"src="js/OrbitControls.js"></script>
<script type = "module" src="js/GLTFLoader.js"></script>
<style>
body { margin: 0;}
canvas { display: block; }
</style>
</head>
<body>
<div class = "wave"></div>
<script type = "module">
var scene, camera, renderer, controls;
var hlight,directionalLight, light, light2, light3, light4;
function init () {
//scene
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xdddddd );
//camera
camera = new THREE.PerspectiveCamera(40,window.innerWidth/window.innerHeight,1,5000);
camera.rotation.y = 45/180*Math.PI;
camera.position.x = 800;
camera.position.y = 100;
camera.position.z = 1000;
//render
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
hlight = new THREE.AmbientLight (0x404040,100);
scene.add(hlight);
directionalLight = new THREE.DirectionalLight(0xffffff,100);
directionalLight.position.set(0,1,0);
directionalLight.castShadow = true;
scene.add(directionalLight);
light = new THREE.PointLight(0xc4c4c4,10);
light.position.set(0,300,500);
scene.add(light);
light2 = new THREE.PointLight(0xc4c4c4,10);
light2.position.set(500,100,0);
scene.add(light2);
light3 = new THREE.PointLight(0xc4c4c4,10);
light3.position.set(0,100,-500);
scene.add(light3);
light4 = new THREE.PointLight(0xc4c4c4,10);
light4.position.set(-500,300,500);
scene.add(light4);
var loader = new THREE.GLTFLoader();
loader.load('scene.gltf', function(gltf){
car = gltf.scene.children[0];
car.scale.set(0.5,0.5,0.5);
scene.add(gltf.scene);
animate();
});
}
function onWindowResize () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.addEventListener('resize', onWindowResize, false);
function animate () {
requestAnimationFrame(animate);
controls.update();
render();
}
function render() {
renderer.render( scene, camera );
}
init ();
animate();
</script>
</body>
</html>
Comes with an error:
GET http://127.0.0.1:5500/build/three.module.js net::ERR_ABORTED 404
(Not Found) index4.html:78 Uncaught TypeError: THREE.GLTFLoader is not
a constructor
at init (index4.html:78)
at index4.html:122
I think easier to stick to the example's code style and organize your imports like so:
<script type = "module">
import * as THREE from '../build/three.module.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
var scene, camera, renderer, controls;
Meaning three.module.js, OrbitControls and GLTFLoader are ES6 modules. In this case, you can create an instance of GLTFLoader without the THREE namespace. Same for OrbitControls.
Notice that it's no good approach to mix ES6 modules with non-ES6 modules. If you do so, you will be inevitably faced with issues which are really hard to track down. E.g. libraries like three.js get included twice.
I'm trying to make a hologram with Three.JS (Pepperghost Effect) and for it to work I need 4 rotating models.
I have a working POC (https://gyazo.com/57da565593493a2c9971457632bb5552). This was an STL model, so I wasn't able to add textures to it. I did some research and gave gLTF's a shot. I got a model with textures and the importing all worked, but the rotation part was not working as I expected.
Here is a gif of the problem: https://gyazo.com/c5a1a8ee65f7da2cce1c83261d465b33
I want it to spin on its own axes instead of in circles. What I think is the problem, is that it doesn't import it centered, so it would be a problem with the model position and not the rotating part (which is mesh.rotation.y += 0.01; to be clear).
I tried moving the mesh with the mesh.position.set() function, but that moves the whole scene (I guess that's what you call it?).
Also, as you can see on the last gif, I have another problem where the chest is only displayed twice. Maybe this is tied to the other problem I have?
I tried putting it together in a jsfiddle, but since I cant upload the model that doesn't work. This is the 3D model I'm importing: https://sketchfab.com/3d-models/chest-92a8d45d2d5c43b8b0b5bf7d97816ada
The peppersghost file can be found here https://threejs.org/examples/jsm/effects/PeppersGhostEffect.js
<!DOCTYPE html>
<html lang="en">
<head>
<title>Three.js Hologram POC</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.js"></script>
<script src="peppersghost.js"></script>
<!-- <script charset="utf-8" src="STLLoader.js"></script> -->
<!-- <script src="three.module.js"></script> -->
<!-- <script src="http://threejs.org/build/three.min.js"></script> -->
<script src="http://threejs.org/examples/js/loaders/MTLLoader.js"></script>
<script src="http://threejs.org/examples/js/loaders/OBJLoader.js"></script>
<script src="http://threejs.org/examples/js/loaders/GLTFLoader.js"></script>
</head>
<body>
<script type="module">
var container;
var camera, scene, renderer, effect, mesh, cube;
var group;
// var cameraTarget = new THREE.Vector3( 0, - 0.25, 0 );
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
// console.log(window.innerWidth / window.innerHeight)
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100000 );
scene = new THREE.Scene();
// scene.background = new THREE.Color( 0xffd300 );
var ambientLight = new THREE.AmbientLight(0xffffff);
var light = new THREE.PointLight(0xffffff, 2.0, 200);
camera.add(ambientLight);
camera.add(light);
scene.add(camera);
camera.position.z = 1100;
camera.lookAt(scene.position);
const gltfLoader = new THREE.GLTFLoader();
gltfLoader.load('/media/autoconvert/scene.gltf', (gltf) => {
mesh = gltf.scene;
// mesh.position.set(0, 100, 0)
// mesh.scale.set(3, 1, 1);
scene.add(mesh);
const box = new THREE.Box3().setFromObject(mesh);
const boxSize = box.getSize(new THREE.Vector3()).length();
const boxCenter = box.getCenter(new THREE.Vector3());
});
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio( window.devicePixelRatio );
container.appendChild( renderer.domElement );
effect = new THREE.PeppersGhostEffect( renderer );
effect.setSize( window.innerWidth, window.innerHeight );
effect.cameraDistance = 5;
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
effect.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.y += 0.02;
// var timer = Date.now() * 0.0005;
// camera.position.x = Math.cos( timer ) * 3;
// camera.position.z = Math.sin( timer ) * 3;
// camera.lookAt( cameraTarget );
effect.render( scene, camera );
}
</script>
</body>
</html>
Thanks!
EDIT: Thanks for the help! I tried both solutions, but I am still encountering problems :(
First I tried getting the first child. Although it didnt spin in circles like it did before, it still rotates the wrong way and it only shows two models instead of four: https://gyazo.com/1da02beff790bbb440c42eec42540e56
Then I expanded and added a group like this:
group = new THREE.Group(); scene.add(group); and group.add(mesh) instead of scene.add(mesh).
This is what I got after that: https://gyazo.com/220f5eed04ec05c56000327b57837047
As you can see, it still isn't working. I am still trying to find a solution for my problem. Any other suggestions are welcome!