自定義相機

起因

由於最近用uniapp調用原生相機容易出現閃退問題,找瞭很多教程又是壓縮圖片又是優化代碼,我表示並沒有太大作用!!

於是開啟瞭我的解決之路

利用livePusher實現

實現自定義相機

拓展性挺強的,可以實現自定義水印、身份證拍攝、人像拍攝等 這裡我簡單實現一個相機功能主要用於解決閃退

Tip:這裡需要創建nvue文件哦~

創建camera.nvue

<template>
 <view class="pengke-camera" :style="{ width: windowWidth, height: windowHeight }">
  <live-pusher
   id="livePusher"
   ref="livePusher"
   class="livePusher"
   mode="FHD"
   beauty="0"
   whiteness="0"
   :aspect="aspect"
   min-bitrate="1000"
   audio-quality="16KHz"
   device-position="back"
   :auto-focus="true"
   :muted="true"
   :enable-camera="true"
   :enable-mic="false"
   :zoom="false"
   @statechange="statechange"
   :style="{ width: windowWidth, height: windowHeight }"
  ></live-pusher>

  <view class="menu">
   <!--底部菜單區域背景-->
   <cover-image class="menu-mask" src="/static/live-camera/bar.png"></cover-image>

   <!--返回鍵-->
   <cover-image class="menu-back" @tap="back" src="/static/live-camera/back.png"></cover-image>

   <!--快門鍵-->
   <cover-image class="menu-snapshot" @tap="snapshot" src="/static/live-camera/shutter.png"></cover-image>

   <!--反轉鍵-->
   <cover-image class="menu-flip" @tap="flip" src="/static/live-camera/flip.png"></cover-image>
  </view>
 </view>
</template>

<script>
let _this = null;
export default {
 data() {
  return {
   poenCarmeInterval:null,//打開相機的輪詢
   aspect: '2:3', //比例
   windowWidth: '', //屏幕可用寬度
   windowHeight: '', //屏幕可用高度
   camerastate: false, //相機準備好瞭
   livePusher: null, //流視頻對象
   snapshotsrc: null, //快照
  };
 },
 onLoad(e) {
  _this = this;
  this.initCamera();
 },
 onReady() {
  this.livePusher = uni.createLivePusherContext('livePusher', this);
  this.startPreview(); //開啟預覽並設置攝像頭
  this.poenCarme();
 },
 methods: {
  
  //輪詢打開
  poenCarme(){
   //#ifdef APP-PLUS
   if (plus.os.name == 'Android') {
    this.poenCarmeInterval = setInterval(function() {
     console.log(_this.camerastate);
     if (!_this.camerastate) _this.startPreview();
    }, 2500);
   }
   //#endif
  },
  //初始化相機
  initCamera() {
   uni.getSystemInfo({
    success: function(res) {
     _this.windowWidth = res.windowWidth;
     _this.windowHeight = res.windowHeight;
     let zcs = _this.aliquot(_this.windowWidth,_this.windowHeight);
     _this.aspect = (_this.windowWidth/zcs)+':'+(_this.windowHeight/zcs);
     // console.log('畫面比例:'+_this.aspect);
    }
   });
  },
  
  //整除數計算
  aliquot(x, y) {
   if (x % y == 0) return y;
   return this.aliquot(y, x % y);
  },

  //開始預覽
  startPreview() {
   this.livePusher.startPreview({
    success: a => {
     console.log(a)
    }
   });
  },
  
  //停止預覽
  stopPreview() {
   this.livePusher.stopPreview({
    success: a => {
     _this.camerastate = false;
    }
   });
  },
  
  //狀態
  statechange(e) {
   //狀態改變
   console.log(e);
   if (e.detail.code == 1007) {
    _this.camerastate = true;
   } else if (e.detail.code == -1301) {
    _this.camerastate = false;
   }
  },
  

  //返回
  back() {
   uni.navigateBack();
  },

  //抓拍
  snapshot() {
   //震動
   uni.vibrateShort({
       success: function () {
           console.log('success');
       }
   });
   //拍照
   this.livePusher.snapshot({
    success: e => {
     _this.snapshotsrc = e.message.tempImagePath;
     _this.stopPreview();
     _this.setImage();
     uni.navigateBack();
    }
   });
  },

  //反轉
  flip() {
   this.livePusher.switchCamera();
  },

  //設置
  setImage() {
   let pages = getCurrentPages();
   let prevPage = pages[pages.length - 2];
   prevPage.$vm.setImage({ path: _this.snapshotsrc});
  }
 }
};
</script>

<style lang="less">
.pengke-camera {
 justify-content: center;
 align-items: center;
 .menu {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 750rpx;
  height: 180rpx;
  z-index: 98;
  align-items: center;
  justify-content: center;
  .menu-mask {
   position: absolute;
   left: 0;
   bottom: 0;
   width: 750rpx;
   height: 180rpx;
   z-index: 98;
  }
  .menu-back {
   position: absolute;
   left: 30rpx;
   bottom: 50rpx;
   width: 80rpx;
   height: 80rpx;
   z-index: 99;
   align-items: center;
   justify-content: center;
  }
  .menu-snapshot {
   width: 130rpx;
   height: 130rpx;
   z-index: 99;
  }
  .menu-flip {
   position: absolute;
   right: 30rpx;
   bottom: 50rpx;
   width: 80rpx;
   height: 80rpx;
   z-index: 99;
   align-items: center;
   justify-content: center;
  }
 }
}
</style>

這裡用瞭一些圖片作為圖標佈局畫面美觀,例如返回圖標,拍攝圖標

使用

在點擊拍照的時候跳轉到camera頁面即可 在需要使用的頁面中編寫setImage方法,即可拿到返回過來的圖片臨時路徑 再通過uniapp自帶的上傳圖片api進行上傳至服務器即可 這樣就避免瞭調用原生相機

setImage(e){
//e.path即是圖片臨時路徑
uni.uploadFile({
 url: '上傳接口的路徑',
 filePath: e.path,
 name: 'imageFile',
 success: function(res) {
  //服務器返回的圖片地址url
 },
 error: function(err) {
  console.log(err)
 }
}

效果圖

自定義相機效果圖

拓展

如果既要實現從相冊選又要手機拍呢?該如何實現 這裡相冊選調用的uniapp的api, 手機拍跳轉到自定義相機頁面即可

這裡可以寫一個彈窗,讓它選擇,如果選擇瞭從相冊選圖片則

uni.chooseImage({
 count: size, //默認9
 sizeType: ['original', 'compressed'], //可以指定是原圖還是壓縮圖,默認二者都有
 sourceType: ['album'], //從相冊選擇
 success: function (res) {
  console.log(res)//拿到臨時路徑再向後端發送上傳請求....
 }
});

如果用相機拍則跟上方步驟一致

實現多種自定義相機

這裡的話我貼上效果圖,如果需要就在我的博客資源中獲取吧

水印相機

水印相機

身份證相機

身份證識別相機

人像相機

人像相機

這樣我就成功解決瞭閃退問題~,有問題評論區d我