Place a Three.js scene within a jQuery modal dialogue box

I am attempting to integrate a Three.js scene into a jQuery modal window. The objective is to utilize the Three.js scene in a larger window size. This scene should be displayed after clicking on an image that represents the scene in a smaller dimension.

You can view an example of what I have achieved so far: here

Currently, I have an image at the center and when hovered over and clicked, the intention is for the Three.js scene to appear in a modal window.

However, upon testing, when I click on the image, things don't turn out as expected (the scene window appears at the top-left corner, overlapping with the image ...)

To explain my approach, here's the JavaScript source code link:

When a user hovers over the image and clicks it (imageElement DOM), the following code snippet is executed (based on a standard jQuery modal window implementation):

imageElement.onclick = function RaiseWindow() {                                          
      
      var popID = 'canvas'; // Identify the pop-up                                           
      var popWidth = 700; // Set width                                                  
      
      // Display the pop-up and add a closing button
      $('#' + popID).fadeIn().css({ 'width': popWidth}).prepend('<a href="#" class="close"><img src="../close_pop.png" class="btn_close" title="Close Window" alt="Close" /></a>');                                                                                        
                                                                                         
      // Calculate margin to center the window - adjust by 80px                                  
      var popMargTop = ($('#' + popID).height() + 80) / 2;                               
      var popMargLeft = ($('#' + popID).width() + 80) / 2;                               
                                                                                         
      // Apply Margin Styles to the Popup                                                           
      $('#' + popID).css({                                                               
        'margin-top' : -popMargTop,                                                      
        'margin-left' : -popMargLeft                                                     
        });                                                                              
                                                                                         
      // Show background                                                              
      $('body').append('<div id="fade"></div>');                                         
      $('#fade').css({'filter' : 'contrast(0.3)'}).fadeIn();                             
                                                                                         
      return false;                                                                      
    };                     

The container (div) with id canvas is obtained using the following:

// Div container for canvas                                                              
container = document.getElementById('canvas');                                                                                                     
container.style.display = 'none';                                                                   
                                                                                         
// Initialize WebGLRenderer renderer                                                       
renderer = new THREE.WebGLRenderer({ antialias: true });                                                                                         
renderer.setSize(CANVAS_WIDTH, CANVAS_HEIGHT);                                           
renderer.sortObjects = true;                                                             
// AppendChild renderer to container                             
container.appendChild(renderer.domElement);                                              
                                                             

Initially, I set

container.style.display = 'none';
to prevent the scene from being drawn before clicking on the image.

In the HTML source, I have added the following:

<td class="body_content"><br>
    <!-- WebGL into td body_content -->
    <div id="canvas" class="center"></div>
    <!-- Javascript -->                                                                  
    <script src="js/sphere_dev.js"></script>                                                                                     
</td>

Currently, the modal window does not appear when clicked, and the reason escapes me. After resolving this issue, I may need to remove

container.style.display = 'none';
, but doing this initially causes both Three.js and the image to appear.

How can I first display the modal window followed by the Three.js scene inside it?

Update 1

Progress has been made. I have managed to grey out the entire window, but the popup remains invisible.

In the HTML code, I have included the following:

    <!-- WebGL into td body_content -->
    <div id="canvas" data-width="500" data-rel="popup_webgl" class="center"></div>
    <!-- HTML content of popup_webgl -->
    <div id="popup_webgl" class="popup_block">
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce euismod efficitur est, eget vehicula leo volutpat ac. Nullam finibus purus nec orci consectetur, et varius urna fermentum. </p>
    </div>
    <!-- Javascript -->
    <script src="js/sphere_dev.js"></script>

In the sphere_dev.js file, I have implemented the following logic:

imageElement.onclick = function RaiseWindow() {

    var popID = $(this).data('rel'); // Retrieve pop-up ID
    var popWidth = $(this).data('width'); // Get width

    // Make the popup visible and add a close button
    $('#' + popID).fadeIn().css({ 'width': popWidth}).prepend('<a href="#" class="close"><img src="./close_pop.png" class="btn_close" title="Close Window" alt="Close" /></a>');

    // Calculate margins for centering
    var popMargTop = ($('#' + popID).height() + 80) / 2;
    var popMargLeft = ($('#' + popID).width() + 80) / 2;

    // Apply Margins to the Popup
    $('#' + popID).css({
      'margin-top' : -popMargTop,
      'margin-left' : -popMargLeft
      });

    // Show background
    $('body').append('<div id="fade"></div>');
    $('#fade').css({'filter' : 'contrast(0.8)'}).fadeIn();

    return false;
};

//Close Popups and Fade Layer
$('body').on('click', 'a.close, #fade', function() {
    $('#fade , .popup_block').fadeOut(function() {
      $('#fade, a.close').remove();
      });

    return false;
    });

You can view the updated version at this link.

Despite greying out the full window upon clicking, the popup itself is not visible. Why is this happening?

Update 2

After following various suggestions, I have successfully displayed the Three.js scene, albeit with a centering issue.

You can see the latest results at this link

Upon clicking the image to display the popup, the layout appears off-center (observed in Firefox and Chrome):

https://i.stack.imgur.com/cIKqO.jpg

The problem lies in the misalignment of the popup (slightly shifted horizontally and vertically off-center, with the bottom portion missing).

In an attempt to correct this, I have utilized the following calculations (where mainWidth and mainHeight are global variables):

// Maintain proportions for popup (from image dimensions: width=900, height=490)
// Set popup width to 90% of available width and calculate height accordingly:
var mainWidth = 0.9*window.innerWidth,
    mainHeight = mainWidth*(490/900);


imageElement.onclick = function RaiseWindow() {

    var popWidth = mainWidth;
    var popHeight = mainHeight;
    var xPop = (window.innerWidth/2) - (popWidth/2);
    var yPop = (window.innerHeight/2) - (popHeight/2);    

    console.log('print popWidth = ', popWidth);
    console.log('print popHeight = ', popHeight);

    console.log('print x = ', xPop);
    console.log('print y = ', yPop);

    // Make the popup visible and add a closing button
    $('#' + popID).fadeIn().css({'position': 'fixed', 'width': popWidth+'px', 'height': popHeight+'px', 'top': xPop+'px', 'left': yPop+'px'}).prepend('<a href="#" class="close"><img src="./close_pop.png" class="btn_close" title="Close Window" alt="Close" /></a>');

    // Display the background
    $('body').append('<div id="fade"></div>');
    $('#fade').css({'filter' : 'contrast(0.8)'}).fadeIn();

    return false;
};

Please note that the window.offsetHeight function didn't work on Firefox and Chrome, requiring the use of window.innerHeight instead.

Below is the CSS styling applied to the popup:

.popup_block{
display: none; /* hidden by default */
background: #fff;
padding: 20px;
border: 20px solid #ddd;
font-size: 1.2em;
position: fixed;
z-index: 99999;
/*--CSS3 Shadow Definitions--*/
-webkit-box-shadow: 0px 0px 20px #000;
-moz-box-shadow: 0px 0px 20px #000;
box-shadow: 0px 0px 20px #000;
/*--CSS3 Rounded Corners--*/
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}

You can access the complete CSS code at this link.

How can I resolve the centering issue with the popup?

Answer №1

To enhance the functionality of your existing code, consider moving your canvas element inside the popup div#fade block. Instead of completely removing it on a body click event, simply hide it by applying a fadeOut effect when either the a.close or body is clicked. Modify the image click event as follows:

$('#contrast').get(0).onclick = function RaiseWindow() {
//$('a.poplight').on('click', function() {

    var popID = $(this).data('rel'); // Obtain popup name
    var popWidth = $(this).data('width'); // Get width

    // Display and set up closing button for the popup
    $('#' + popID).fadeIn().css({ 'width': popWidth}).prepend('<a href="#" class="close"><img src="./close_pop.png" class="btn_close" title="Close Window" alt="Close" /></a>');

    // Calculate margins to center window - offset by 80 pixels
    var popMargTop = ($('#' + popID).height() + 80) / 2;
    var popMargLeft = ($('#' + popID).width() + 80) / 2;

    // Apply calculated margin to Popup
    $('#' + popID).css({ 
        'margin-top' : -popMargTop,
        'margin-left' : -popMargLeft
        });

    // Display background
    //$('body').append('<div id="fade"></div>');
    //$('#fade').css({'filter' : 'contrast(0.8)'}).fadeIn();
    //$('#fade').css({'filter' : 'alpha(opacity=0.99)'}).fadeIn();

    if($('#fade').length > 0) {
        $('#fade').fadeIn();
    } else {
        $('<div>', { id: 'fade' })
            .appendTo('body')
            .css({'filter' : 'contrast(0.8)'})
            .append($('#canvas').show())
            .fadeIn();
    }

    return false;
};

Adjust the a.close, body click event handler like this:

$('body').on('click', 'a.close, #fade', function() { // Click on body
    $('#fade , .popup_block').fadeOut(); // Fade out elements
});

Witness this implemented through my demonstration which can be seen here:

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

Creating a simulated textarea with a scrollbar and dynamically refreshing the content

Due to limitations on markup content inside <p> tags, I have decided to create my own custom textbox. This textbox will function as a console where the battle progress is logged. Initially, I attempted using nested divs for each log, but encountered ...

The hovering event trail feature is not functioning in tsParticles, unlike in particlejs

I have two questions regarding the implementation of tsParticles in my React application. First question: <Particles id="tsparticles" options={{ background: { color: { value: "black&quo ...

Margin challenge in CSS

Just starting out with CSS, so please be patient with me. I'm currently working on customizing a form and everything is looking good, except for the confirmation label which is located in a div. I've managed to create space between other elements ...

If the text is too lengthy, enclose it within a div element

I am facing an issue with a fixed width DIV of 300px. Within this DIV, I have dynamic text that sometimes exceeds the width and gets cut off. Is there a way to make the text wrap when it exceeds the 300px limit without increasing the height of the DIV? Is ...

Cover the entire section with an image

I'm aiming to achieve a similar layout like this (using tailwind) : https://i.stack.imgur.com/G0oti.png Here's the current setup: <section class="bg-juli-white pt-24"> <div class="max-w-6xl mx-auto flex flex-col" ...

Transitioning JS/CSS effects when the window is inactive

My latest project involved creating a small slider using JavaScript to set classes every X seconds, with animation done through CSS Transition. However, I noticed that when the window is inactive (such as if you switch to another tab) and then return, the ...

The segmented button's dropdown menu in Bootstrap is malfunctioning on Firefox version 27.0.1

I'm attempting to create a basic search bar using Bootstrap's segmented button feature (check out an example at http://getbootstrap.com/components/#input-groups-buttons-segmented). This is the code I have so far, and it's accessible on jsfi ...

What is the best way to adjust column sizes, setting one with a minimum width while allowing the other to expand to accommodate its content?

In the process of creating a user interface, I have included clickable cards that reveal a detailed panel when clicked. The detail panel is set to a minimum width of 900px and should adjust to the remaining space between the cards and itself. The column ...

The functionality of Ng-Show is acting up

$scope.stay = function() { alert("Inside Keep me In") $scope.timed = false; $scope.isLogStatus = true; } $scope.displayAlert = function() { $scope.timed = true; alert("inside display") } function idleTimer() { var t; $window.o ...

Update the positioning of the element to center instead of the default top left origin using jQuery

I am facing an issue with positioning a marker inside a triangle, which is represented by a simple div, as shown in the image below: https://i.stack.imgur.com/0Q7Lm.png The marker needs to be placed exactly at the centroid of the triangle. However, it see ...

What is the best way to position my Jchartfx area graph below my gridview?

When my page loads, the graph appears like this. It consistently shows up in the top left corner even though it should be positioned underneath the grid view as intended. var chart1; function createGraph(mpy) { if (mpy == undefined) mpy = 12.00; ch ...

An error occurred when attempting to run the command npm run compile:sass, displaying the message: npm ERR! missing script:

Everything seems to be in place with the sass folders and files, so what could be the issue? I have my package.json file set up correctly with the following code: { "name": "starter", "version": "1.0.0", " ...

Deploying CSS/JS files in Magento 2 is a crucial

Hello, I recently set up magento2 with the sample data included. After attempting to deploy static css/JS using the command php bin/magento setup:static-content:deploy, I didn't receive any errors but the issue persists. Additionally, I am unable to l ...

Turn off the CSS hover effect for a custom button if the ng disabled attribute is set to true

My goal is to disable custom buttons, and the disable(pointer) function is working correctly. The issue arises when we try to hover on the button, as the hover effect still works. I therefore need to disable hover as well. I am looking to apply ng-disabl ...

Customizing the scrollbar within a modal using reactjs-popup

I am currently working on a CustomPopup functional component that includes a reactjs-popup: function CustomPopup({setFalse, item}){return(<Popup open={true} onClose={() => {setFalse(false)}} modal closeOnDocumentClick nested> {item === "howto ...

Is there a way to modify the text color within the thumb-label of the Vuetify v-slider component?

Lately, I've been facing some challenges and my objective is to change the color of the thumb label on my v-slider to a custom one that is defined in the component's design. Can anyone provide guidance on how to achieve this? Regards, Joost ...

Chrome has some issues with resizing the SVG Pattern element

Utilizing inline svgs, I have a svg circle filled with a pattern that should cover 100% of the container size. However, when the parent element is resized via JavaScript, the pattern no longer reflects the 100% width and height as expected. This issue seem ...

The theme font fails to take effect on the paragraph

As a novice in HTML and CSS, I attempted to use the "Roboto Condensed" font from a WordPress theme for my entire site. Although I successfully implemented this custom font for a menu, I encountered difficulties when trying to apply it to paragraph elements ...

Bootstrap tab toggle feature

I'm currently facing an issue with Bootstrap's tab component. I need help figuring out how to hide a lorem ipsum section and show a hidden div when a specific tab is clicked, and then revert the changes when a different tab is selected. $(func ...

Is it possible to view the CSS of a PDF file in print template mode using Chrome?

https://i.stack.imgur.com/XlcWm.png Currently facing an issue with debugging CSS on my PDF template. I am unable to inspect the styles directly in the CSS due to limitations. When using inspect element in Chrome, only the styles for text and elements are ...