一切福田,不離方寸,從心而覓,感無不通。

HTML5 实现手机拍照上传

背景:移动端H5项目,需要实现调用手机拍照,并将图片压缩上传功能。

  1. 页面样式:
    1. 上传图片有原生的方法<input type="file" accept="image/*">,如果只想要拍照上传,不希望用户选择图片上传,可以通过添加capture属性,该属性值有camcorder/microphone/camera…,此处选择camera。PS:该属性存在浏览器兼容性问题,不是所有的浏览器都支持。

       
    2. 因为原生file样式不满足要求,需要进行相应的处理,此时使用定位,在input上面放置我们想要的页面效果。然后当点击上面的元素,就可以触发我们的input进行图片上传。此时的问题是:当点击input上面的元素,需要事件穿透,即相当于点击input。则借助于css3心术新pointer-events。

       

      —-此时图片上传的样式已经处理好了—-

      代码片段:

       

  2. 图片压缩处理:
    1. 因为要做的是手机拍照上传,现在的手机拍照片都很大,比如小米4S,大小在3M以上,如果原图上传,太消耗用户流量,于是要解决图片压缩的问题。
    2.   通过change事件,监听图片上传,通过readerAsDataURL获取上传的图片。

       

    3.   对上传的图片进行压缩,需要借助于canvas API,调用其中的canvas.toDataURL(typeencoderOptions); 将图片按照一定的压缩比进行压缩,得到base64编码。重点来了:压缩策略:先设置图片的最大宽度 or 最大高度,一般设置其中一个就可以了,因为所有的手机宽高比差别不是很大。然后设置图片的最大size,allowMaxSize,根据图片的实际大小和最大允许大小,设置相应的压缩比率。

       

  3. 图片上传给服务器:
    1. 图片已经压缩完成了,但是压缩后的图片不是File,而是一个base64编码,于是乎两个选择:1、以String的形式将base64编码上传给服务器,服务器转存base64为img图片;2、前端将base64转为File图片类型,上传给服务器。
    2. 方法一:压缩之后直接上传base64给后台,实现简单。
    3. 方法二:前端自己转存base64位File图片,这个对于前端 压力比较大。原因:html5 canvas属于客户端API,没有权限去保存图片到硬盘,只有canvas.toDataURL()这一接口可导出画布的base64编码,以提供给服务器进行处理保存。所以如果要将base64编码转成图片需要借助于nodeJs。因为nodeJS有相关文件处理的API。

       

      Summary:如果使用nodeJS,需要单独部署nodeJS代码到服务器,整个逻辑会比较麻烦。综合比较两种方法,推荐使用第一种方法,直接传base64给服务器,后台处理相应的转化!

相关知识科普:

  1. 图像一般由两部分组成:一部分是数据本身,他记录了每个像素的颜色值,另一部分是文件头,这里记录着形如图像的宽度,高度等信息。
  2. 不同图片类型及适用场景:
    1. 不同图片类型:
      1. GIF:无损压缩,体积小,支持透明效果,缺点:色彩效果最低,用gif保存鲜艳的图片的话会让网站看上去非常可怕。
      2. PNG:无损压缩,可渐变透明,缺点:不如JPG颜色丰富,同样的图片体积也比JPG略大。
      3. JPG/JPEG:色彩还原性好,可以在照片不明显失真的情况下,大幅度压缩图片格式,所以体积不会很大。缺点:不支持透明
    2. 适用场景:
      1. 当图片色彩鲜艳,基本没有透明效果的时候,选择jpg/jpeg。
      2. 当图片色彩鲜艳,透明效果较多的情况下,选择png;
      3. 当图片色彩比较单一情况下,可以选择gif;
  3. toDataURL,查找原生压缩图片的方法。type支持image/webp格式

     
  4. Base64编码:将三个8Bit的字节转换为四个6Bit的字节。

 

参考资料:

http://www.imys.net/20150916/webapp-input-use-camera.html

http://www.oxxostudio.tw/articles/201409/pointer-events.html

https://segmentfault.com/a/1190000005364299

 

from:http://my.oschina.net/zyxchuxin/blog/700381