效果图如上
react.tsx
import React from 'react';
import { message, Spin } from 'antd';
import { StepBackwardOutlined, StepForwardOutlined, CloseOutlined, ReloadOutlined } from '@ant-design/icons'
import styles from './index.less';
export interface ImgPath {
fileKey: string;
filePath: string;
}
interface ViewerProps {
imgUrls: ImgPath[];
onClose: () => void;
viewVisible: boolean;
}
interface viewerState {
imgUrls: ImgPath[];
current: number;
imgLoaded: boolean;
transform: number;
};
class RcViewer extends React.Component<ViewerProps>{
state: viewerState = {
imgUrls: [],
current: 0,
imgLoaded: false,
transform: 0,
};
constructor(props: ViewerProps) {
super(props);
};
static getDerivedStateFromProps(nextProps: any, prevState: any) {
if (nextProps.imgUrls) {
return {
imgUrls: nextProps.imgUrls,
};
}
return null;
}
pre = () => {
const { current, imgUrls } = this.state;
let index = current;
index--;
if (index < 0) {
message.error("没有上一张啦");
index = imgUrls.length - 1;
}
this.setState({
current: index,
})
};
next = () => {
const { current, imgUrls } = this.state;
let index = current;
index++;
if (index > imgUrls.length - 1) {
message.error("这是最后一张");
index = 0;
}
this.setState({
current: index,
})
};
close = () => {
const { onClose } = this.props;
onClose();
this.setState({
imgUrls: [],
transform: 0,
})
};
handleImgLoad = () => {
this.setState({
imgLoaded: true,
})
};
hanleTrans = () => {
this.setState({
transform: this.state.transform + 90,
})
};
render() {
const { imgUrls, current, imgLoaded, transform } = this.state;
const { viewVisible } = this.props;
return (
<div className={styles.content} style={{ display: viewVisible ? 'block' : 'none' }}>
<div className={styles.shadeBox}>
<div className={styles.imgoutsideBox} >
<div className={styles.imgBox}>
{!imgLoaded && <Spin />}
<img
src={imgUrls[current] ? imgUrls[current].filePath : ''}
onLoad={this.handleImgLoad}
title="图片"
style={{ display: imgLoaded ? 'block' : 'none', transform: `rotate(${transform}deg)` }} />
</div>
<div className={styles.iconStyle} onClick={this.pre}>
<StepBackwardOutlined title="上一张" />
</div>
<div className={styles.iconStyle} onClick={this.next} >
<StepForwardOutlined title="下一张" />
</div>
<div className={styles.iconStyle} onClick={this.hanleTrans} >
<ReloadOutlined title="旋转" />
</div>
</div>
<div className={styles.closeIcon} onClick={this.close}>
<CloseOutlined />
</div>
</div>
</div>
)
}
};
export default RcViewer;
index.less
.content{
position: fixed;
top:0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 9999;
.shadeBox{
box-sizing: border-box;
width: 100%;
height: 100%;
margin: 0 auto;
padding: 0;
color: rgba(0, 0, 0, 0.65);
list-style: none;
font-feature-settings: 'tnum';
position: absolute;
top:64px;
bottom: 64px;
z-index: 1060;
display: block;
min-width: 250px;
min-height: 250px;
visibility: visible;
}
.iconStyle{
display: inline-block;
height: 2rem;
width: 2rem;
margin: 10px;
line-height: 2rem;
border:1px solid #ddd;
text-align: center;
border-radius: 50%;
background-color: #fff;
cursor: pointer;
z-index: 999;
}
.iconStyle:active{
color:#108ee9;
}
.imgoutsideBox{
box-sizing:border-box;
width: 70%;
height: 70%;
margin:20px auto;
padding:46px 28px;
text-align: center;
background-color: rgba(0, 0, 0, 0.75);
border-radius: 2px;
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
overflow: hidden;
.imgBox{
width: 100%;
height: 100%;
overflow: hidden;
img{
// width:100%;
display: block;
margin: 0 auto;
height: 100%;
cursor: pointer;
}
}
}
.closeIcon{
display: block;
height: 3rem;
width: 3rem;
line-height: 3rem;
text-align: center;
border-radius: 50%;
border: 1.5px solid #ddd;
background-color:#fff;
cursor: pointer;
margin: 30px auto 0 auto;
}
.closeIcon:active{
color:#108ee9;
}
}