react antd 实现图片自定义预览
本文最后更新于 13 天前,其中的信息可能已经有所发展或是发生改变。
功能需求
有这样一个需求,用户点击文字或者按钮,会弹出图片的预览界面,要求图片可旋转,可缩放以及可下载。由于antd组件的Image的预览窗口不包含图片下载的功能,所以这里通过modal对img添加预览模块。
实现过程
代码如下:
import React from 'react';
import './style.css';
import { Button, Modal } from 'antd';
import {
ZoomInOutlined,
ZoomOutOutlined,
UndoOutlined,
RedoOutlined,
DownloadOutlined,
} from '@ant-design/icons';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
imgSrc:
'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
imageVisible: false,
imgScale: '100%',
imgTransform: '',
imgCurrent: 0,
closeImagePreviewModel = () => {
this.setState({
imageVisible: false,
imgScale: '100%',
imgTransform: '',
imgCurrent: 0,
imgToBigger = () => {
let a = parseInt(this.state.imgScale) + 5 + '%';
this.setState({ imgScale: a });
imgToSmaller = () => {
let a = parseInt(this.state.imgScale) + -5 + '%';
this.setState({ imgScale: a });
//左旋转
imgToLeftRoll = () => {
let a = (this.state.imgCurrent - 90) % 360;
this.setState({ imgTransform: 'rotate(' + a + 'deg)', imgCurrent: a });
//右旋转
imgToRightRoll = () => {
let a = (this.state.imgCurrent + 90) % 360;
this.setState({ imgTransform: 'rotate(' + a + 'deg)', imgCurrent: a });
// 下载
downloadImage = () => {
const imgUrl = this.state.imgSrc;
const xhr = new XMLHttpRequest();
let url = imgUrl;
xhr.responseType = 'blob';
xhr.onload = function () {
if (this.status == '200') {
let blob = this.response;
let a = document.createElement('a');
a.style = '';
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function (e) {
a.download = 'test.jpg';
a.href = e.target.result;
document.body.append(a);
a.click();
a.remove();
xhr.open('get', url, true);
xhr.send();
render = () => {
const { imgScale, imgSrc, imgTransform, imageVisible } = this.state;
return (
<Button
onClick={() => {
this.setState({ imageVisible: true });
</Button>
<Modal
title="图片预览"
visible={imageVisible}
onCancel={this.closeImagePreviewModel}
style={{
top: 0,
maxWidth: '100vw',
paddingBottom: 0,
bodyStyle={{
textAlign: 'center',
height: 'calc(100vh - 118px)',
overflowY: 'auto',
width="100vw"
footer={[
<div style={{ margin: '0 auto', textAlign: 'center' }}>
<Button
style={{ border: 'none', padding: '5px 8px' }}
title="放大"
onClick={() => this.imgToBigger()}
<ZoomInOutlined />
</Button>
<Button
style={{ border: 'none', padding: '5px 8px' }}
title="缩小"
onClick={() => this.imgToSmaller()}
<ZoomOutOutlined />
</Button>
<Button
style={{ border: 'none', padding: '5px 8px' }}
title="逆时针旋转"
onClick={() => this.imgToLeftRoll()}
<UndoOutlined />
</Button>
<Button
style={{ border: 'none', padding: '5px 8px' }}
title="顺时针旋转"
onClick={() => this.imgToRightRoll()}
<RedoOutlined />
</Button>
<Button
style={{ border: 'none', padding: '5px 8px' }}
title="下载"
onClick={() => this.downloadImage()}
<DownloadOutlined />
</Button>
</div>,
src={imgSrc}
style={{
width: 'auto',
height: 'auto',
maxWidth: '100vw',
maxHeight: 'calc(100vh - 158px)',
position: 'relative',
margin: '0 auto',
scale: imgScale,
transform: imgTransform,