c语言编程笔录

首页 >   > 笔记大全

笔记大全

关于H5调用相机拍照并压缩图片的代码

更新时间:2023-09-15

需求背景

在一些移动端的应用场景中,需要用户使用手机的相机拍照并上传图片。因为移动端的屏幕相对较小,用户拍摄的照片可能过大,不仅占用用户的手机存储空间,同时上传和下载也需要更多的时间。因此,需要在拍摄照片时对照片进行压缩,保留图片的主体内容,同时减少照片的大小。

  
    
    

其中,input 标签中的 accept="image/*" 表示只接受用户上传图片类型的文件;capture="camera" 则表示调用相机

调用相机拍照

移动端浏览器需要使用HTML5提供的getUserMedia API来调用摄像头,在调用前需要检查用户设备是否支持这个API。如果设备支持getUserMedia API,拍照逻辑如下所示:

  
    const takePhoto = document.querySelector('#take-photo');
    const previewImg = document.querySelector('.preview-img');
    
    takePhoto.addEventListener('change', function() {
      const file = takePhoto.files[0];
      const reader = new FileReader();
      
      reader.readAsDataURL(file);
      
      reader.onload = function(e) {
        previewImg.src = e.target.result;
      };
    });
  

上述代码中,takePhoto 是调用相机拍摄照片的 input 元素,previewImg 是显示已拍摄照片的 img 元素。当用户拍摄照片后,读取照片文件到 FileReader 中,使用 readAsDataURL方法将照片文件转换为 base64 编码的数据,并将这个数据作为 img 元素的 src 属性值展示给用户

压缩图片

在调用相机拍摄照片后,照片文件的尺寸可能过大,需要对照片进行压缩并将压缩后的数据上传至服务器。在压缩图片时,我们需要先进行尺寸缩放,然后再压缩图片的质量,最后将压缩后的数据上传至服务器。以下是一段压缩图片并上传的代码:

  
    const takePhoto = document.querySelector('#take-photo');
    const previewImg = document.querySelector('.preview-img');
    const uploadBtn = document.querySelector('.upload-btn');
    
    takePhoto.addEventListener('change', function() {
      const file = takePhoto.files[0];
      const reader = new FileReader();
      
      reader.onload = function(e) {
        const img = new Image();
        img.src = e.target.result;
        
        img.onload = function() {
          const canvas = document.createElement('canvas');
          const ctx = canvas.getContext('2d');
          const scale = img.width / img.height;
          const MAX_WIDTH = 600;
          const MAX_HEIGHT = MAX_WIDTH / scale;
          
          let width = img.width;
          let height = img.height;
          
          if (width > MAX_WIDTH) {
            width = MAX_WIDTH;
            height = width / scale;
          }
          if (height > MAX_HEIGHT) {
            height = MAX_HEIGHT;
            width = height * scale;
          }
          
          canvas.width = width;
          canvas.height = height;
          ctx.drawImage(img, 0, 0, width, height);
          
          const compressQuality = 0.7;
          const compressedDataUrl = canvas.toDataURL('image/jpeg', compressQuality);
          previewImg.src = compressedDataUrl;
          
          uploadBtn.onclick = function() {
            const xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function() {
              if (xhr.readyState === 4 && xhr.status === 200) {
                alert('上传成功');
              }
            };
            
            xhr.open('POST', '/upload');
            xhr.send(compressedDataUrl);
          };
        }
      };
      
      reader.readAsDataURL(file);
    });
  

上述代码中,通过在 input 元素添加 .capture="camera",读取用户拍照的照片信息,将读取到的照片数据转为图片格式,展示在 img 元素上。然后根据指定的最大宽度,将图片等比例缩放,最后将压缩后的数据上传至服务器。

上传压缩后的照片到服务器

压缩后的照片数据已经在前面部分中实现。在调用压缩方法后,将数据上传至服务器上,使用XMLHttpRequest 的 POST 方法即可上传压缩后的文件。以下是代码实例:

  
    const uploadBtn = document.querySelector('.upload-btn');
    
    uploadBtn.onclick = function() {
      const xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
          alert('上传成功');
        }
      };
      
      xhr.open('POST', '/upload');
      xhr.send(compressedDataUrl);
    };
  

上述代码中,通过使用 AJAX,异步上传压缩后的照片数据至服务器 /upload的请求中,请求方式使用 POST,当资源上传成功后提醒用户,上传完成。