Photo.tsx 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import React from 'react';
  2. import classNames from 'classnames';
  3. import Spinner from './components/Spinner';
  4. import getSuitableImageSize from './utils/getSuitableImageSize';
  5. import useMountedState from './utils/useMountedState';
  6. import './Photo.less';
  7. import { brokenElementDataType } from './types';
  8. export interface IPhotoProps extends React.HTMLAttributes<any> {
  9. src: string;
  10. intro?: React.ReactNode;
  11. loaded: boolean;
  12. broken: boolean;
  13. width: number;
  14. height: number;
  15. rotate: number;
  16. className?: string;
  17. onImageLoad: (PhotoParams, callback?: Function) => void;
  18. loadingElement?: JSX.Element;
  19. brokenElement?: JSX.Element | ((photoProps: brokenElementDataType)=>JSX.Element);
  20. }
  21. const Photo: React.FC<IPhotoProps> = (props) => {
  22. const {
  23. src,
  24. intro,
  25. loaded,
  26. broken,
  27. width,
  28. height,
  29. rotate,
  30. className,
  31. onImageLoad,
  32. loadingElement,
  33. brokenElement,
  34. ...restProps
  35. } = props;
  36. const isMounted = useMountedState();
  37. function handleImageLoaded(e) {
  38. const { naturalWidth, naturalHeight } = e.target;
  39. if (isMounted()) {
  40. onImageLoad({
  41. loaded: true,
  42. naturalWidth,
  43. naturalHeight,
  44. ...getSuitableImageSize(naturalWidth, naturalHeight, rotate),
  45. });
  46. }
  47. }
  48. function handleImageBroken() {
  49. if (isMounted()) {
  50. onImageLoad({
  51. broken: true,
  52. });
  53. }
  54. }
  55. React.useEffect(() => {
  56. const currPhoto = new Image();
  57. currPhoto.onload = handleImageLoaded;
  58. currPhoto.onerror = handleImageBroken;
  59. currPhoto.src = src;
  60. }, []);
  61. if (src && !broken) {
  62. if (loaded) {
  63. return (
  64. <img
  65. className={classNames('PhotoView__Photo', className)}
  66. src={src}
  67. width={width}
  68. height={height}
  69. alt=""
  70. {...restProps}
  71. />
  72. );
  73. }
  74. return loadingElement || <Spinner />;
  75. }
  76. if(brokenElement){
  77. if(typeof brokenElement === 'function'){
  78. return brokenElement({
  79. src,
  80. intro,
  81. })
  82. }
  83. return brokenElement;
  84. }
  85. return null;
  86. };
  87. Photo.displayName = 'Photo';
  88. export default Photo;