简体   繁体   English

将 style.transform 设置为父组件后模态(子组件)的行为发生奇怪变化

[英]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.聊天上传预览 div 是父元素,而模态是子元素。 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).但是,当通过向其添加 transform/translate CSS 属性使聊天上传预览可拖动时,模式只会扩展并覆盖上传预览器(父元素)的高度和宽度。 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.有趣的是,如果我删除这个可拖动的 function(转换/翻译),模态将恢复正常行为,一直扩展到屏幕边缘。 I wonder why adding the transform/translate CSS property to the style of the parent component affects the behavior of the child component.我想知道为什么在父组件的样式中添加 transform/translate CSS 属性会影响子组件的行为。 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):如果没有向父组件(聊天上传预览 div)添加转换/翻译,它通常看起来是这样的: 在此处输入图像描述

Here's how it starts looking after the transform/translate property is added to the parent component (Chat upload preview div):以下是在将 transform/translate 属性添加到父组件(Chat upload preview div)后它是如何开始查找的: 在此处输入图像描述

Here's the JSX code of the chat upload preview (parent).这是聊天上传预览(父级)的 JSX 代码。 The modal lives in the FilePreview component whose code is also below.模态存在于 FilePreview 组件中,其代码也在下方。

{/* 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).这是 FilePreview 组件的代码,它也包含模式的代码(在底部)。

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:这又是模态的 JSX:

 {/* 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.这是 function,它通过向其添加 transform/translate 属性来拖动聊天上传预览。 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:这是聊天上传预览的(父组件)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:这是模态的 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?为什么它不能像添加 transform/translate 属性之前那样充分扩展? 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答案在关于 Transform 的 MDN 文章中: 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.答案:如果 transform 属性的值不同于 none,则会创建一个堆叠上下文。 In that case, the element (the one that has the transform property) will act as a containing block for any position: fixed;在这种情况下,该元素(具有 transform 属性的元素)将充当任何 position: fixed; 的包含块; or position: absolute;或 position:绝对; elements (modal div) that it contains.它包含的元素(模态 div)。

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.问题确实出在转换 CSS function 中。事实证明,转换将可拖动元素更改为一个包含块,该包含块将其内部的所有元素限制在其尺寸限制内。 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.更具体地说,Modal div 没有展开以填满整个屏幕,因为 transform 属性是在拖动时添加到 FilePreview 组件的。 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.结果,image-preview-container div(父元素)成为模态 div(子元素)的包含块,将其限制在其限制/边距内。

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:因此,解决方法是在单击图像时从包含块中删除 transform 属性,以便它可以像以前一样填满整个屏幕:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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