uniapp實現水印相機-livePusher
水印相機
背景
前兩天拿到了一個需求,要求在內部的oaApp中增加一個衛生檢查模塊,這個模塊中的核心訴求就是要求拍照的照片添加水印。對于這個需求,我首先想到的是直接去插件市場,下一個水印相機插件導入使用。可惜,這個oaApp的架子搭建實在是毛坯,很多時候一些簡單方法,并不能直接使用。沒辦法,只能去找一些不那么常規的方法。在網上,找到一些方法使用livePusher和canvas來實現水印相機的效果。
核心livePusher與canvas
livePusher
官方介紹
實時音視頻錄制,也稱直播推流。
這里使用livePusher來實現,調起系統相機,實現攝像頭實時畫面預覽。
頁面布局(頁面需要是 .nvue的文件)
<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>
在onReady
時創建 live-pusher 上下文 livePusherContext 對象,并初始化相機開啟預覽。
this.livePusher = uni.createLivePusherContext('livePusher', this);
this.startPreview(); //開啟預覽并設置攝像頭//開始預覽
startPreview() {this.livePusher.startPreview({success: a => {console.log(a)}});
},
一些踩坑的想法
這里沒使用livePusher之前,我的想法是采用webView加plus-camera的方法去構建一個能夠自定義的拍攝頁面。為什么會有這個錯誤的想法,是因為我曾用過webView加plus-barcode構建了自定義的掃碼頁面。實踐發現這個想法是錯誤的,因為無論是uniapp還是plus-camera使用到相機時都是調起系統的相機功能,且在app端使用內嵌相機頁面的api也不支持。
拍照的操作方法
<view class="menu"><!-- 底部菜單區域背景 --><cover-image class="menu-mask" src="/static/image/13@3x.png"></cover-image><!--返回鍵--><cover-image class="menu-back" @click="back" src="/static/image/icon-back@3x.png"></cover-image><!--快門鍵--><cover-image class="menu-snapshot" @tap="snapshot" src="/static/image/condition-data-bj-circles@3x.png"></cover-image><!--反轉鍵--><cover-image class="menu-flip" @tap="flip" src="/static/image/Ranking-cylindricality-top10@3x.png"></cover-image></view>
//抓拍snapshot() {//震動uni.vibrateShort({success: function() {console.log('success');}});this.livePusher.snapshot({success: e => {_this.snapshotsrc = e.message.tempImagePathlet data = {url:_this.snapshotsrc,deptName: _this.deptName,time: _this.time}uni.$emit('waterMark', data);// 發送數據后返回上一頁uni.navigateBack();}});},//反轉flip() {this.livePusher.switchCamera();},
水印添加
用一個相對定位,將你的水印添加到你需要的位置,就可以試下水印和畫面的實時預覽啦。
canvas
前面拍照得到的照片,實際上水印并沒有添加到畫面中,這個時候我們需要使用canvas重新繪制,將圖片和水印繪制在一起。
<canvas v-if="canvasShow" :style="canvasStyle" canvas-id="watermarkCanvas"></canvas>
// 添加水印的函數addWatermark(imagePath, markDept, markTime) {return new Promise((resolve, reject) => {uni.getImageInfo({src: imagePath,success: (info) => {console.log("info.width, info.height", info.width, info.height);const ctx = uni.createCanvasContext('watermarkCanvas');ctx.drawImage(info.path, 0, 0, info.width, info.height);ctx.width = info.width;ctx.height = info.height;// 設置水印樣式ctx.setFontSize(50); // 設置字體大小ctx.setFillStyle('white'); // 設置水印顏色ctx.setGlobalAlpha(0.5); // 設置水印透明度// 添加水印文字// ctx.fillText(markDept, info.width - 15, info.height - 55);// ctx.fillText(markTime, info.width - 15, info.height - 15);ctx.fillText('部門', 30, 250); // 設置水印位置ctx.fillText(markDept, 30, 300); // 設置水印位置ctx.fillText('時間', 30, 350); // 設置水印位置ctx.fillText(markTime, 30, 400); // 設置水印位置ctx.draw(true, () => {uni.canvasToTempFilePath({canvasId: 'watermarkCanvas',success: (res) => {console.log("res.tempFilePath", res.tempFilePath);resolve(res.tempFilePath);},fail: (err) => {reject(err);}});});},fail: (err) => {reject(err);}});});},
最終效果
預覽畫面
繪制好的水印照片
最后
水印照片的比例以及水印的位置需要自己多調試幾次找到合適的比例和位置。