赞
踩
基本上同时兼容安卓和苹果的插件都需要付费,这里我找了2个好用的免费插件
1.仅支持安卓:自定义身份证相机(支持蒙版自定义),内置蒙版,照片预览,身份证裁剪 - DCloud 插件市场、
2.支持iOS(已测),支持Android(未测,应该也可以用):
第一个插件使用方法(仅支持安卓):
创建一个realName.vue文件
- <view class="personalInfo" style="margin-top: 20rpx;">
- <view class="label" style="margin-bottom: 8rpx;">
- <view class="blue"></view>
- <view class="title">证件图片</view>
- </view>
- <view class="tips">请拍摄或上传身份证原件照片,确保照片完整清晰</view>
- <view class="imgBox">
- <view class="front">
- <image :src="frontImg" :class="platform == 'ios' ? 'transformImg' : ''" @click="uploadImgNew('front')"/>
- <view class="frontBtn" @click="uploadImgNew('front')" v-if="frontImg == ''">
- 上传人像面
- </view>
- </view>
- <view class="back">
- <image :src="backImg" :class="platform == 'ios' ? 'transformImg' : ''" @click="uploadImgNew('back')"/>
- <view class="backBtn" @click="uploadImgNew('back')" v-if="backImg == ''">
- 上传国徽面
- </view>
- </view>
- </view>
- </view>
- export default {
- data () {
- return {
- frontImg: '',
- backImg: '',
- canvasSiz:{
- width:188,
- height:273
- },
- flag: true
- }
- },
- methods:{
- uploadImgNew(types){
- console.log('打开相机');
- let platform = uni.getSystemInfoSync().platform
- if(!this.flag){
- uni.showToast({
- title: '图片正在上传中,请误做其他操作',
- icon: 'none'
- })
- return
- }
- if(platform == 'ios'){
- // ios的另外用了别的插件,下面会讲到
- uni.navigateTo({
- url: `./idcard?dotype=${types == 'front' ? 'face' : 'badge'}`
- })
- }else{
- var cameraModule = uni.requireNativePlugin('yun-camerax-module');
- //无需蒙版可将type设置为非参数值,例如 type:99
- cameraModule.takePhoto({
- type: types == 'front' ? 0 : 1,
- imageIndex: 2, fullSrc: true,
- text: types == 'front' ? '将身份证正面置于此区域内并对齐边缘' : '将身份证背面置于此区域内并对齐边缘'
- }, res => {
- console.log(res);
- uni.showModal({
- title: '提示',
- // content: JSON.stringify(res),
- content: '请再次确认使用该图',
- success: (res1) => {
- if (res1.confirm) {
- console.log('用户点击确定',res);
- this.upLoadImg(res.file,types)
- } else if (res1.cancel) {
- console.log('用户点击取消');
- }
- }
- });
- });
- }
- },
- async upLoadImg(path,type) {
- setTimeout(()=>{
- uni.showToast({
- title: '上传中',
- icon: 'none'
- })
- this.flag = false
- uni.uploadFile({
- url: 'xxxxxx/upload', //后端上传接口
- filePath: path,
- name: "file",
- success: (res) => {
- console.log('res222',res);
- if(JSON.parse(res.data).code == 0){
- console.log('JSON.parse(res.data)',JSON.parse(res.data));
- if(type == 'front'){
- this.frontImg = JSON.parse(res.data).data.rel_path
- this.$forceUpdate()
- }else{
- this.backImg = JSON.parse(res.data).data.rel_path
- this.$forceUpdate()
- }
- this.flag = true
- }else{
- uni.showToast({
- title: JSON.parse(res.data).msg,
- icon: 'none'
- })
- }
-
- },
- fail(e) {
- this.showTip("上传图片失败");
- },
- });
- },300)
- },
第二个插件使用方法:
需要用到live-pusher直播推流,在manifest.json中勾选,真机调试需要重新打自定义基座再重新运行
为了防止样式兼容问题,另外需配置如下:
在同级目录下创建idcard.nvue文件
然后把下面代码整个copy进去
- <template>
- <view class="live-camera" :style="{ width: windowWidth, height: windowHeight }">
- <view class="preview" :style="{ width: windowWidth, height: windowHeight - 65 }">
- <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: cameraWidth, height: cameraHeight }"
- ></live-pusher>
-
- <!--提示语-->
- <cover-view class="remind">
- <text class="remind-text" style="">{{ message }}</text>
- </cover-view>
-
- <!--辅助线-->
- <cover-view class="outline-box" :style="{ width: windowWidth, height: windowHeight - 80}">
- <cover-image
- class="outline-img"
- :src="dotype == 'face' ? '/static/live-camera/outline/idcardface.png' : '/static/live-camera/outline/idcardbadge.png'"
- style=""
- ></cover-image>
- </cover-view>
- </view>
-
- <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, //打开相机的轮询
- dotype: 'face', //操作类型
- message: '', //提示
- aspect: '2:3', //比例
- cameraWidth: '', //相机画面宽度
- cameraHeight: '', //相机画面宽度
- windowWidth: '', //屏幕可用宽度
- windowHeight: '', //屏幕可用高度
- camerastate: false, //相机准备好了
- livePusher: null, //流视频对象
- snapshotsrc: null //快照
- };
- },
- onLoad(e) {
- console.log('e',e);
- _this = this;
- this.dotype = e.dotype;
- this.initCamera();
- },
- onReady() {
- uni.showToast({
- title: '相机加载中...',
- icon: 'none',
- duration: 800
- })
- this.livePusher = uni.createLivePusherContext('livePusher', this);
- console.log('this.livePusher',this.livePusher);
- this.startPreview(); //开启预览并设置摄像头
- this.poenCarme();
- },
- methods: {
- //轮询打开
- poenCarme() {
- //#ifdef APP-PLUS
- if (plus.os.name == 'Android') {
- console.log('111');
- this.poenCarmeInterval = setInterval(function() {
- console.log(_this.camerastate);
- if (!_this.camerastate) _this.startPreview();
- }, 2500);
- }else{
- console.log('2222');
- }
- //#endif
- },
- //初始化相机
- initCamera() {
- //处理安卓手机异步授权问题
- uni.getSystemInfo({
- success: (res) => {
- console.log('resxxxx',res);
- this.windowWidth = res.windowWidth;
- this.windowHeight = res.windowHeight;
- this.cameraWidth = res.windowWidth;
- this.cameraHeight = res.windowWidth * 1.5;
- }
- });
- },
-
- //开始预览
- startPreview() {
- console.log('执行开始预览');
- this.livePusher.startPreview({
- success: (a) => {
- console.log('aaa',a);
- }
- });
- },
-
- //停止预览
- stopPreview() {
- this.livePusher.stopPreview({
- success: a => {
- console.log('停止预览',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() {
- this.livePusher.snapshot({
- success: e => {
- console.log('快门',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]; //上一个页面
-
- //直接调用上一个页面的setImage()方法,把数据存到上一个页面中去
- prevPage.$vm.setImage({ path: this.snapshotsrc, dotype: this.dotype });
- }
- }
- };
- </script>
-
- <style lang="scss">
-
- .live-camera {
- .preview {
- justify-content: center;
- align-items: center;
- .outline-box {
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- z-index: 99;
- align-items: center;
- justify-content: center;
- .outline-img {
- width: 750rpx;
- height: 1125rpx;
- }
- }
- .remind {
- position: absolute;
- top: 880rpx;
- width: 750rpx;
- z-index: 100;
- align-items: center;
- justify-content: center;
- .remind-text {
- color: #dddddd;
- font-weight: bold;
- }
- }
- }
- .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>
因为第一次使用nvue,代码整个都成灰色,需要在vscode设置中按下图配置,代码就会和.vue文件一样变彩色,方便阅读
在realName.vue文件中加入:
<canvas id="canvas-clipper" canvas-id="canvas-clipper" type="2d" :style="{width: canvasSiz.width+'px',height: canvasSiz.height+'px',position: 'absolute',left:'-500000px',top: '-500000px'}" />
这里用到canvas是为了把live-pusher横屏拍摄的身份证裁剪
- methods:{
- //设置图片
- setImage(e) {
- console.log('跳回这个页面',e);
- let type = e.dotype == 'face' ? 'front' : 'back'
- //显示在页面
- console.log('type',type);
- // this.upLoadImg(e.path,type)
- this.zjzClipper(e.path,type)
- },
- //证件照裁切
- zjzClipper(path,type) {
- uni.getImageInfo({
- src: path,
- success: (image) => {
- console.log('image',image);
- this.canvasSiz.width =188;
- this.canvasSiz.height =273;
-
-
- //因为nvue页面使用canvas比较麻烦,所以在此页面上处理图片
- let ctx = uni.createCanvasContext('canvas-clipper', this);
-
- ctx.drawImage(
- path,
- parseInt(0.15 * image.width),
- parseInt(0.17 * image.height),
- parseInt(0.69 * image.width),
- parseInt(0.65 * image.height),
- 0,
- 0,
- 188,
- 273
- );
-
- ctx.draw(false, () => {
- uni.canvasToTempFilePath(
- {
- destWidth: 188,
- destHeight: 273,
- canvasId: 'canvas-clipper',
- fileType: 'jpg',
- success: (res) => {
- // this.savePhoto(res.tempFilePath);
- // this.frontImg = res.tempFilePath
- this.upLoadImg(res.tempFilePath,type)
- }
- },
- this
- );
- });
- }
- });
- },
如果想保存拍摄的照片还可以使用下面方法
- savePhoto(path){
- this.imagesrc = path;
- //保存到相册
- uni.saveImageToPhotosAlbum({
- filePath: path,
- success: () => {
- uni.showToast({
- title: '已保存至相册',
- duration: 2000
- });
- }
- });
- },
realName.vue的css样式部分
- .personalInfo{
- padding: 27rpx 30rpx;
- box-sizing: border-box;
- background-color: #fff;
- .label{
- display: flex;
- align-items: center;
- margin-bottom: 50rpx;
- .blue{
- width: 8rpx;
- height: 30rpx;
- background-color: #3E71FE;
- margin-right: 12rpx;
- }
- .title{
- font-weight: 500;
- font-size: 32rpx;
- color: #1D1B1A;
- }
- }
- .realName{
- display: flex;
- align-items: center;
- margin-bottom: 30rpx;
- padding-left: 20rpx;
- box-sizing: border-box;
- .name{
- font-weight: 500;
- font-size: 28rpx;
- color: #1D1B1A;
- }
- }
- .tips{
- font-weight: normal;
- font-size: 24rpx;
- color: #929292;
- margin-bottom: 30rpx;
- }
- .lineBottom{
- width: 650rpx;
- height: 2rpx;
- background: #F5F5F5;
- margin: auto;
- margin-bottom: 30rpx;
- }
- .imgBox{
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- padding: 0 82rpx;
- box-sizing: border-box;
- .front{
- position: relative;
- width: 526rpx;
- height: 288rpx;
- border-radius: 20rpx 20rpx 20rpx 20rpx;
- margin-bottom: 28rpx;
- background: url('https://res.qyjpay.cn/static/res/yewuban-smrz-zhengmian.png') no-repeat center;
- background-size: contain;
- .frontBtn{
- position: absolute;
- bottom: 50rpx;
- left: 123rpx;
- width: 280rpx;
- height: 90rpx;
- line-height: 90rpx;
- background: #3E71FE;
- box-shadow: 0rpx 8rpx 12rpx 1rpx rgba(62,113,254,0.15);
- border-radius: 45rpx 45rpx 45rpx 45rpx;
- font-size: 32rpx;
- color: #FFFFFF;
- font-weight: normal;
- text-align: center;
- }
- image{
- position: absolute;
- left: 0;
- top: 0;
- width: 526rpx;
- height: 288rpx;
- border-radius: 20rpx 20rpx 20rpx 20rpx;
- }
- }
- .transformImg{
- position: absolute;
- left: 120rpx !important;
- top: -120rpx !important;
- transform: rotate(-90deg);
- width: 288rpx !important;
- height: 526rpx !important;
- z-index: 999;
- }
- .back{
- position: relative;
- width: 526rpx;
- height: 288rpx;
- border-radius: 20rpx 20rpx 20rpx 20rpx;
- background: url('https://res.qyjpay.cn/static/res/yewuban-smrz-fanmian.png') no-repeat center;
- background-size: contain;
- .backBtn{
- position: absolute;
- bottom: 50rpx;
- left: 123rpx;
- width: 280rpx;
- height: 90rpx;
- line-height: 90rpx;
- background: #3E71FE;
- box-shadow: 0rpx 8rpx 12rpx 1rpx rgba(62,113,254,0.15);
- border-radius: 45rpx 45rpx 45rpx 45rpx;
- font-size: 32rpx;
- color: #FFFFFF;
- font-weight: normal;
- text-align: center;
- }
- image{
- position: absolute;
- left: 0;
- top: 0;
- width: 526rpx;
- height: 288rpx;
- border-radius: 20rpx 20rpx 20rpx 20rpx;
- }
- }
- }
- }
里面的图片和结构根据项目需求自行修改
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。