/*
* 图片预览组件
* @Author: Jiang
* @since: 2018-12-21 13:54:00
*/
import React from 'react';
import { Modal, Icon } from 'antd';
import PropTypes from 'prop-types';
import config from 'Common/config';
import { redirect } from 'Common/util';
import './index.less';
// 判断游览器
const USER_AGENT = navigator.userAgent;
export default class PreviewImage extends React.Component {
constructor(props) {
super(props);
// 是否按下
this.isDown = false;
this.IMG_WIDTH = 300;
this.IMG_HEIGHT = 300;
// 放大或缩小比例
this.zoomOut = 0;
this.state = {
// 移动的时候,更改距离和放大缩小
imgStyle: {
position: 'relative',
left: '0px',
top: '0px'
},
// 放大缩小比例
num: 0,
// 是否显示缩小放大比例
isShowRate: false,
// true 为图片模式, false为pdf|word|xls预览模式
isShowPreView: false
};
// 图片按下事件
this.handlerImgDown = this.handlerImgDown.bind(this);
// 图片加载
this.onload = this.onload.bind(this);
}
componentDidMount() {
const { url, destruction } = this.props;
// true 打开弹窗 false 预览pdf or xls or word
if(this.getType(url)) {
const getType = this.getType(url);
if(document.addEventListener && USER_AGENT.indexOf('Firefox') > -1) {
document.addEventListener('DOMMouseScroll', this.onScroll, false);
} else {
document.body.onmousewheel = this.onScroll;
}
this.setState({
isShowPreView: getType
});
} else {
this.openUrl(url);
destruction();
}
}
// 销毁
componentWillUnmount() {
document.onmousemove = null;
document.onmouseup = null;
document.body.onmousewheel = null;
document.removeEventListener('DOMMouseScroll', this.onScroll, false);
}
// 取得文件后缀名
getFileSuffix = url => {
const fileArr = url.split('.');
return fileArr[fileArr.length - 1].toLocaleLowerCase();
}
// 根据文件类型是跳转页面还是预览图片
getType = url => {
if(url) {
let suffix = this.getFileSuffix(url);
if(suffix.indexOf('?') > -1) {
suffix = suffix.split('?')[0];
}
return config.FILE_TYPE.IMAGE.indexOf(suffix) > -1;
}
}
// 缩小或放大
onScroll = (e) => {
const { num, imgStyle } = this.state;
const event = e || window.event;
let style = {};
let wheelDelta;
let wheelDeltaNumber;
let rate;
// firefox and safari 的滚动轴值不一样,其余的都是1200
if(USER_AGENT.indexOf('Firefox') > -1) {
// wheelDelta = 3 or -3
wheelDelta = event.detail;
wheelDeltaNumber = 30;
} else if(USER_AGENT.indexOf('Safari') > -1) {
// wheelDelta = 360 or -360
wheelDelta = event.wheelDelta;
wheelDeltaNumber = 3600;
} else {
// wheelDelta = 120 or -120
wheelDelta = event.wheelDelta;
wheelDeltaNumber = 1200;
}
// 如果比例达到100或者为1的时候,停止继续放大或缩小 > 0 放大, < 0 缩小
if((num === 100 && wheelDelta > 0) || (num === 1 && wheelDelta < 0)) {
return;
}
// 计算放大或缩小比例
this.zoomOut = (this.zoomOut + wheelDelta / wheelDeltaNumber);
style.width = this.IMG_WIDTH * (1 + this.zoomOut) + 'px';
style.height = this.IMG_HEIGHT * (1 + this.zoomOut) + 'px';
style.top = imgStyle.top;
style.left = imgStyle.left;
style.position = 'relative';
// 换算成百分比,显示
if(this.zoomOut.toFixed(1) * 100 < 0) {
rate = 10 + (this.zoomOut.toFixed(1) * 100) / 10;
} else {
rate = parseInt(this.zoomOut.toFixed(1) * 100);
}
// 不允许出现百分之0
rate = rate === 0 ? rate = 10 : rate;
this.setState({
imgStyle: style,
num: rate,
isShowRate: true
});
}
// 打开pdf、xls、word等文件
openUrl = url => {
if(url) {
redirect(url, '_blank');
}
}
// 图片按下事件
handlerImgDown = (e) => {
e.preventDefault();
const previewImg = document.getElementsByClassName('preview-image');
this.isDown = true;
this.currentX = e.clientX;
this.currentY = e.clientY;
this.offsetLeft = parseInt(previewImg[0].offsetLeft);
this.offsetTop = parseInt(previewImg[0].offsetTop);
this.handlerImgMove();
// 移除事件
document.onmouseup = () => {
document.onmousemove = null;
document.onmouseup = null;
this.isDown = false;
};
}
// 图片移动
handlerImgMove = () => {
document.onmousemove = (e) => {
if(this.isDown) {
const { imgStyle } = this.state;
let style = {};
style.width = imgStyle.width + 'px';
style.height = imgStyle.height + 'px';
style.left = e.clientX - (this.currentX - this.offsetLeft) + 'px';
style.top = e.clientY - (this.currentY - this.offsetTop) + 'px';
style.position = 'relative';
this.setState({
imgStyle: style
});
}
};
}
// 获取图片真实宽高
onload = (e) => {
this.IMG_WIDTH = e.target.width;
this.IMG_HEIGHT = e.target.height;
}
render() {
const { imgStyle, isShowRate, num } = this.state;
const { url, hideModal } = this.props;
const { isShowPreView } = this.state;
return (
<div className="c-c-preview-image">
{
isShowPreView &&
<Modal
wrapClassName="c-c-preview-image-modal"
visible={true}
centered={true}
closable={false}
width="100%"
onCancel={hideModal}
footer={null}
>
<img
draggable="false"
alt="img"
className="preview-image select-cursor"
onMouseDown={this.handlerImgDown}
src={url}
onLoad={this.onload}
style={imgStyle}
/>
{
isShowRate &&
<div className="viewer-tooltip">{num}%</div>
}
</Modal>
}
<Icon onClick={hideModal} className="close" type="close" />
</div>
);
}
}
PreviewImage.propTypes = {
// src or pdf or xls or word
url: PropTypes.string,
};