Taro实现微信小程序自定义拍照截图识别

效果图:

代码:

<template><view class="lary-top" :style="{ height: `${topBarHight}px` }"></view><Camerav-show="!canvasShow"class="camera-photo":style="{width: `${info.windowWidth}px`,height: `${info.windowHeight}px`,}"><viewclass="page-flex":style="{width: `${info.windowWidth}px`,height: `${info.windowHeight}px`,}"><view:style="{height: `${info.windowHeight}px`,width: `${convasXL}px`,}"class="page-mask page-mask-lr take-photo"><viewclass="colose-x":style="{ marginTop: `${convasY - 75}px` }"><cover-imagesrc="@/assets/imgs/icon-x.png"style="height: 24px; width: 24px"@tap="evtBack"></cover-image></view></view><viewclass="page-content":style="{ height: `${info.windowHeight}px` }"><viewclass="page-mask":style="{ height: `${convasY - 40}px` }"></view><viewclass="camera-frame":style="{width: `100%`,height: `${canvasHeight}px`,}"><view class="corner top-left"></view><view class="corner top-right"></view><view class="corner bottom-left"></view><view class="corner bottom-right"></view></view><viewclass="page-mask tackPhoto":style="{ height: `${convasY + 40}px` }"><view class="confirm-photo" @tap="takePhoto">><view class="in-box"></view></view></view></view><view:style="{height: `${info.windowHeight}px`,width: `${convasXL}px`,}"class="page-mask page-mask-lr"></view></view><view class="id-card">请对准框内拍摄<view class="id-card-text">题目</view></view></Camera><viewv-show="canvasShow"class="canvas-main":style="{height: `${info.windowHeight}px`,width: `${info.windowWidth}px`,}"><TopNavbar ref="topbarRef" :navbar-props="{ title: '' }"><template #left><Left @click="evtBack" /></template><template #right><Left color="transparent" /></template></TopNavbar><viewstyle="flex-grow: 1; background-color: rgba(1, 1, 1, 0.9)"class="canvas-wrepper"><view :style="{ width: `${canvasWidth + 40}px` }"><Canvasclass="canvas-style"canvas-id="myCanvas":style="{width: `${canvasWidth}px`,height: `${canvasHeight}px`,}"></Canvas><!-- 二侧底部按钮 --><viewstyle="display: flex;justify-content: space-between;margin-top: 20px;"><viewstyle="color: #fff; font-size: 16px"@tap="reTakePhoto">重新拍照</view><viewstyle="color: #fff; font-size: 16px"v-if="isImgLoading">文件处理中...</view><viewstyle="color: #fff; font-size: 16px"@tap="startOcr"v-if="!isImgLoading">开始识别</view></view></view></view></view>
</template><script>
definePageConfig({navigationStyle: "custom",navigationBarTitleText: "",//启用页面分享//enableShareAppMessage:true,//启动朋友圈分享//enableShareTimeline:true
});
import { reactive, toRefs, ref, onMounted, nextTick, watch } from "vue";
import Taro from "@tarojs/taro";import router from "@/router";
import useSystemInfoStore from "@/stores/systemInfo";
import constants from "@/common/constants";
import store from "@/stores";
import useLoginUserStore from "@/stores/loginUser";
import TopNavbar from "@/components/TopNavbar.vue";
import { Left } from "@nutui/icons-vue-taro";
import { Camera, Canvas } from "@tarojs/components";
export default {name: "Ocr",components: { TopNavbar, Left, Camera, Canvas },setup() {//camera实例const camera = Taro.createCameraContext();//系统信息const systemInfo = useSystemInfoStore();//系统文件服务const fileManager = Taro.getFileSystemManager();//登录用户信息const loginUserStore = useLoginUserStore(store);//头部refconst topbarRef = ref(null);const state = reactive({//识别中isImgLoading: true,//是否正在识别isOcrLoading: false,//转存图片的定时器timer: null,//cor识别内容ocrContent: "",//头部导航栏topBaRefHight: 0,//ocr识别组件的展示img: require("@/assets/imgs/icon-x.png"),//状态栏高度topBarHight: systemInfo.getState.statusBarHeight,//底部导航栏高度bottomBarHight: systemInfo.getState.bottomBarHeight? systemInfo.getState.bottomBarHeight: 0,//是否显示canvascanvasShow: false,//canvas相关计算info: {windowWidth: 0,windowHeight: 0,},//canvas相关计算canvasWidth: 0,canvasHeight: 0,convasX: 0,convasXL: 0,convasY: 0,//图片相关baseImg: "",isBaseImg: false,isCanvas: false,//识别的照相路径srcCanvasPath: "",});//初始化数据const initData = () => {var statusBarHeight = 0;Taro.getSystemInfo({success: (res) => {statusBarHeight = res.statusBarHeight; //状态栏高度state.info.windowHeight = res.windowHeight;state.info.windowWidth = res.windowWidth;state.convasX = res.screenWidth / 4; //遮罩层上下的高度(生成canvas的起始横坐标)state.convasY = res.screenHeight / 5; //遮罩层左右的宽度(生成canvas的起始纵坐标)state.canvasWidth = state.convasX * 3; //中间裁剪部位的宽度state.canvasHeight = state.convasY * 3; //中间裁剪部位的高度state.convasXL = state.convasX / 2;},});//获取胶囊对象var menuButtonObject = Taro.getMenuButtonBoundingClientRect();let menuBottonHeight = menuButtonObject.height; //胶囊高度let menuBottonTop = menuButtonObject.top; //胶囊距离顶部距离state.topBaRefHight =statusBarHeight +menuBottonHeight +(menuBottonTop - statusBarHeight) * 2; //胶囊距离顶部距离};//回退路由 携带好识别信息const evtBack = () => {state.isImgLoading = true;router.back({ data: state.ocrContent });};// Retrieve system info and set top and bottom bar heightsonMounted(async () => {//state.topBarHight = statusBarHeight;//state.bottomBarHight = bottomBarHeight;initData();});//重新拍照const reTakePhoto = () => {//清除定时器停止缓存clearTimeout(state.timer);const canvaCtx = Taro.createCanvasContext("myCanvas", this);canvaCtx.clearRect(0, 0, state.canvasWidth, state.canvasHeight);canvaCtx.draw();state.isOcrLoading = false;state.isImgLoading = true;state.canvasShow = false;};//剪切图片const drawImage = (filepath) => {const ctx = Taro.createCanvasContext("myCanvas", this);Taro.getImageInfo({src: filepath,success: (imgInfo) => {// 我这里宽度和高度都计算了设备比,其实两个值是一样的 ,计算一个就够了let prxHeight = state.info.windowHeight / imgInfo.height; //计算设备比let prxWidth = state.info.windowWidth / imgInfo.width; //计算设备比let canvasWidth = state.canvasWidth;let canvasHeight = state.canvasHeight;//生成ctx.clearRect(0, 0, canvasWidth, canvasHeight);ctx.drawImage(filepath,state.convasXL / prxWidth,(state.convasY - 40) / prxHeight,canvasWidth / prxWidth,canvasHeight / prxHeight,0,0,canvasWidth,canvasHeight);ctx.draw(false, () => {// 增加延迟,等待图片资源加载完成state.timer = setTimeout(() => {Taro.canvasToTempFilePath({canvasId: "myCanvas",success: (res) => {const tempFilePath = res.tempFilePath;//uploadFile(tempFilePath);console.log(tempFilePath);state.isBaseImg = false;state.isCanvas = false;state.baseImg = tempFilePath;state.srcCanvasPath = tempFilePath;state.isImgLoading = false;},fail: (res) => {// 转换为临时文件失败state.isImgLoading = false;Taro.showToast({title: "转换为临时文件失败",duration: 2000,icon: "none",});},},this);}, 2000); // 增加延迟时间,单位为毫秒});},fail: (res) => {// Handle getImageInfo failureTaro.showToast({title: "获取图片信息失败",duration: 2000,icon: "none",});},});};//开始ocr识别const startOcr = () => {//防止连续识别if(state.isOcrLoading){return;}state.isOcrLoading = true;//识别中Taro.showToast({title: "识别中",icon: "loading",duration: 100000,});//上传文件然后识别uploadFile(state.srcCanvasPath);};//文件上传服务  l is not a constructorconst uploadFile = (filepath) => {let file;fileManager.readFile({filePath: filepath,success: (res) => {//读取文件成功file = res.data;//上传给后端 MultipartFile photo 进行解析//上传文件之前剪切照片 将照片按中心剪切然后上传Taro.uploadFile({//TODO constants.taroReqUrl.ocrurl: constants.taroReqUrl.ocr,filePath: filepath,name: "photo",header: {"content-type": "multipart/form-data",Authorization: loginUserStore.token,},success: (res) => {//上传成功//解析成功try {const data = JSON.parse(res.data);state.ocrContent = data.data.content;state.isOcrLoading = false;Taro.hideToast();//识别完成跳转回去evtBack();} catch (e) {state.isOcrLoading = false;Taro.hideToast();//上传失败Taro.showToast({title: "Ocr服务异常",duration: 2000,icon: "none",});}},fail: (res) => {state.isOcrLoading = false;Taro.hideToast();//上传失败Taro.showToast({title: "Ocr服务异常",duration: 2000,icon: "none",});},});},fail: (res) => {Taro.hideToast();//读取文件失败Taro.showToast({title: "文件处理中,请稍后重试",duration: 2000,icon: "none",});},});};//拍照const takePhoto = () => {camera.takePhoto({quality: "high",success: (res) => {//拍照成功const filepath = res.tempImagePath;state.canvasShow = true;drawImage(filepath);state.baseImg = filepath;state.isBaseImg = true;state.isCanvas = true;//上传文件//uploadFile(filepath);},fail: (res) => {//拍照失败 弹出提示框拍照失败 请检查权限Taro.showToast({title: "拍照失败",duration: 2000,icon: "none",});},});};return {...toRefs(state),takePhoto,evtBack,topbarRef,reTakePhoto,startOcr,};},
};
</script><style lang="less">
.camera-warpper {height: 100%;width: 100%;
}//相机聚焦线
.camera-frame {position: relative;.corner {width: 120rpx;height: 120rpx;position: absolute;}.top-left {border-top: 2px solid #fff;border-left: 2px solid #fff;left: 0;top: 0;}.top-right {border-top: 2px solid #fff;border-right: 2px solid #fff;right: 0;top: 0;}.bottom-left {border-bottom: 2px solid #fff;border-left: 2px solid #fff;left: 0;bottom: 0;}.bottom-right {border-bottom: 2px solid #fff;border-right: 2px solid #fff;right: 0;bottom: 0;}
}
//canvas主盒子
.canvas-main {display: flex;flex-direction: column;
}
.canvas-wrepper {display: flex;justify-content: center;align-items: center;
}.lary-top {position: fixed;z-index: 101;top: 0;width: 100%;
}
.camera-photo {position: fixed;z-index: 100;overflow: hidden;
}
.page-flex {display: flex;.take-photo {}
}
.page-mask {background-color: rgba(0, 0, 0, 0.6);
}
.page-mask-lr {display: flex;justify-content: center;.take-photo {}
}
.page-content {flex: 1;
}
.tackPhoto {color: #fff;display: flex;align-items: center;justify-content: center;
}
.confirm-photo {width: 130rpx;height: 130rpx;background-color: #4f4f4f;border: 1px solid #bbbbbb;border-radius: 50%;text-align: center;line-height: 130rpx;justify-content: center;display: flex;align-items: center;.in-box {height: 100rpx;width: 100rpx;background-color: #fff;border-radius: 50%;}
}
.cancel {position: absolute;right: 90rpx;color: #fff;
}
.id-card {position: absolute;font-size: 36rpx;color: #fff;top: 53%;right: 40rpx;display: flex;align-items: center;transform-origin: right;transform: rotate(90deg);
}
.id-card-text {color: #3b8bff;
}
.canvas-style {margin: auto;overflow: hidden;border: 2px solid #ffffff;
}
.base-img {position: fixed;z-index: 101;
}
.success-img {position: fixed;z-index: 101;background-color: black;
}
.after-img-tips {display: flex;align-items: center;justify-content: space-between;width: 100%;position: fixed;bottom: 75rpx;padding-left: 60rpx;padding-right: 60rpx;box-sizing: border-box;
}
.back {width: 141rpx;height: 141rpx;
}
</style>

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

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

相关文章

LIO-SAM如何保存地图

一、找到LIO-SAM配置文件&#xff0c;路径为config/params.yaml&#xff0c;修改以下两项参数&#xff1a; savePCD: true # https://github.com/TixiaoShan/LIO-SAM/issues/3savePCDDirectory: "/home/slam/catkin_ws/src/maps" …

Http带消息头两种请求办法

API接口最近经常碰到&#xff0c;协调几个乙方来回对接&#xff0c;把我折腾晕了&#xff0c;索性自己写一个小的工具&#xff0c;导入历史数据。 获取平台免登录token 接口说明 URL Path&#xff1a;gateweb/bigm-dm/openApi/ologin/openLogin 说明&#xff1a;第三方免登…

Java架构师实战篇Redis亿级数据统计方案

目录 1 Redis亿个keys数据统计方案2 Redis聚合统计(SUNIONSTORE)3 Redis排序统计(LRANGE)4 值状态统计(bitmap)4.1 位图简介4.2 应用场景4.3 常用的命令4 基数统计(SADD)5 总结想学习架构师构建流程请跳转:Java架构师系统架构设计 1 Redis亿个keys数据统计方案 在 Web 和移动…

.NET 一款用于解密web.config配置的工具

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

SpringBoot2:请求处理原理分析-接口参数解析原理(argumentResolvers)

一、知识回顾 我们知道&#xff0c;接口的参数&#xff0c;一般都要配上注解来一起使用。 不同的参数注解&#xff0c;决定了传参的方式不同。 为什么会这样&#xff1f; 如果让你设计接口参数解析&#xff0c;你会怎么做&#xff1f; 首先&#xff0c;我们知道方法参数是形…

机器学习之监督学习(三)神经网络

机器学习之监督学习&#xff08;三&#xff09;神经网络基础 0. 文章传送1. 深度学习 Deep Learning深度学习的关键特点深度学习VS传统机器学习 2. 生物神经网络 Biological Neural Network3. 神经网络模型基本结构模块一&#xff1a;TensorFlow搭建神经网络 4. 反向传播梯度下…

开源的 Windows 12 网页体验版!精美的 UI 设计、丰富流畅的动画

大家周二好呀&#xff01;博主今天给小伙伴们分享一款炫酷的 Windows 12 体验版&#xff0c;网页效果拉满&#xff0c;非常值得我们去尝试&#xff01; 如果你对未来的Windows操作系统充满期待&#xff0c;那么这款开源的Windows 12 网页体验版绝对不容错过&#xff01;这不仅…

consul配置ACL安全认证

文章目录 前言一、漏洞详情二、漏洞处理1.ACL相关介绍2.开启ACL3.创建令牌4.修改acl文件5.修改单节点consul启动配置文件6.重启consul 三、漏洞处理结果验证 前言 因为现阶段属于护网期,因此公司对服务器、业务的安全都很关注,只要再次期间被漏扫出来的漏洞&#xff0c;都需要…

tomcat是不是已经被Springboot集成了?

Tomcat 确实已经被 Spring Boot 集成。Spring Boot 通过其独特的“starter”模块&#xff08;如spring-boot-starter-web&#xff09;实现了对Tomcat的自动配置。当在Spring Boot项目中引入这个starter时&#xff0c;会自动引入相关的依赖&#xff0c;包括tomcat-embed-core、t…

C语言补习课——文件篇

来源&#xff1a;黑马程序员 第157讲 C语言操作文件概述 读取文件&#xff1a;输入流 写文件&#xff1a;输出流 读写的方向判断取决与参照&#xff0c;一般我们站在程序的角度判断读写方向。 第158讲 路径 基本概念 路径就是指文件在电脑中的位置&#xff0c;eg&#xf…

阿里旗下土耳其电商Trendyol计划进军欧洲市场

阿里旗下土耳其电商Trendyol计划进军欧洲市场 近年来&#xff0c;阿里巴巴集团在全球电商领域的布局持续深化&#xff0c;其旗下土耳其电商巨头Trendyol更是凭借其出色的市场表现和强劲的增长势头&#xff0c;成为了备受瞩目的焦点。近日&#xff0c;Trendyol宣布了一项重要战…

Java初步

背景 名字 Oak&#xff08;橡树&#xff09;改到一个岛&#xff08;疑似盛产咖啡&#xff09; Java之父 詹姆斯高斯林&#xff08;James Gosling&#xff09; sun公司研发 现在属于Oracle公司 把它称为甲骨文公司 应用 企业级应用开发 重点学习JavaSE&#xff08;Standa…

线性代数 第六讲 特征值和特征向量_相似对角化_实对称矩阵_重点题型总结详细解析

文章目录 1.特征值和特征向量1.1 特征值和特征向量的定义1.2 特征值和特征向量的求法1.3 特征值特征向量的主要结论 2.相似2.1 相似的定义2.2 相似的性质2.3 相似的结论 3.相似对角化4.实对称矩阵4.1 实对称矩阵的基本性质4.2 施密特正交化 5.重难点题型总结5.1 判断矩阵能否相…

JavaScript高级——函数中的this

1、this是什么&#xff1f; ① 任何函数本质上都是通过某个对象来调用的&#xff0c;如果没有直接指定就是 window 。 ② 所有函数内部都有一个变量 this 。 ③ 它的值是调用函数的当前对象。 2、如何确定 this 的值&#xff1f; ① test&#xff08;&#xff09;&#xff…

如何进行DAP-seq的数据挖掘,筛选验证位点

从样本准备到寄送公司&#xff0c;每一天都在“祈祷”有个心仪的分析结果&#xff0c;终于在这天随着邮件提示音的响起&#xff0c;收到了分析结果...... 分析前工作 爱基在进行数据分析之前&#xff0c;会有两次质控报告反馈给老师们。第一个&#xff0c;基因组DNA的提取质控…

springBoot 集成https

springBoot 集成https 1、springBoot默认的证书格式 pring Boot 需要 .p12 或 .jks 格式的证书。如果你只有 .pem 和 .key 文件&#xff0c;可以使用 openssl 工具将它们转换成 .p12 文件 2、转换.p12 我的证书文件如下&#xff0c;需要转换 2.1 下载openssl https://slpr…

苹果手机铃声怎么设置自己的歌?3个方法自定义手机铃声

苹果手机内部的手机铃声库只有固定的几首铃声&#xff0c;且都是纯音乐&#xff0c;比较单调&#xff0c;并不是所有用户都喜欢这些铃声。那么&#xff0c;苹果手机铃声怎么设置自己的歌呢&#xff1f;小编这里有3个方法&#xff0c;可以教大家如何将手机铃声设置成自己喜欢的歌…

Java 入门指南:Java 并发编程 —— 同步工具类 Semephore(信号量)

文章目录 同步工具类Semephore核心功能限制并发访问量公平与非公平策略灵活性与适应性 常用方法使用示例 同步工具类 JUC&#xff08;Java.util.concurrent&#xff09;是 Java 提供的用于并发编程的工具类库&#xff0c;其中包含了一些通信工具类&#xff0c;用于在多个线程之…

C语言-综合案例:通讯录

传送门&#xff1a;C语言-第九章-加餐&#xff1a;文件位置指示器与二进制读写 目录 第一节&#xff1a;思路整理 第二节&#xff1a;代码编写 2-1.通讯录初始化 2-2.功能选择 2-3.增加 和 扩容 2-4.查看 2-5.查找 2-6.删除 2-7.修改 2-8.退出 第三节&#xff1a;测试 下期…

【单片机开发】单片机常用开发工具

【前言】 在嵌入式系统领域&#xff0c;单片机&#xff08;Microcontroller, MCU&#xff09;作为核心组件&#xff0c;广泛应用于智能家居、工业控制、汽车电子等众多领域。而单片机开发工具&#xff0c;则是开发者们实现创意、解决问题的重要助手。本文主要讲述目前主流的单…