我正在try 在画布上上传图片/视频.当用户上传图像时,它将显示在画布上;如果用户上传视频,它将显示在画布上.我可以在画布上显示图像,但无法加载视频.请判断下面的代码并帮助我解决此问题.

    import React, { useState, useRef, useEffect } from 'react';
    
    const FileUpload = () => {
      const [uploadedFile, setUploadedFile] = useState(null);
      const fileInputRef = useRef(null);
      const canvasRef = useRef(null);
    
      const handleFileChange = (e) => {
        const file = e.target.files[0];
        setUploadedFile(file);
      };    
    
    useEffect(() => {
      if (uploadedFile) {
        const canvas = canvasRef.current;
        const context = canvas.getContext('2d');
    
        const mediaElement = document.createElement(
          uploadedFile.type.startsWith('image/') ? 'img' : 'video'
        );
    
        mediaElement.src = URL.createObjectURL(uploadedFile);
    
        mediaElement.onload = () => {
          context.clearRect(0, 0, canvas.width, canvas.height);
    
          // For videos, play the video and update the canvas during playback
          if (uploadedFile.type.startsWith('video/')) {
            mediaElement.addEventListener('timeupdate', () => {
              context.drawImage(
                mediaElement,
                0,
                0,
                canvas.width,
                canvas.height
              );
            });
    
            mediaElement.play().catch((error) => {
              console.error('Error playing video:', error);
            });
          } else {
            // For images
            context.drawImage(
              mediaElement,
              0,
              0,
              canvas.width,
              canvas.height
            );
          }
        };
      }
    }, [uploadedFile]);
    
      return (
        <div className="App">
          <input type="file" ref={fileInputRef} onChange={handleFileChange} accept="image/*,video/*" />
          
          <canvas ref={canvasRef} width={460} height={300} style={{ marginTop: '20px' }} />
        </div>
      );
    };
    
    export default FileUpload;

推荐答案

这里有一个有效的香草解决方案.它与您的解决方案基本相同(使用一组helper函数),但有几点不同:

  1. 它将创建的媒体元素附加到DOM
  2. 它对<video>个元素使用"CanPlay"事件,而不是"Load"
  3. 它通过在删除前一个媒体元素时调用revokeObjectURL来避免内存泄漏

const element = {
  app: document.querySelector('#app'),
  file: document.querySelector('#fileSelect'),
  canvas: document.querySelector('#surface'),
  media: null
};



const isImageFile = (file) => file.type.startsWith('image');

const createMediaElement = (file) => {
  return isImageFile(file)
    ? document.createElement('img')
    : document.createElement('video');
};

const render = (elem, context) => {
  const width = context.canvas.width;
  const height = context.canvas.height;
  
  context.clearRect(0, 0, width, height);
  context.drawImage(elem, 0, 0, width, height);
};



const handleFileChange = (event) => {
  const file = event.target.files[0];
  setUploadedFile(file);
};



const runRenderInto = (context) => () => {
  render(element.media, context);
};

const runPlay = (elem) => () => {
  elem.play();
}; 


const setUploadedFile = (file) => {
  if (file) {
    const ctx = element.canvas.getContext('2d');
    const media = createMediaElement(file);
    
    // Removes previously generated media elements
    if (element.media) {
      URL.revokeObjectURL(element.media.src); // <-- Avoid memory leaks!
      element.media.remove();
    }
    
    // Store a reference to the new media element, add some styles to make it dissapear
    element.media = media;
    element.media.style.position = 'fixed';
    element.media.style.bottom = '100%';
    element.media.style.left = '100%';
    
    // Add appropriate event listeners
    if (isImageFile(file)) {
      element.media.addEventListener('load', runRenderInto(ctx));
    } else {
      element.media.addEventListener('timeupdate', runRenderInto(ctx));
      element.media.addEventListener('canplay', runPlay(element.media));
    }
    
    // Add new media element to the DOM.
    // Attach new URL as a last step to ensure the event listeners
    // are properly registered
    element.app.appendChild(element.media);
    element.media.src = URL.createObjectURL(file);
  }
};



element.file.addEventListener('change', handleFileChange);
<div id="app" className="App">
  <input type="file" id="fileSelect" accept="image/*,video/*" />
  <canvas id="surface" width="460" height="300" style="margin-top:20px" />
</div>

Javascript相关问答推荐

如何在JavaScript中在文本内容中添加新行

在贝塞尔曲线的直线上找不到交叉点:(使用@Pomax的bezier.js)

如何分配类型脚本中具有不同/额外参数的函数类型

docx.js:如何在客户端使用文档修补程序

如何在Javascript中的控制台上以一行形式打印循环的结果

如何粗体匹配的字母时输入搜索框使用javascript?

有条件重定向到移动子域

将数组扩展到对象中

向数组中的对象添加键而不改变原始变量

<;img>;标记无法呈现图像

有效路径同时显示有效路径组件和不存在的路径组件

使用Document.Evaluate() Select 一个包含撇号的HTML元素

将相关数据组合到两个不同的数组中

react -原生向量-图标笔划宽度

如何在TransformControls模式下只保留箭头进行翻译?

有没有办法在R中创建一张具有多个色标的热图?

Plotly.js栏为x轴栏添加辅助文本

如何在Firebase中读取对象的特定字段?

在HTML中使用meta标记来指定定制元数据以用于使用JavaScript进行检索是不是一个坏主意?

使用onClick单击子元素时,使用交点观察器的关键帧动画意外运行