Creating interactive panorama hotspots with THREE.js SphereGeometry and DOMElements

After creating a WebGL 3D Panorama application using a SphereGeometry, PerspectiveCamera, and CanvasTexture, I am now trying to enhance the scene by adding "HotSpots" over specific areas of the SphereGeometry. However, I am facing difficulty in updating the positions of various DOMElements based on the Camera's movement.

As the Camera rotates, I want the DOMElements to move in and out of view according to the camera's spin direction. My attempts at positioning a div absolutely to the canvas and translating its X and Y positions using the PerspectiveCamera's rotation property did not yield desired results. Here is my implementation in JavaScript and CSS:

CSS

#TestHotSpot {
    margin-top: 50px;
    margin-left: 50px;
    width: 50px;
    height: 50px;
    background: red;
    position: absolute;
}

JavaScript

/** 
   CONFIG is a stored object variable that contains the PerspectiveCamera instance
**/

config.camera.updateProjectionMatrix();
config.controls.update(delta);

document.getElementById("TestHotSpot").style.transform = "translate("+ config.camera.rotation.x +"px, "+ config.camera.rotation.y +"px)";

Here is an example demonstrating the desired effect live.

I am seeking the best solution to resolve this issue. When testing my code, I noticed that the DOMElements moved only slightly and did not consider their placement relative to the SphereGeometry (e.g., if they were positioned behind the Camera). Any recommendations for resolving this complexity are appreciated!

I am open to utilizing plugins for the THREE.js engine or following tutorials. Thank you in advance for your assistance!

Answer №1

  1. Start by positioning a planemesh/mesh at the desired location.
  2. Take note of the coordinates of the CSS elements (domElements generated with three.js cssObject [if applicable]) in addition to the position of the planemesh/mesh.

Follow these steps and your task will be complete!

Answer №2

Joining in on my own query! I encountered some hurdles, but I have successfully integrated CSS3d with THREE.js WebGL scenes.

To start, I needed to update my THREE.js Library; I was using version 71 from an earlier download, but it was necessary to switch to the library Mr.Doob utilized in this demonstration. Additionally, I updated my CSS3d library to match the file included in that same example.

Subsequently, I followed the method outlined in the provided link to construct a demo scene.

var camera, scene, renderer;

var scene2, renderer2;

var controls;

init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
    camera.position.set( 200, 200, 200 );

    controls = new THREE.TrackballControls( camera );

    scene = new THREE.Scene();
    scene2 = new THREE.Scene();

    var material = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, wireframeLinewidth: 1, side: THREE.DoubleSide } );

            //

    for ( var i = 0; i < 10; i ++ ) {

        var element = document.createElement( 'div' );
            element.style.width = '100px';
            element.style.height = '100px';
            element.style.opacity = 0.5;
            element.style.background = new THREE.Color( Math.random() * 0xffffff ).getStyle();

        var object = new THREE.CSS3DObject( element );
            object.position.x = Math.random() * 200 - 100;
            object.position.y = Math.random() * 200 - 100;
            object.position.z = Math.random() * 200 - 100;
            object.rotation.x = Math.random();
            object.rotation.y = Math.random();
            object.rotation.z = Math.random();
            object.scale.x = Math.random() + 0.5;
            object.scale.y = Math.random() + 0.5;
        scene2.add( object );

        var geometry = new THREE.PlaneGeometry( 100, 100 );
        var mesh = new THREE.Mesh( geometry, material );
            mesh.position.copy( object.position );
            mesh.rotation.copy( object.rotation );
            mesh.scale.copy( object.scale );
        scene.add( mesh );

    }

            //

    renderer = new THREE.WebGLRenderer();
    renderer.setClearColor( 0xf0f0f0 );
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

    renderer2 = new THREE.CSS3DRenderer();
    renderer2.setSize( window.innerWidth, window.innerHeight );
    renderer2.domElement.style.position = 'absolute';
    renderer2.domElement.style.top = 0;
    document.body.appendChild( renderer2.domElement );

}

function animate() {

    requestAnimationFrame( animate );

    controls.update();

    renderer.render( scene, camera );
    renderer2.render( scene2, camera );

}

Once I had that functioning, I repurposed the CSS3d scene, CSS3d object, and the CSS3d renderer to include them in my scene.

Best of luck to others facing similar challenges, and may this offer assistance!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Developing a new class within a function

In this section of the HTML file, I have set up a form to collect email and password information from new users in order to create a new profile: <form name="userInfo"> <fieldset> <legend>Create a new account</legend> ...

I keep encountering an error that says "ReferenceError: localStorage is not defined" even though I have already included the "use

I have a unique app/components/organisms/Cookies.tsx modal window component that I integrate into my app/page.tsx. Despite including the 'use client' directive at the beginning of the component, I consistently encounter this error: ReferenceErr ...

What methods can be used to perform unit testing on a controller within an AngularJS Directive?

My command is: window.map.directive('dosingFrequencies', [ function() { return { restrict: 'E', scope: true, templateUrl: '/views/directives/dosingFrequencies.html', controller: function($scope, ...

While making a promise, an error occurred: TypeError - Unable to access the property '0' of null

I encountered an issue when trying to assign data from a function. The error appears in the console ((in promise) TypeError: Cannot read property '0'), but the data still shows on my application. Here is the code: <template> ...

Is there a way to share another person's contact card using whatsapp-web.js?

Is it possible to send a contact card of someone else using whatsapp-web.js, even if the person is not saved in my phone's contact list? I want to send a contact card to someone who is on my phone's contacts, but the contact information I want to ...

Ways to prevent mouse selection in an input field without disabling or making it read-only

Imagine this scenario: <input type="text"> The task at hand is to prevent text selection within the <input> field. ...

Tips for displaying a dropdown on top of a modal with the help of Tailwind CSS

I am currently utilizing Tailwind CSS and I am struggling to display the white dropdown over my modal. Despite attempting to use the z-index, I have been unsuccessful in getting it to work. Do you have any suggestions or insights on how to resolve this is ...

Stop the page from scrolling when scrolling within a specific DIV to address the [Violation] warning appearing in the console

Initially, it may seem like a duplicate question that has been answered here, but there are additional aspects that need to be addressed. How do I resolve the following [Violation] warning in the Google Chrome console? [Violation] Added non-passive eve ...

Switching between nested lists with a button: A simple guide

I have successfully created a nested list with buttons added to each parent <li> element. Here is how the list is structured: $("#pr1").append("<button id='bnt-cat13' class='buttons-filter'>expnd1</button>"); $("#pr ...

Textfield with autocomplete dropdown

I have a text field on my website that needs to work as an autocomplete box. I have included the following code in the "headerbar" section of my page: Find :<input type="text" class="input2" style="margin-bottom:0px;" id="customersearchfield"> < ...

How to display two elements side by side within a div using React

I have an array that looks like this: const arr = [1,2,3,4,5,6,7,8,9,10] I am looking to display the elements in pairs per line within two-dimensional divs. Here is what I have in mind: This represents the main React element: render() { return <di ...

How can HTML and CSS be linked to display images independently?

Check out this code: body{ background-image:url('http://wallpoper.com/images/00/31/33/51/black-background_00313351.jpg'); } div.header{ background-color:#F0F8FF; text-align:center; padding:3px; ...

I'm having trouble getting my innerHTML command to update anything on the webpage, and the reason is eluding me

Below is the code snippet provided: <div id="js"><button onclick="document.getElementById('js').innerHTML=('<form> <input type=text name=tick1></input> <input type=text name=tick2></input> ...

Updating the style of different input elements using Angular's dynamic CSS properties

I am seeking guidance on the proper method for achieving a specific functionality. I have a set of buttons, and I would like the opacity of a button to increase when it is pressed. Here is the approach I have taken so far, but I have doubts about its eff ...

In the middle of one div, there are two additional divs positioned nearby

I am facing a challenge with positioning three divs within one container. I want one to be on the right, another on the left, and the third one at the center, but so far I have not been successful; <div id="durum3" style="width: 100%; height: calc(10 ...

Guide on effectively sending a secondary parameter in an ajax request

Struggling to implement a year/make/model multi-select feature, I have managed to get the scripts working. However, what appears to be missing is the ability to pass both a year and make variable together in order to fetch the final model results. Below a ...

Sustain unbroken websocket connection with Discord using Node.js

I've been working on developing a Discord bot using the raw API, but I've encountered an issue where the bot stops functioning after some time. I suspect that this is due to neglecting to maintain the websocket connection. How can I ensure that ...

The alert message fails to appear during an Ajax request

I'm having trouble understanding why the Ajax function in this code snippet is not triggering the success or error functions: function get_cust_key(custid) { $.ajax({ type: "POST", url: 'http://localhost/Test/index.php/getCust ...

The MongoDB .push operation is returning a null value

Take a look at the GitHub repository where I am actively working: https://github.com/Stick-z/first-media-app I'm currently in the process of creating a website and focusing on the backend development. One of my tasks involves setting up a jokes array ...