如何实现Material-UI Dialog从点击图片处过渡展开?
实现Material-UI Dialog从图片位置展开并过渡尺寸
核心思路
要实现这个效果,咱们需要两步关键操作:
- 精准获取触发图片在屏幕上的位置和尺寸,以此作为Dialog展开的原点和初始大小
- 结合
Grow过渡组件和自定义样式,让Dialog从图片的位置/尺寸平滑过渡到目标状态
步骤1:获取图片的屏幕坐标与尺寸
首先给触发图片加个ref,这样在Dialog打开时能拿到它的位置信息:
// 父组件中管理图片引用和Dialog状态 class ParentComponent extends Component { imageRef = React.createRef(); state = { previewImage: false, imgOrigin: '', imgSize: { width: 0, height: 0 } }; openDialog = () => { const imgRect = this.imageRef.current.getBoundingClientRect(); // 计算图片中心点作为展开原点,也可以改成左上角/右下角等 const origin = `${imgRect.left + imgRect.width/2}px ${imgRect.top + imgRect.height/2}px`; this.setState({ previewImage: true, imgOrigin: origin, imgSize: { width: imgRect.width, height: imgRect.height } }); }; render() { return ( <> <img ref={this.imageRef} src="your-image-url" onClick={this.openDialog} style={{ cursor: 'pointer' }} /> <ImagePopup previewImage={this.state.previewImage} close={() => this.setState({ previewImage: false })} imgOrigin={this.state.imgOrigin} imgSize={this.state.imgSize} /> </> ); } }
步骤2:修改Dialog的过渡与样式
接下来调整ImagePopup组件,让它用获取到的原点和初始尺寸实现过渡:
class ImagePopup extends Component { popupTransition(props) { return ( <Grow {...props} style={{ transformOrigin: this.props.imgOrigin }} timeout={500} /> ); } render() { const { imgSize, previewImage } = this.props; return ( <Dialog TransitionComponent={this.popupTransition.bind(this)} onClose={this.props.close} open={previewImage} // 自定义Paper的样式,实现尺寸过渡 PaperProps={{ style: { position: 'fixed', left: '50%', top: '50%', transform: 'translate(-50%, -50%)', minWidth: 'auto', // 初始尺寸和图片一致,展开后过渡到目标大小 width: previewImage ? '80vw' : imgSize.width, height: previewImage ? '80vh' : imgSize.height, transition: 'width 0.5s ease, height 0.5s ease' } }} maxWidth="lg" fullWidth > <DialogTitle id="alert-dialog-title">{"图片预览"}</DialogTitle> <DialogContent style={{ height: 'calc(100% - 64px)' }}> <img src="your-large-image-url" style={{ width: '100%', height: '100%', objectFit: 'contain' }} /> </DialogContent> </Dialog> ); } }
关键细节说明
- transformOrigin:通过父组件传递的图片原点,让
Grow组件以图片位置为中心展开 - 尺寸过渡:给Dialog的Paper设置初始尺寸(和图片一致),打开时自动过渡到目标尺寸(80vw/80vh),配合
Grow的缩放效果,实现完整的展开动画 - 定位处理:用
position: fixed和translate(-50%, -50%)确保Dialog从图片位置平滑移动到屏幕中心
函数组件版优化(可选)
如果习惯用函数组件,结合useRef和useEffect会更简洁:
function ImagePopup({ previewImage, close, imgOrigin, imgSize }) { const popupTransition = (props) => ( <Grow {...props} style={{ transformOrigin: imgOrigin }} timeout={500} /> ); return ( <Dialog TransitionComponent={popupTransition} onClose={close} open={previewImage} PaperProps={{ style: { position: 'fixed', left: '50%', top: '50%', transform: 'translate(-50%, -50%)', minWidth: 'auto', width: previewImage ? '80vw' : imgSize.width, height: previewImage ? '80vh' : imgSize.height, transition: 'width 0.5s ease, height 0.5s ease' } }} maxWidth="lg" fullWidth > <DialogTitle>图片预览</DialogTitle> <DialogContent style={{ height: 'calc(100% - 64px)' }}> <img src="your-large-image-url" style={{ width: '100%', height: '100%', objectFit: 'contain' }} /> </DialogContent> </Dialog> ); }
内容的提问来源于stack exchange,提问作者meds
相关产品推荐
相关产品推荐

