Skip to content
Advertisement

How to make two canvas with two separate javascript code?

I am using Three.js to develop a cube that translates and rotate in 3D space using data from accelerometer and gyroscope data.

So far I have one canvas that shows the accelerometer movement. Now I need to have another canvas that shows the gyroscope data on a separate canvas, I prefer to have two JS code for each canvas, so they are independent of each other. I wasn’t able to make two separate canvases, and I don’t know if it is even possible to use two different javascript codes in the html.

Below is how my HTML is structured:

HTML

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
</head>

<body>
    <canvas id="canvas" width="500" height="800" style="border:1px solid #eb1c1c;"></canvas>
    <div id="info">
        <div>t = <span id="time">0</span> s</div>
        <div>accX = <span id="accX">0</span></div>
        <div>accY = <span id="accY">0</span></div>
        <div>accZ = <span id="accZ">0</span></div>
    </div>

</body>
</html>

and this is the javascript:

import * as THREE from "three";
import data from "../data/data.json"
import "./style.css"

var width = window.innerWidth;
var height = window.innerHeight;
const canvas = document.querySelector('#canvas');
const renderer = new THREE.WebGLRenderer({ canvas });
renderer.setSize (width, height);

var planeSize = 100000
const fov = 70;
const aspect = 2;  // the canvas default
const near = 20;
const far = 500;

const camera = new THREE.PerspectiveCamera(70, width/height, 1, 10000);

camera.position.y = 3;
camera.position.z = 30;

camera.lookAt (new THREE.Vector3(0,0,0));
// camera.position.set(0, 40, 1.5);
// camera.up.set(0, 10, 1);
// camera.lookAt(0, 10, 0);

const scene = new THREE.Scene();
{
    const color = 0x00afaf;
    const intensity = 10;
    const size = 10;
    const divisions = 10;

    const gridHelper = new THREE.GridHelper( planeSize, 5000 );
    gridHelper.setColors( new THREE.Color(0xff0000), new THREE.Color(0xffffff) );
    scene.add(gridHelper);
    
    const light = new THREE.PointLight(color, intensity);
    scene.add(light);
    // scene.add( gridHelper );
}

// // label the axis
// var  textGeo = new THREE.TextGeometry('Y', {
//     size: 5,
//     height: 2,
//     curveSegments: 6,
//     font: "helvetiker",
//     style: "normal"       
// });

// var  color = new THREE.Color();
// color.setRGB(255, 250, 250);
// var  textMaterial = new THREE.MeshBasicMaterial({ color: color });
// var  text = new THREE.Mesh(textGeo , textMaterial);

// text.position.x = axis.geometry.vertices[1].x;
// text.position.y = axis.geometry.vertices[1].y;
// text.position.z = axis.geometry.vertices[1].z;
// text.rotation = camera.rotation;
// scene.add(text);

const boxGeometry = new THREE.BoxGeometry();
const boxMaterial = new THREE.MeshBasicMaterial({ color: "green", wireframe: false });
const object = new THREE.Mesh(boxGeometry, boxMaterial);

var cubeAxis = new THREE.AxesHelper(3);
object.add(cubeAxis);

object.scale.set(5, 5, 5)
scene.add(object);
scene.background = new THREE.Color(0.22, 0.23, 0.22);

let currentIndex = 0
let time = data[currentIndex].time
let velocity = new THREE.Vector3()
requestAnimationFrame(render);

function render(dt) {
    dt *= 0.0001 // in seconds
    time += dt
    document.querySelector("#time").textContent = time.toFixed(2)

    // Find datapoint matching current time
    while (data[currentIndex].time < time) {
        currentIndex++
        if (currentIndex >= data.length) return
    }
    const { rotX, rotY, rotZ, accX, accY, accZ } = data[currentIndex]
    document.querySelector("#accX").textContent = accX* 10;
    document.querySelector("#accY").textContent = accY* 10;
    document.querySelector("#accZ").textContent = accZ* 10;
    const acceleration = new THREE.Vector3()
    // object.rotation.set( rotX, rotY, rotZ)
    object.position.x = accX * 30;
    // object.position.add(velocity.clone().multiplyScalar(dt)).add(acceleration.clone().multiplyScalar(50 * dt ** 2))
    // object.position.add(accZ)
    // velocity.add(acceleration.clone().multiplyScalar(dt))

    var relativeCameraOffset = new THREE.Vector3 (0,10,10);
    var cameraOffset = relativeCameraOffset.applyMatrix4( object.matrixWorld );
    camera.position.x = cameraOffset.x;
    camera.position.y = cameraOffset.y;
    camera.position.z = cameraOffset.z;
    camera.lookAt( object.position );

    resizeToClient();
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

function resizeToClient() {
    const needResize = resizeRendererToDisplaySize()
    if (needResize) {
        const canvas = renderer.domElement;
        camera.aspect = canvas.clientWidth / canvas.clientHeight;
        camera.updateProjectionMatrix();
    }
}

function resizeRendererToDisplaySize() {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
        renderer.setSize(width, height, false);
    }
    return needResize;
}

this is how I want the canvas to look like:

enter image description here

Advertisement

Answer

Good news is it is possible, you just have to put all your code(at least animations) in separate functions :

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const scene1 = new THREE.Scene();
const camera1 = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

scene.background = new THREE.Color( 0xf0000f);
scene1.background = new THREE.Color( 0x0000ff );

const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );

const renderer1 = new THREE.WebGLRenderer();
renderer1.setSize( window.innerWidth, window.innerHeight );

renderer1.domElement.width=500;
renderer1.domElement.height=300;
renderer1.domElement.style.position="absolute";
renderer1.domElement.style.top=0;
renderer1.domElement.style.height=150+"px";
renderer1.domElement.style.width=200+"px";

renderer.domElement.width=500;
renderer.domElement.height=300;
renderer.domElement.style.position="absolute";
renderer.domElement.style.top=0;


document.body.appendChild( renderer.domElement );
document.body.appendChild( renderer1.domElement );

            const geometry = new THREE.BoxGeometry();
            const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
            const cube = new THREE.Mesh( geometry, material );
            scene.add( cube );
      
      const geometry1 = new THREE.BoxGeometry(3,3,3);
            const material1 = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
            const cube1 = new THREE.Mesh( geometry1, material1 );
            scene1.add( cube1 );

            camera.position.z = 5;
      camera1.position.z = 5;

            const animate = function () {
                requestAnimationFrame( animate );

                cube.rotation.x += 0.01;
                cube.rotation.y += 0.01;

                renderer.render( scene, camera );
            };
      
      const animate1 = function () {
                requestAnimationFrame( animate1 );

                cube1.rotation.x += 0.01;
                cube1.rotation.y += 0.01;

                renderer1.render( scene1, camera1 );
            };

            animate();
      animate1();
<script src="http://threejs.org/build/three.min.js"></script>
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement