小程序拍照压缩上传全攻略

前言

以小程序 【识花君】为例子,分析下在小程序中如何实现拍照压缩上传。

识花君

一、camera 和 cover-view、cover-image 组件

首先分析如何实现类似的设计:

  1. 引用 camera 组件,并且通过样式设置宽高为全屏。(拓展:可以在样式中设置宽高,或者定位来调整相机组件在页面中的大小以及位置。)
  2. 以 cover-view 为父容器设置定位,以嵌套的 cover-image 引用图片

说明:

  • 为什么不直接对 cover-image,而要使用 在外面嵌套一层 cover-view ?
    答:因为对 cover-image 设置定位样式后,在真机上无效。基础库 1.9.90 起最外层 cover-view 支持 position: fixed 。
  • cover-image 使用本地图片路径会存在问题
    答:图标路径,支持临时路径、网络地址(1.6.0起支持)、云文件ID(2.2.3起支持)。暂不支持base64格式。

二、从相册选取

点击相册图标时,触发事件调用 wx.chooseImage(Object object) 即可。

三、拍照

  • 图片 api :wx.chooseImage(Object object)
  • 相机 api :CameraContext.takePhoto(Object object)

四、压缩

现在的智能手机拍出的照片,很容易达到 5M 左右,上传时不仅占用带宽,且速度慢。

小程序提供了 3 种方式可压缩图片:

  1. 选择照片时指定图片的尺寸或者拍照时指定成像质量
    经过测试,如果对压缩要求比较高,这种方法是不行的,因为压缩效果不显著。
  2. wx.compressImage(Object object)
    局限性:仅对 jpg 有效。实际业务中包含 pngjpg 等多种格式。
  3. 通过 canvas 来曲线救国

原理:将一张大尺寸的图片通过 canvas 的提供的 drawImage() 方法绘制到小尺寸的画布上,再通过 canvasToTempFilePath 将画布内容生成图片,就完成了大尺寸到小尺寸的转换,完成了压缩。

步骤

  • wx.getSystemInfoSync() 获取设备像素比
  • wx.chooseImg() 或者 CameraContext.takePhoto 获取图片
  • wx.getImageInfo() 获取图片信息,并检测图片是否超过指定尺寸
  • drawImage() 绘制图片到画布
  • draw()
  • wx.canvasToTempFilePath() 将画布内容生成图片

说明:为什么需要设备像素比??

看下不处理设备像素比时,普通屏和二倍屏的对比,只关注 width 即可

pixelRatio = 1

pixelRatio = 2

在高倍屏上面,1px 对应的物理像素会比普通屏幕更多,这就导致通过 drawImage() 方法绘制时,虽然在 css
层面设置的宽高是一致的,比如(w: 300px),如果普通屏(pixelRatio: 1) 1px = 1 个物理像素,那么在二倍屏 (pixelRatio: 2) 上面 1 px = 4 个物理像素(宽是2, 高是2),所以实际上是将图片的宽绘制为 300 * 2 个物理像素,这时使用
canvasToTempFilePath() 生成图片的宽度是 600, 而不是期望的 300

设备像素比对 px 和物理像素的关系图

主要代码
模板 部分 (以下为 mpvue 中的语法)

<canvas class="canvas-hidden" :style="{width: cWidth + 'px', height: cHeight + 'px'}" canvas-id="CanvasId"/>

js 部分

pixelRatio 通过 wx.getSystemInfoSync() 获取。

// 将图片绘制到画布上
drawImage(file) {
   const ctx = wx.createCanvasContext('CanvasId');
   wx.getImageInfo({
      src: file,
      success: (res) => {
        if (res.width > 300 || res.height > 300) { // 判断图片是否超过300像素
          this.cWidth = 300 / this.pixelRatio;
          this.cHeight = 300 / this.pixelRatio / scale;
          // 画出压缩图片
          ctx.drawImage(file, 0, 0, this.cWidth, this.cHeight);
          ctx.draw();
          setTimeout(() => {
            this.canvasToImg();
          }, 3000);
        } else {
          this.upload(file);
        }
      }
    });
  },
// 将画布内容转成图片
canvasToImg() {
   wx.canvasToTempFilePath({
      canvasId: 'CanvasId',
      success: (res) => {
        // 上传图片
     this.upload(res.tempFilePath);
     }
   });
 },

五、兼容性

  1. 小米 android 9.0 版本无法渲染出 https 协议的图片。
    解决方案:前端强制转换成 http 。
  2. CanvasContext.draw(boolean reserve, function callback)
    callback 在某些机型上面无效。(当前基础库 2.6.5)
    解决方案:draw 之后强制 setTimeout 3s ,然后再去执行 wx.canvasToTempFilePath(Object object, Object this)

2019/5/13 更改
解决方案:通过wx.getSystemInfoSync()获取当前设备信息,其中的 platform 字段代表当前系统类型

  • ios
CanvasContext.draw(false, () => {
  wx.canvasToTempFilePath(Object object, Object this)
})
  • android
    draw 之后强制 setTimeout 3s ,然后再去执行 wx.canvasToTempFilePath(Object object, Object this)

3: 对 canvas 应用样式 visibility 无效
解决方案: 通过 left: -9999; 或者 tranlateX() 改变位置,移至不可见区域。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容