gifv.tsx 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import { useCallback, useState } from 'react';
  2. interface Props {
  3. src: string;
  4. key: string;
  5. alt?: string;
  6. lang?: string;
  7. width: number;
  8. height: number;
  9. onClick?: () => void;
  10. }
  11. export const GIFV: React.FC<Props> = ({
  12. src,
  13. alt,
  14. lang,
  15. width,
  16. height,
  17. onClick,
  18. }) => {
  19. const [loading, setLoading] = useState(true);
  20. const handleLoadedData: React.ReactEventHandler<HTMLVideoElement> =
  21. useCallback(() => {
  22. setLoading(false);
  23. }, [setLoading]);
  24. const handleClick: React.MouseEventHandler = useCallback(
  25. (e) => {
  26. if (onClick) {
  27. e.stopPropagation();
  28. onClick();
  29. }
  30. },
  31. [onClick],
  32. );
  33. return (
  34. <div className='gifv' style={{ position: 'relative' }}>
  35. {loading && (
  36. <canvas
  37. width={width}
  38. height={height}
  39. role='button'
  40. tabIndex={0}
  41. aria-label={alt}
  42. title={alt}
  43. lang={lang}
  44. onClick={handleClick}
  45. />
  46. )}
  47. <video
  48. src={src}
  49. role='button'
  50. tabIndex={0}
  51. aria-label={alt}
  52. title={alt}
  53. lang={lang}
  54. muted
  55. loop
  56. autoPlay
  57. playsInline
  58. onClick={handleClick}
  59. onLoadedData={handleLoadedData}
  60. style={{ position: loading ? 'absolute' : 'static', top: 0, left: 0 }}
  61. />
  62. </div>
  63. );
  64. };