Search code examples
javascriptjquerycsscanvasthree.js

Set Three.js scene into a jQuery modal window


I try to insert a Three.js scene into a jQuery modal window. The goal is to use the Three.js scene with bigger dimensions, i.e in a bigger window. This scene is expected to appear after clicking on an image which represents the scene but with a smaller dimension.

Right now, you can see an example of what I have managed to do: on this link

As you can see, I have a centered image and if a mouse is over it and click it, the expected result is to have the Three.js scene into a modal window.

But, as you can test it, if I click, things are totally wrong (a scene window appears at the top-left, in addition to the image ...)

I explain what I did (see JavaScript source HERE) :

When user is over image and click it (imageElement DOM), I call the following part of code (which is inspired from a standard jQuery modal window code) :

imageElement.onclick = function RaiseWindow() {                                          
      
      var popID = 'canvas'; // Find the pop-up                                           
      var popWidth = 700; // Width                                                  
      
      // Make appear pop-up and add 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>');                                                                                        
                                                                                         
      // Get margin to center window - adjust with 80px                                  
      var popMargTop = ($('#' + popID).height() + 80) / 2;                               
      var popMargLeft = ($('#' + popID).width() + 80) / 2;                               
                                                                                         
      // Apply Margin to Popup                                                           
      $('#' + popID).css({                                                               
        'margin-top' : -popMargTop,                                                      
        'margin-left' : -popMargLeft                                                     
        });                                                                              
                                                                                         
      // Display background                                                              
      $('body').append('<div id="fade"></div>');                                         
      $('#fade').css({'filter' : 'contrast(0.3)'}).fadeIn();                             
                                                                                         
      return false;                                                                      
    };                     

The container (div) for id canvas is got by doing :

// Div container for canvas                                                              
container = document.getElementById('canvas');                                                                                                     
container.style.display = 'none';                                                                   
                                                                                         
// Initiate 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 did container.style.display = 'none'; because otherwise, the scene is drawn whereas I have not clicked on the image.

In HTML source, I have done :

<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 is not displayed when I click and I don't understand why. Then, after this first issue, Surely I will have to remove container.style.display = 'none'; but I can't do this firstly (Three.js will appear and the image too).

How can I display firstly the modal window and after the Three.js scene into this window.

Update 1

I have progressed. I manage to grey full window but the popup is not displayed.

In the HTML code, I did :

    <!-- 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>Aliquip transverbero loquor esse ille vulputate exerci veniam fatua eros similis illum valde. Praesent, venio conventio rusticus antehabeo lenis. Melior pertineo feugait, praesent hos rusticus et haero facilisis abluo. </p>
    </div>
    <!-- Javascript -->
    <script src="js/sphere_dev.js"></script>

Into sphere_dev.js code, Here what I did (at the beginning, I get back rel and width variables, and after I use fadeIn) :

imageElement.onclick = function RaiseWindow() {

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

    // Make appear pop-up and add 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>');

    // Get margin to center window - adjust with 80px
    var popMargTop = ($('#' + popID).height() + 80) / 2;
    var popMargLeft = ($('#' + popID).width() + 80) / 2;

    // Apply 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();

    return false;
};

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

    return false;
    });

You can check the last results on this link.

Why is the popup not displayed even if full window is grey after clicking.

Update 2

Following the different answers, I can get to display the Three.js scene but an issue of centering is occurring.

You can check the last results on this link

As you can see, if you click on image to display popup, you get this (on Firefox and Chrome) :

Capture of popup

The issue is that popup is not centered (slightly shifted horizontally to the right and vertical margin on top too high, and finally bottom of popup not visible).

I tried to center it by doing (mainWidth and mainHeight are global variables) :

// Keep good proportions for popup (from image (width=900, height=490))
// For popup, set 90% of available width and compute height from this value :
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);

    // window.offsetHeight not working
    //console.log('window.offsetHeight = ', window.offsetHeight);

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

    // Make appear pop-up and add 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 background
    $('body').append('<div id="fade"></div>');
    // Working only for background
    $('#fade').css({'filter' : 'contrast(0.8)'}).fadeIn();

    return false;
};

I have to make you notice that function window.offsetHeight doesn't work on Firefox and Chrome, instead of this, I have to use window.innerHeight.

Here's the CSS I used for this popup :

.popup_block{
display: none; /* masked by default */
background: #fff;
padding: 20px;
border: 20px solid #ddd;
font-size: 1.2em;
position: fixed;
z-index: 99999;
/*--Les différentes définitions de Box Shadow en CSS3--*/
-webkit-box-shadow: 0px 0px 20px #000;
-moz-box-shadow: 0px 0px 20px #000;
box-shadow: 0px 0px 20px #000;
/*--Coins arrondis en CSS3--*/
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}

The entire CSS is available on this link.

How can I fix this issue of centering.


Solution

  • As with the code you already have, you can just move your canvas element inside the popup div#fade block and then instead of destroying it on body click, hide it by just leaving fadeOut on the a.close, body click event. Try to change the image click event to be like this:

    $('#contrast').get(0).onclick = function RaiseWindow() {
    //$('a.poplight').on('click', function() {
    
        var popID = $(this).data('rel'); // Get name of pop-up
        var popWidth = $(this).data('width'); // Get width
    
        // Make appear pop-up and add 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>');
    
        // Get margin to center window - adjust with 80px
        var popMargTop = ($('#' + popID).height() + 80) / 2;
        var popMargLeft = ($('#' + popID).width() + 80) / 2;
    
        // Apply 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;
    };
    

    and the a.close, body click event handler to be like this:

    $('body').on('click', 'a.close, #fade', function() { // When click body
        $('#fade , .popup_block').fadeOut(); // They disappear
    });
    

    See my screen capture with it working here: http://zikro.gr/dbg/html/treejs-canvas-popup/