/// 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;