I cannot center three js object into DIV
Here is my code:
import * as THREE from 'https://cdn.skypack.dev/pin/three#v0.128.0-iDyvDZdRCoyR9DXa2rWg/mode=imports,min/optimized/three.js';
const container = document.getElementById("canvas");
// const selected = document.querySelector("#canvas");
// document.body.appendChild(container);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( container.offsetWidth, container.offsetWidth );
// renderer.setSize( item.clientWidth, item.clientHeight );
container.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;
const animate = function () {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
And that's how the problem looks:
Object just going outside the DIV:
I dont know why it happens. I'm trying to fix this a couple of days and try a lot of ways and it still does not work. Probably I don't understand something and need your help...
I guess i solved the problem. I just delete padding of the #canvas in css and its now work as expected.
Related
my three.js canvas is not responsive on ios
when I go to landscape mode on iPhone 12 the canvas is not responsive. it becomes small an squarish, and when I go back to portrait mode it stays in this new size (small square)
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.01,1000);
var clock = new THREE.Clock();
var renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener ('resize', ()=> {
renderer.setSize(window.innerWidth,window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
})
var rmapped = 0;
const controls = new OrbitControls( camera, renderer.domElement );
var loader = new GLTFLoader();
scene.background = new THREE.Color(0x000000)
const cube = new THREE.BoxGeometry( 1,1,1 );
var light1 = new THREE.PointLight( 0xff0040, 2, 50 );
light1.add( new THREE.Mesh( cube, new THREE.MeshBasicMaterial( { color: 0xff0040 } ) ) );
scene.add( light1 );
var light2 = new THREE.PointLight( 0x0040ff, 2, 50 );
light2.add( new THREE.Mesh( cube, new THREE.MeshBasicMaterial( { color: 0x0040ff } ) ) );
light2.position.x=3;
var light2Obj = new THREE.Object3D();
light2Obj.add(light2);
scene.add(light2Obj);
camera.position.set(0, 5, 10);
function animate(){
requestAnimationFrame(animate);
light1.rotateY(0.005);
light2Obj.rotateY(0.009);
renderer.render( scene, camera );
function render() {
renderer.render( scene, camera );
}
}
animate()
Any idea of what the problem is ? seems to work on Android.
read somewhere that resizeobserver api could be a solution but i cannot figure it out
this is what it looks like
lanscape mode:
https://i.stack.imgur.com/LXnnz.jpg
back to portrait mode
https://i.stack.imgur.com/QjkBR.jpg
The editor project I am making should allow me to Import a cdn library and use it to write code . So to show my problem , enter https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js in the import cdn input and click import . Then enter this in the code section :
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
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;
const animate = function () {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
Click the run button at the top . You should get a tiny three js window at the bottom. My first question is , why is the text undefined coming above the render ? And two , if you change the code in the input to :
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;
const animate = function () {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
It adds another render to the div . Why ? especially when I have used the .html method to replace the contents of the div . My complete code is visible here
By inspecting the Javascript console, it's clear that the renderer is not added to #body2 but rather to the document.body.
This line:
document.body.appendChild( renderer.domElement );
appends the renderer to the body element.
The undefined is because of String( eval( $("#editor #editor-textarea").val() ));
The text content in eval must return something.
https://www.w3schools.com/jsref/jsref_eval.asp
In this case, the return value of $("#editor #editor-textarea").val() is undefined. Hence eval(undefined) is undefined and String(undefined) is "undefined"
I'm trying to work out camera navigation functionality in threejs, using THREE.OrbitControls. Even though I'm following a guide, I just can't seem to get it working.
The link to my fiddle code is: https://jsfiddle.net/Matty1/uc671jbL/18/
It's on line 18/19 of the javascript:
const controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.update();
Any advice would be appreciated.
You have included OrbitControls from a relative path in your fiddle. Try it like so:
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x19d7f8);
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set(0,0,5);
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener('resize', function(){
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize(width, height);
camera.aspect = width/height;
camera.updateProjectionMatrix;
} )
const controls = new THREE.OrbitControls( camera, renderer.domElement );
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.124/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.124/examples/js/controls/OrbitControls.js"></script>
I create two scenes and two renderers, one is for simple 3D mesh sphere and another is for svg circle. SVG scene sits on top of Mesh scene, like an overlay. Sphere and circle are placed on the same position in 3D space. I use OrbitControls to look around. When program loads I see sphere and the circle in the same place, but when I look around I see another svg sphere on the opposite side. Why do I see two svg icons in 3D space and how to get rid of the second one? I know for sure it is one svg node, not two, but somehow orbit controls see it behind like in the mirror.
Here is demo link: http://mystic-peanut.com/mystic_sites/svgdouble/svg_sandbox.html
Here is code snippet:
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = -50;
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xff0000 );
meshScene = new THREE.Scene();
meshScene.background = new THREE.Color( 0x000000 );
// 3d sphere mesh added to mesh scene
var sphereGeometry = new THREE.SphereGeometry( 51, 60, 40 )
var mesh = new THREE.Mesh( sphereGeometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
mesh.name = 'pointer sphere';
mesh.position.set( 0, 0, 1500 );
meshScene.add( mesh );
// svg circle added to svg scene
node = document.createElementNS( 'http://www.w3.org/2000/svg', 'circle' );
node.setAttribute( 'stroke', 'black' );
node.setAttribute( 'fill', 'blue' );
node.setAttribute( 'r', '10' );
node.style.cursor = 'pointer';
var object = new THREE.SVGObject( node );
object.position.x = 0;
object.position.y = 0;
object.position.z = 1500;
scene.add( object );
meshRenderer = new THREE.WebGLRenderer( { antialias: true } );
meshRenderer.setPixelRatio( window.devicePixelRatio );
meshRenderer.setSize(window.innerWidth, window.innerHeight);
meshRenderer.domElement.style.position = 'absolute';
meshRenderer.domElement.style.top = '0px';
threeJSCanvas.appendChild( meshRenderer.domElement );
renderer = new THREE.SVGRenderer( {alpha: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setQuality( 'low' );
renderer.domElement.style.position = 'absolute';
renderer.domElement.style.top = '0px';
renderer.domElement.style.zIndex = 2;
renderer.setClearColor( 0x000000, 0);
threeJSCanvas.appendChild( renderer.domElement );
// controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)
controls.minDistance = 10;
controls.maxDistance = 100;
controls.maxPolarAngle = 2*Math.PI / 3;
controls.minPolarAngle = Math.PI / 3;
This issue was fixed within this ticket:
github.com/mrdoob/three.js/issues/15476
I want to to enable dat-gui controls for the threejs camera in the basic threejs example on this page:
https://github.com/mrdoob/three.js/
var camera, scene, renderer;
var geometry, material, mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 1000;
scene = new THREE.Scene();
geometry = new THREE.CubeGeometry( 200, 200, 200 );
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
// note: three.js includes requestAnimationFrame shim
requestAnimationFrame( animate );
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
I've tried the following code:
var params = {
z: 100
}
var gui = new dat.GUI();
gui.add(params, 'z', -500,500).step(5).onChange(function(value){
changeCameraZ(value);
});
function changeCameraZ(value){
camera.position.z = value;
}
which works, but it means that I have to write a new function:
changeBlah();
for each three.js variable I wish to change from the GUI. Is there a better, cleaner way of achieving this?
You could also make use of how DAT.gui makes use of references.
gui.add( camera.position , 'z', -500, 500 ).step(5)
and an example
http://jsfiddle.net/2WKqL/2/
This one-liner should work.
gui.add( params, 'z', -500, 500 ).step(5).onChange( function( value ){ camera.position.z = value; } );