简体   繁体   中英

Strange change in the behavior of a modal (child component) after setting style.transform to the parent component

I am experiencing a weird change in the appearance or behavior of a modal. The modal is used to enlarge an image sent in a chat. A chat upload preview div is the parent element while the modal is a child element. This strange behavior started happening after I made the chat upload preview draggable with some functions. Under normal conditions, the modal expands and covers the entire screen, going outside of the boundaries of the upload preview (parent component). However, when the chat upload preview is made draggable by adding the transform/translate CSS property to it, the modal only expands and covers the height and width of the upload previewer (parent element). Interestingly enough, if I remove this draggable function (transform/translate), the modal snaps back to its normal behavior, expanding all the way to the edges of the screen. I wonder why adding the transform/translate CSS property to the style of the parent component affects the behavior of the child component. This has really puzzled me. Please help.

Here's how it would normally look without the transform/translate addition to the parent component (Chat upload preview div): 在此处输入图像描述

Here's how it starts looking after the transform/translate property is added to the parent component (Chat upload preview div): 在此处输入图像描述

Here's the JSX code of the chat upload preview (parent). The modal lives in the FilePreview component whose code is also below.

{/* CHAT-UPLOAD-PREVIEW */}                        
{
    this.state.chatFiles.length > 0 ? 

    <div className="chat-upload-preview-1"
    ref={this.myUploader}
    onMouseMove={this.onMouseMove}
    onMouseDown = {() => {this.setState({pressed: true})}}
    onMouseUp = {() => {this.setState({pressed: false})}}
    >


        <p className="close-button-1" onClick={this.closeUploadPreview}>&#10006;</p>

    <h3 className="chat-upload-preview-title-1">Preview</h3>

    <div className="file-preview-div-1">**<FilePreview files={this.state.chatFiles} 
    deletePreviewfile={this.deletePreviewfile2}
    getReadableFileSizeString={this.getReadableFileSizeString}
    /> </div>**
    
    <div className='chat-upload-container-1'>
    <img src='/images/chat-upload.jpg' alt="upload" height="70" 
    width="70" className='chat-upload-3' onClick={this.inputClick2}>                         
    </img>
                <input className="file-input" type="file" name="file" id="file-1"
                onChange={this.handleChange2} multiple 
                accept=".jpg, .jpeg, .png, .pdf, .doc, .docx"></input> 

                <button className="chat-upload-send-button-1" onClick={this.sendImageToChat}>Send</button>  
    </div> 
    
    </div>
    :
    null

}     

Here's the code of the FilePreview component which contains the modal's code too (on the bottom).

import React from 'react'
import './FilePreview.css'

function FilePreview(props) {
    return (
        <div className="image-preview-container">

                            <ul className="image-preview-list">
                            {props.files.map((item) =>                           
                           

                                <li className="image-preview-listItem" key={item.name}>
                                            
                                                                                  
                                            {item.type === "application/pdf"  ?
                                            
                                                // PDF


                                            <div className="pdf-file" >

                                          
                                        <iframe src={URL.createObjectURL(item)} className="iframe-pdf"
                                            height="110" width="100" title="pdf-review">
                                                </iframe>

                                            <a className="pdf-link" href={URL.createObjectURL(item)} target="_blank">view pdf</a>

                                                 <button className="document-image-deleter" onClick={() => props.deletePreviewfile(item)}>x</button>

                                <p className="file-name">{item.name}</p> 
                                <p className="file-size">{props.getReadableFileSizeString(item.size)}</p>    
                                            </div>
                                            
                                            :

                                                    // WORD

                                                                                    
                                            item.type === "application/msword" ?

                                            <div className="pdf-file" >
                                                

                                                <img className="document-image" src="images\msword.png" alt="your file" height="50" width="50"/> 

                                                    
                                            <a className="pdf-link" href={URL.createObjectURL(item)} target="_blank">download to view</a>

                                        <button className="document-image-deleter" onClick={() => props.deletePreviewfile(item)}>x</button>

                                <p className="file-name">{item.name}</p> 
                                <p className="file-size">{props.getReadableFileSizeString(item.size)}</p>
                                            </div>

                                            :

                                                    // WORD docx

                                            item.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ?

                                            <div className="pdf-file" >
                                                

                                                <img className="document-image" src="images\msword.png" alt="your file" height="50" width="50"/> 

                                                    
                                            <a className="pdf-link" href={URL.createObjectURL(item)} target="_blank">download to view</a>

                                        <button className="document-image-deleter" onClick={() => props.deletePreviewfile(item)}>x</button>

                                <p className="file-name">{item.name}</p> 
                                <p className="file-size">{props.getReadableFileSizeString(item.size)}</p>    
                                            </div>

                                            :

                                                        // Image - Jpeg    

                                            item.type === "image/jpeg" ?   

                                                        

                                            <div className="image-file">

                                          {console.log(URL.createObjectURL(item))}

                                                <img className="document-image" src={URL.createObjectURL(item)} alt="your file" height="50" width="50" 
                                    
                                    onClick={() => {
                                        
                                        const modal = document.getElementById("myModal");
                                        const modalImg = document.getElementById("img01");

                                        modal.style.display = "block";
                                        modalImg.src = URL.createObjectURL(item);

                                    }}>

                                    </img>

                                        <button className="document-image-deleter" onClick={() => props.deletePreviewfile(item)}>x</button>

                                    <p className="file-name">{item.name}</p> 
                                    <p className="file-size">{props.getReadableFileSizeString(item.size)}</p>     

                                            </div>

                                            :
                                                        // Image - png

                                            item.type === "image/png" ?                                               

                                            <div className="image-file">

                                            {console.log(URL.createObjectURL(item))}

                                                <img className="document-image" src={URL.createObjectURL(item)} alt="your file" height="50" width="50" 

                                            onClick={() => {

                                            const modal = document.getElementById("myModal");
                                            const modalImg = document.getElementById("img01");

                                            modal.style.display = "block";
                                            modalImg.src = URL.createObjectURL(item);

                                            }}>

                                            </img>

                                            <button className="document-image-deleter" onClick={() => props.deletePreviewfile(item)}>x</button>

                                            <p className="file-name">{item.name}</p> 
                                            <p className="file-size">{props.getReadableFileSizeString(item.size)}</p>     

                                            </div>

                                            :

                                                         // Others to be added

                                            <div className="image-file">
                                                <img className="document-image" src={URL.createObjectURL(item)} alt="your file" height="50" width="50" 
                                    
                                    onClick={() => {
                                        
                                        const modal = document.getElementById("myModal");
                                        const modalImg = document.getElementById("img01");

                                        modal.style.display = "block";
                                        modalImg.src = URL.createObjectURL(item);

                                    }}>

                                    </img>

                                        <button className="document-image-deleter" onClick={() => props.deletePreviewfile(item)}>x</button>

                                    <p className="file-name">{item.name}</p> 
                                    <p className="file-size">{props.getReadableFileSizeString(item.size)}</p>     

                                            </div>


                                                                                    
                                                                                
                                            }
                                    
                                    


                                    {/* The Image PopUp */}

                                    <div id="myModal" className="modal">

                                                                                  
                                        {/* the close button (x) */}
                                        <span className="close" onClick={() => {
                                            const modal = document.getElementById("myModal");
                                            modal.style.display = "none";
                                        }}>&times;</span>

                                        {/* the image itself */}
                                        <img className="modal-content" id="img01" alt="Something"></img>

                                        {/* Text needs to be added */}
                                        <div id="caption"></div>

                                    </div>


                                </li>
                            )}                                                

                        </ul>                                    
            
        </div>
    )
}

export default FilePreview

Here's the JSX of the modal again:

 {/* The Image PopUp */}

                                    <div id="myModal" className="modal">

                                                                                   
                                        {/* the close button (x) */}
                                        <span className="close" onClick={() => {
                                            const modal = document.getElementById("myModal");
                                            modal.style.display = "none";
                                        }}>&times;</span>

                                        {/* the image itself */}
                                        <img className="modal-content" id="img01" alt="Something"></img>

                                        {/* Text needs to be added */}
                                        <div id="caption"></div>

                                    </div>

Here's the function that drags the chat upload preview by adding the transform/translate property to it. It seems to be the culprit in the modal's strange behavior because when I remove it, the modal behaves well again.

componentDidUpdate () {

        if (this.myUploader.current) {
          this.myUploader.current.style.transform = `translate(${this.state.position.x}px, ${this.state.position.y}px)`
          document.onmouseup = () => {this.setState({pressed: false})}
               
        }
      
        
      }

Here's the Chat Upload Preview's (parent component) CSS:

.chat-upload-preview-1 {
    position: absolute;
    bottom: 30px;
    left: 300px;
    background-color: blanchedalmond;
    width: 330px;
    height: 600px;
    border-radius: 20px;
    opacity: 0.9;

}

Here's the modal's css:

/* The Modal (background) */
.modal {
    display: none; /* Hidden by default */
    position: fixed; /* Stay in place */
    z-index: 1; /* Sit on top */
    padding-top: 100px; /* Location of the box */
    left: 0;
    top: 0;
    width: 100%; /* Full width */
    height: 100%; /* Full height */
    overflow: auto; /* Enable scroll if needed */
    background-color: rgb(0, 0, 0); /* Fallback color */
    background-color: rgba(0, 0, 0, 0.9); /* Black w/ opacity */
    
  }
  
  /* Modal Content (image) */
  .modal-content {
    margin: auto;
    display: block;
    width: 80%;
    max-width: 700px;
  }
  
  /* Caption of Modal Image */
  #caption {
    margin: auto;
    display: block;
    width: 80%;
    max-width: 700px;
    text-align: center;
    color: #ccc;
    padding: 10px 0;
    height: 150px;
  }
  
  /* Add Animation */
  .modal-content,
  #caption {
    -webkit-animation-name: zoom;
    -webkit-animation-duration: 0.6s;
    animation-name: zoom;
    animation-duration: 0.6s;
  }
  
  @-webkit-keyframes zoom {
    from {
      -webkit-transform: scale(0);
    }
    to {
      -webkit-transform: scale(1);
    }
  }
  
  @keyframes zoom {
    from {
      transform: scale(0);
    }
    to {
      transform: scale(1);
    }
  }

I just do not know what is happening with the modal once the upload preview has the transform/translate property added to it. Why would it not expand as fully as before the addition of the transform/translate property? I am completely puzzled.

So, I found the answer myself. And the answer was in the MDN article about Transform: https://developer.mozilla.org/en-US/docs/Web/CSS/transform

Answer: If the transform property has a value different than none, a stacking context will be created. In that case, the element (the one that has the transform property) will act as a containing block for any position: fixed; or position: absolute; elements (modal div) that it contains.

The issue was indeed in the transform CSS function. Turns out the Transform changes the draggable element into a containing block which restrains all the elements inside of it within its dimensional limits. In other words, all the inside elements will not get bigger than its height or width.

More specifically, the Modal div did not expand to fill the full screen because the transform property was added to the FilePreview component when it was dragged. As a result, the image-preview-container div (parent element) became a containing block for the modal div (child element), restraining it within its limits/margins.

So, the workaround is to remove the transform property from the containing block when the image is clicked so that it can fill the full screen as before:

if (props.myUploader) { props.myUploader.current.style.transform = 'none' }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM