///
import * as React from 'react';
import Hammer from 'react-hammerjs';
import classNames from 'classnames';
import { getUrlParams } from '../util/router';
import Exception from '../exception';
const prefix = 'tsp-component-ImgView';
class ImgView extends React.Component {
constructor(props: TspComponentImgViewProps, state: any) {
super(props, state);
this.onLoad = this.onLoad.bind(this);
this.onError = this.onError.bind(this);
this.onTap = this.onTap.bind(this);
}
public static defaultProps: TspComponentImgViewProps = {
src: '',
loading: '',
fail: '',
timeout: ''
};
/**
* 加载图片的元素
*/
private elem: HTMLElement;
/**
* img对象
*/
private img: HTMLImageElement;
/**
* 图片加载状态
*/
private status: TspComponentImgViewStatus = 'loading';
/**
* setTimeout 实例,用于清除定时器
*/
private timeoutInstance: number;
/**
* 是否销毁组件
*/
private isDestory: boolean;
public componentWillUnmount(): void {
if (this.img) {
this.img.src = '';
this.img = null;
this.isDestory = true;
}
clearTimeout(this.timeoutInstance);
}
public componentDidMount(): void {
const src = this.props.src ? this.props.src : this.props.default;
this.elem = this.refs.elem as HTMLElement;
this.imgInitial(src);
}
public componentWillReceiveProps(nextProps: TspComponentImgViewProps): void {
if (this.props.src !== nextProps.src && !this.props.default) {
this.setImgSrc(nextProps.src);
} else if (!this.props.src && this.props.default) {
this.setImgSrc(nextProps.default);
}
}
/**
* 图片加载成功
*/
public onLoad(): void {
this.setStatus('complete');
}
/**
* 图片加载失败
*/
public onError(): void {
if (!this.isDestory) {
this.setStatus('fail');
}
}
/**
* 图片点击事件
*/
public onTap(): void {
if (this.status === 'timeout') {
const time = new Date().getTime();
let src = this.props.src;
if (getUrlParams(this.props.src).search) {
src += `&componentLoadTimestamp=${time}`;
} else {
src += `?componentLoadTimestamp=${time}`;
}
this.imgInitial(src);
this.status = 'loading';
} else if (this.props.onClick) {
this.props.onClick();
}
}
/**
* img对象初始化
*/
public imgInitial(src: string): void {
this.img = new Image();
this.img.onload = this.onLoad;
this.img.onerror = this.onError;
this.setImgSrc(src);
}
public setStatus(status: TspComponentImgViewStatus): void {
const exceptionParams = {
errorType: undefined,
url: this.props.src,
content: `id: ${this.props.id ? this.props.id : ''};`,
details: JSON.stringify(this.props.describe)
};
this.status = status;
switch (status) {
case 'loading':
this.elem.style.backgroundImage = `url(${this.props.loading})`;
this.elem.classList.remove(`${prefix}-timeout`);
this.elem.classList.add(`${prefix}-loading`);
break;
case 'complete':
this.elem.style.backgroundImage = `url(${this.props.src ? this.props.src : this.props.default})`;
this.elem.classList.remove(`${prefix}-loading`);
this.elem.classList.add(`${prefix}-complete`);
this.elem.dataset.trackurl = this.props.src;
break;
case 'timeout':
this.elem.style.backgroundImage = `url(${this.props.timeout})`;
this.elem.classList.remove(`${prefix}-loading`);
this.elem.classList.add(`${prefix}-timeout`);
exceptionParams.errorType = 5;
Exception.send(exceptionParams);
break;
case 'fail':
this.elem.style.backgroundImage = `url(${this.props.fail})`;
this.elem.classList.remove(`${prefix}-loading`);
this.elem.classList.add(`${prefix}-fail`);
exceptionParams.errorType = 4;
Exception.send(exceptionParams);
break;
default: break;
}
if (this.props.onStatusChange) {
this.props.onStatusChange(status);
}
}
/**
* 设置图片地址
*/
public setImgSrc(src: string): void {
if (src) {
clearTimeout(this.timeoutInstance);
this.img.src = src;
this.timeoutInstance = setTimeout(() => {
if (this.status === 'loading') {
this.setStatus('loading');
if (this.props.timeout) {
this.timeoutInstance = setTimeout(() => {
if (this.status === 'loading') {
this.img.onerror = null;
this.img.src = '';
this.img = null;
this.setStatus('timeout');
}
}, 15000);
}
}
}, 100);
} else {
this.setStatus('loading');
}
}
public render(): JSX.Element {
const classname = classNames({
[prefix]: true,
[this.props.className]: this.props.className
});
return (
);
}
}
export default ImgView;