APP自定义身份证相机(Android +iOS)

基本上同时兼容安卓和苹果的插件都需要付费,这里我找了2个好用的免费插件

1.仅支持安卓:自定义身份证相机(支持蒙版自定义),内置蒙版,照片预览,身份证裁剪 - DCloud 插件市场、

2.支持iOS(已测),支持Android(未测,应该也可以用):

 自定义相机 - DCloud 插件市场

第一个插件使用方法(仅支持安卓):

创建一个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().platformif(!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:99cameraModule.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 = falseuni.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_paththis.$forceUpdate()}else{this.backImg = JSON.parse(res.data).data.rel_paththis.$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-pusherid="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-imageclass="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-PLUSif (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.tempFilePaththis.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;}}}}

里面的图片和结构根据项目需求自行修改

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/4359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

泰迪智能科技受邀参加2024年粤港澳大湾区产教融合技能人才培养联盟理事会会议

4月24日下午&#xff0c;2024年粤港澳大湾区产教融合技能人才培养联盟&#xff08;以下简称联盟&#xff09;理事会会议在白云区成功举办。 会议由广州市人力资源和社会保障局、广州市发展和改革委员会、广州市教育局、广州市工业和信息化局、广州市总工会等单位指导&#xff…

Python实现对规整的二维列表中每个子列表对应的值求和

目录 一、二维列表及其结构 二、对应位置元素求和的逻辑 三、代码实现 四、优化与改进 五、实际应用场景 六、扩展与变体 七、总结 在Python编程中&#xff0c;处理二维列表&#xff08;即列表的列表&#xff09;是一个常见的任务。有时候我们需要对二维列表中每个子列表…

多线程编程7——wait和notify、notifyAll

线程最大的问题就是抢占式执行&#xff0c;随机调度。可以通过一些API让线程主动阻塞&#xff0c;主动放弃CPU&#xff0c;从而控制线程之间的执行顺序。比如&#xff1a;join&#xff0c;sleep&#xff0c;wait和notify、notifyAll 前面章节已经介绍过 join 和 sleep了&#…

计算机网络-IPv6地址规范与分类

昨天学习了IPv6的基础概念&#xff0c;了解了IPv6的由来以及地址格式&#xff0c;今天继续学习下IPv6的地址分类与表示。 一、IPv6地址缩写规范 IPv6地址的长度为128 bit。一般用冒号分割为8段&#xff0c;每一段16 bit&#xff0c;每一段内用十六进制表示。 IPv6地址格式 那12…

【kettle004】kettle访问本地MySQL数据库并处理数据至execl文件

一直以来想写下基于kettle的系列文章&#xff0c;作为较火的数据ETL工具&#xff0c;也是日常项目开发中常用的一款工具&#xff0c;最近刚好挤时间梳理、总结下这块儿的知识体系。 熟悉、梳理、总结下MySQL关系数据库相关知识体系 kettle访问MySQL数据库并处理数据至execl文件…

详解SPI、I2C、UART、I2S、GPIO、SDIO、CAN

总线,总线,总要陷进里面。这世界上的信号都一样,但是总线却成千上万,让人头疼。 总的来说,总线有三种:内部总线、系统总线和外部总线。内部总线是微机内部各外围芯片与处理器之间的总线,用于芯片一级的互连;而系统总线是微机中各插件板与系统板之间的总线,用于插件板一…

为什么要进行人脸识别?

人脸识别技术被广泛应用于各种场景和行业&#xff0c;其主要目的包括但不限于以下几点&#xff1a; 1. **安全验证**&#xff1a;人脸识别可以用作身份验证的一种方式&#xff0c;确保只有授权人员才能进入特定的区域或访问敏感信息。例如&#xff0c;用于解锁手机或电脑、进入…

Linux---为什么会有粘滞位?

在前面已经讲过目录的rwx权限&#xff1a; 可读权限(r): 如果目录没有可读权限, 则无法用ls等命令查看目录中的文件内容. 有可写权限(w):如果目录没有可写权限&#xff0c;则无法在目录中创建文件, 也无法在目录中删除文件.可执行权限(x): 如果目录没有可执行权限, 则无法cd到…

D-Wave 推出快速退火功能,扩大量子计算性能增益

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨浪味仙 排版丨沛贤 深度好文&#xff1a;1400字丨6分钟阅读 摘要&#xff1a;量子计算公司 D-Wave 宣布在其 Leap™ 实时量子云服务中的所有量子处理单元 (QPU) 上推出新的快速退火功能。…

Java 网络编程之TCP(五):分析服务端注册OP_WRITE写数据的各种场景(二)

接上文 二、注册OP_WRITE写数据 服务端代码&#xff1a; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.S…

RFC 6071: IP Security (IPsec) and Internet Key Exchange (IKE) Document Roadmap

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/96882d1fb67b4383bc77c4dd421f7b

【一刷《剑指Offer》】面试题 10:二进制中 1 的个数

力扣对应题目链接&#xff1a;191. 位1的个数 - 力扣&#xff08;LeetCode&#xff09; 牛客对应题目链接&#xff1a;二进制中1的个数_牛客题霸_牛客网 一、《剑指Offer》内容 核心考点 &#xff1a;二进制计算。 二、分析问题 1、循环检查二进制位 可以直接循环检查给定数字…

Springboot实现国际化以及部署Linux不生效问题

1、在application.properties 添加以下配置&#xff1a; #国际化配置 spring.messages.basenamei18n/messages/messages spring.messages.fallback-to-system-localefalse 2、添加配置文件在 resources目录下 如下图所示&#xff1a; 这个国际化文件命名有个坑&#xff0c;必须…

胸部X光图像分类:因果视角

Chest X-ray Image Classification: A Causal Perspective 摘要 这篇论文提出了一种新的方法来处理胸部X射线&#xff08;CXR&#xff09;分类问题&#xff0c;将因果推理融入到基于深度学习的方法中。尽管近年来深度学习在CXR分类方面取得了许多进展&#xff0c;但确保这些算…

【接口测试】JMeter接口关联测试

‍‍1 前言 我们来学习接口管理测试&#xff0c;这就要使用到JMeter提供的JSON提取器和正则表达式提取器了&#xff0c;下面我们来看看是如何使用的吧。 2 JSON提取器 1、添加JSON提取器 在线程组右键 > 添加 > 后置处理器 > JSON提取器 2、JSON提取器参数说明 N…

在浏览器中查看Revit模型:原理及实现

Greg Schleusner AIA 有一天向我提到&#xff0c;业内许多人认为带有 SVF2 的 Autodesk Viewer 是建筑模型最强大、性能最强的在线查看器之一&#xff0c;并且想知道开源 VIM 查看器和格式如何比较。 可以使用NSDT 3DConvert的 Revit插件 上传你的模型并在线查看预览&#xff…

怎么通过PHP语言实现远程控制棋牌室

怎么通过PHP语言实现远程控制棋牌室呢&#xff1f; 本文描述了使用PHP语言调用HTTP接口&#xff0c;实现控制棋牌室&#xff0c;通过专用的包间控制器&#xff0c;来实现包间内所有电器以及门锁的独立控制。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规…

BetterDisplay Pro for Mac:显示器校准软件

BetterDisplay Pro for Mac是一款出色的显示器校准软件&#xff0c;旨在提升你的视觉体验。它提供了准确的显示器参数调整&#xff0c;包括亮度、对比度、色温和色域等&#xff0c;让你的显示器呈现更真实、清晰、细腻的图像。此外&#xff0c;软件还提供多种预设模式和自定义选…

遥感雷达波段的原理及应用

雷达波段是不同波长的组。每一种都有其独特的穿透地球表面的能力。它们还可以揭示环境的不同方面。 雷达频段在电磁频谱内具有特定的频率范围。这些波段由 L-、S-、C- 和 X-波段等字母表示。稍后会详细介绍这一点。 什么是合成孔径雷达&#xff1f; 合成孔径雷达 (SAR) 是一…

后台图书管理系统:SSM整合开发案例

代码已经完善,文章内容会在后续补充 代码地址(https://javazhang.lanzn.com/ig8tf1wd2aba 密码:1234) 1.1 .SpringConfig 代码 Configuration ComponentScan({"com.itheima.service" }) PropertySource("classpath:jdbc.properties") Import({JdbcConfig…