js移动端调用摄像头拍照并实现上传

js移动端调用摄像头拍照并实现上传

前言

这次的需求功能中有一个用到手机拍照的功能,用户通过手机拍照从而识别图片中的信息,这个功能必然需要将图片上传到服务器,服务端实现图片的识别。(以下代码结合Vue

需求分析

  • 图片拍摄

js代码调用手机摄像头可以通过input标签的file类型来实现,代码实现如下:

1
<input type="file" multiple="multiple" accept="image/*" capture="camera" @change="getImage" ref="file">

通过这个方式可以成功调用手机的摄像头和相册选取功能(红米5只支持相册选取,小米的奇葩手机,磨人);

  • 图片上传

图片上传这里就有问题了,直接上传图片是不现实的,现在的手机像素都很高,拍照的图片质量必然很大,直接上传服务器并不显示,在这里就需要将图片进行压缩。

图片压缩可以通过两种方式:

  • 一种是服务端进行操作,比如七牛云或者阿里云的图片处理,但是现在的场景下并不可能;
  • 另一种是客户端处理,通过canvas来降低图片质量,进行图片压缩。

很显然是选择下面一种,直接上代码不bb

HTML部分

1
<canvas id="dealPic" style="display:none;"></canvas>

JS部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let _this = this;
let img = new Image();
var reader = new FileReader();
reader.onload = function(){
_this.base64Img = this.result; //在这里获取base64码
img.src = _this.base64Img;
img.onload=function(){
let canvas = document.getElementById('dealPic');
let context = canvas.getContext('2d');
context.scale(0.4,0.4);
canvas.width = img.width*0.4;
canvas.height = img.height*0.4;
context.drawImage(img, 0, 0, img.width*0.4, img.height*0.4); //缩小画布,毕竟手机拍下来的图片都是几千像素乘几千像素的大小
_this.base64Img = canvas.toDataURL(_this.$refs.file.files[0].type,0.5); //canvas生成后通过toDataURL获取canvas 处理后的其base64码,并自定义其画质,此处是0.5
let PicBlob = _this.getBlobBydataURI(_this.base64Img,_this.$refs.file.files[0].type); //转成文件流方便上传服务器
}
}
reader.readAsDataURL(_this.$refs.file.files[0]);

到此,通过实验已经将原7M大小的照片转成了200多K,画质上来讲差的也不是太多,这样上传图片服务器压力就小了很多很多,用户体验也就更好。

在压缩一步

其实200多K还是很大,虽然相比于原来的7M来说是小了很多,但是相信很多人和我一样希望能够在保证图片质量的情况下再缩小图片大小,这个是可行的,上面介绍了两种方法来压缩图片,我们完全可以在客户端压缩图片后再上传服务器来进行图片的处理。因为公司用的是七牛云,所以这里介绍下七牛云的服务端图片处理。

其实很简单就分两步:上传七牛云服务器图片地址加参

上传七牛云就不说了,这里介绍下图片地址加参

七牛云的图片处理服务为七牛云上的图片文件提供以下功能:

  • 对图片进行缩略操作
  • 图片缩放、裁剪、旋转
  • 获取图片格式、大小、色彩模型信息
  • 提供数码相机照片的可交换图像文件格式
  • 图片添加图片、文字、图文混合水印
  • 计算图片的平均色调

接口如下:

接口 简介
imageslim 图片瘦身(imageslim)将存储在七牛的JPEG、PNG格式的图片实时压缩而尽可能不影响画质。
imageView2 图片基本处理接口可对图片进行缩略操作,生成各种缩略图。imageView2 接口可支持处理的原图片格式有 psd、jpeg、png、gif、webp、tiff、bmp。

七牛提供了很多图片处理的接口,这里我用的是imageView2这个接口来进行图片操作;

接口规格

注意:接口规格不含任何空格与换行符。

1
2
3
4
5
6
imageView2/<mode>/w/<LongEdge>
/h/<ShortEdge>
/format/<Format>
/interlace/<Interlace>
/q/<Quality>
/ignore-error/<ignoreError>

上面一次往下是长,宽,输出格式,渐进显示,图片质量以及失败返回等参数。

其中 <mode> 分为如下几种情况:

接口 简介
/0/w/<LongEdge>/h/<ShortEdge> 限定缩略图的长边最多为,短边最多为,进行等比缩放,不裁剪。如果只指定 w 参数则表示限定长边(短边自适应),只指定 h 参数则表示限定短边(长边自适应)
/1/w/<Width>/h/<Height> 限定缩略图的宽最少为,高最少为,进行等比缩放,居中裁剪。转后的缩略图通常恰好是 x 的大小(有一个边缩放的时候会因为超出矩形框而被裁剪掉多余部分)。如果只指定 w 参数或只指定 h 参数,代表限定为长宽相等的正方图。
/2/w/<Width>/h/<Height> 限定缩略图的宽最多为,高最多为,进行等比缩放,不裁剪。如果只指定 w 参数则表示限定宽(长自适应),只指定 h 参数则表示限定长(宽自适应)。它和模式0类似,区别只是限定宽和高,不是限定长边和短边。从应用场景来说,模式0适合移动设备上做缩略图,模式2适合PC上做缩略图。
/3/w/<Width>/h/<Height> 限定缩略图的宽最少为,高最少为,进行等比缩放,不裁剪。如果只指定 w 参数或只指定 h 参数,代表长宽限定为同样的值。你可以理解为模式1是模式3的结果再做居中裁剪得到的。
/4/w/<LongEdge>/h/<ShortEdge> 限定缩略图的长边最少为,短边最少为,进行等比缩放,不裁剪。如果只指定 w 参数或只指定 h 参数,表示长边短边限定为同样的值。这个模式很适合在手持设备做图片的全屏查看(把这里的长边短边分别设为手机屏幕的分辨率即可),生成的图片尺寸刚好充满整个屏幕(某一个边可能会超出屏幕)。
/5/w/<LongEdge>/h/<ShortEdge> 限定缩略图的长边最少为,短边最少为,进行等比缩放,居中裁剪。如果只指定 w 参数或只指定 h 参数,表示长边短边限定为同样的值。同上模式4,但超出限定的矩形部分会被裁剪。

由于要考虑到图像识别的问题,图片不能被处理地太过变样,因此采取第一个接口/0/w/<LongEdge>/h/<ShortEdge>,图片长宽方面只是进行等比缩放。

上面说了除了长宽,还可以对质量进行处理,/q/0.5这个表示50%的质量,取值在0~1之间。

综上是这次移动端调用手机摄像头的经验之谈,踩坑之旅。

edit By AmamiRyoin

觉得不错的话可以打赏哦