scan-frame.vue 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <template>
  2. <view class="cameraBg">
  3. <!-- position: absolute;left: 100000px; 隐藏canvas画布 -->
  4. <canvas style="width: 100%; height: 100vh;position: absolute;left: 100000px;" canvas-id="canvas" id="canvas"></canvas>
  5. <!-- 相机组件 -->
  6. <camera device-position="back" flash="auto" style="width: 100%; height: 100vh">
  7. <cover-image src="@/static/scan-frame/cameraBg.png" class="cover-img"> </cover-image>
  8. <cover-view class="scanBtn" v-if="scanShow">
  9. <cover-view class="beat" @click="scan">
  10. <cover-image class="beatImg" src="@/static/scan-frame/album.png"></cover-image>
  11. <cover-view> 相册 </cover-view>
  12. </cover-view>
  13. <cover-view class="album" @click="takePhoto">
  14. <cover-image class="albumImg" src="@/static/scan-frame/beat.png"></cover-image>
  15. <cover-view> 拍照 </cover-view>
  16. </cover-view>
  17. <cover-view class="inputs" @click="inputs">
  18. <cover-image class="beatImg" src="@/static/scan-frame/inputs.png"></cover-image>
  19. <cover-view> 手动输入 </cover-view>
  20. </cover-view>
  21. </cover-view>
  22. </camera>
  23. </view>
  24. </template>
  25. <script>
  26. export default {
  27. data() {
  28. return {
  29. scanShow: true, // 显示操作按钮
  30. sysinfo: null, // 设备信息
  31. imageInfo: null // 拍照图片信息
  32. }
  33. },
  34. onReady() {
  35. const sysinfo = uni.getSystemInfoSync()
  36. this.sysinfo = sysinfo
  37. },
  38. methods: {
  39. // 手动输入
  40. inputs(){
  41. uni.redirectTo({
  42. url:"/pages/vinInput/vinInput"
  43. })
  44. },
  45. // 相册
  46. scan() {
  47. // 选择图片
  48. uni.chooseImage({
  49. count: 1,
  50. sizeType: ['original', 'compressed'],
  51. sourceType: ['album'],
  52. success: (res) => {
  53. this.compress(res.tempFilePaths[0],false)
  54. }
  55. })
  56. },
  57. // 裁剪图片
  58. cutImg(fileUrl){
  59. const vm = this
  60. const ctx = uni.createCanvasContext('canvas')
  61. // 将拍照的图片绘制到canvas,宽高等于窗口宽高和手机窗口保持一致
  62. ctx.drawImage(fileUrl,0,0,this.sysinfo.windowWidth,this.sysinfo.windowHeight)
  63. ctx.draw(true,()=>{
  64. const cutW = 650 // 裁剪框宽度
  65. const cutH = 160 // 裁剪框高度
  66. const cutT = 400 // 裁剪框距离顶部距离
  67. const cutL = 50 // 裁剪框距离左侧距离
  68. // 以上裁剪框宽高及坐标是相对于实际蒙板图片的位置
  69. const canvasW=cutW/750*this.sysinfo.windowWidth; // canvas 画布实际宽度
  70. const canvasH=cutH/1624*this.sysinfo.windowHeight; // canvas 画布实际高度
  71. const canvasL =cutL/750*this.sysinfo.windowWidth; // canvas 画布开始坐标x
  72. const canvasT= cutT/1624*this.sysinfo.windowHeight; // canvas 画布开始坐标y
  73. // 开始裁剪
  74. uni.canvasToTempFilePath({
  75. x: canvasL,
  76. y: canvasT,
  77. width: canvasW,
  78. height: canvasH,
  79. canvasId: 'canvas',
  80. success: function(res) {
  81. // 在H5平台下,tempFilePath 为 base64
  82. vm.parseImgs(res.tempFilePath)
  83. }
  84. })
  85. })
  86. },
  87. // 启动图片压缩
  88. compress(tempFilePaths,isCut) {
  89. const vm = this
  90. vm.scanShow = false
  91. uni.showLoading({
  92. title: '智能识别中...'
  93. })
  94. uni.compressImage({
  95. src: tempFilePaths,
  96. quality: 100,
  97. success: (imageRes) => {
  98. // 获取类型
  99. uni.getImageInfo({
  100. src: imageRes.tempFilePath,
  101. success(imageInfo) {
  102. console.log(imageInfo)
  103. vm.imageInfo = imageInfo
  104. if(isCut){
  105. // 裁剪图片
  106. vm.cutImg(imageRes.tempFilePath)
  107. }else{
  108. // 相册选择的图片直接解析,这里如果需要裁剪可以跳转到裁剪图片页面在继续下一步
  109. vm.parseImgs(imageRes.tempFilePath)
  110. }
  111. }
  112. })
  113. }
  114. })
  115. },
  116. // 拿到图片转base64后在开始进行识别
  117. parseImgs(filePath) {
  118. // 图片转base64格式
  119. uni.getFileSystemManager().readFile({
  120. filePath: filePath,
  121. encoding: 'base64',
  122. success: (base) => {
  123. const base64Str = 'data:image/' + this.imageInfo.type + ';base64,' + base.data
  124. // 拿到base64,不需要base64 就把上层的转换去掉
  125. this.scanShow = true
  126. uni.hideLoading()
  127. uni.showToast({
  128. title: '已识别到图片,看console',
  129. duration: 2000
  130. });
  131. // 此处为后端接口 传base64图片 进行ocr识别
  132. // http.request()
  133. uni.redirectTo({
  134. url: "/pages/vinInput/confirmVin?verifyCode=123456ads11234567&filePath="+base64Str
  135. })
  136. },
  137. fail: (err) => {
  138. console.log(err)
  139. }
  140. })
  141. },
  142. // 点击开始拍照
  143. takePhoto() {
  144. // 获取相机上下文对象
  145. const ctx = uni.createCameraContext()
  146. ctx.takePhoto({
  147. quality: 'high',
  148. success: (res) => {
  149. this.compress(res.tempImagePath,true)
  150. }
  151. })
  152. },
  153. error(e) {
  154. console.log(e.detail)
  155. }
  156. }
  157. }
  158. </script>
  159. <style lang="scss" scoped>
  160. .cameraBg {
  161. width: 100%;
  162. height: 100vh;
  163. position: fixed;
  164. .cover-img {
  165. width: 100%;
  166. height: 100vh;
  167. z-index: 1;
  168. }
  169. .scanBtn {
  170. width: 100%;
  171. z-index: 99999;
  172. position: fixed;
  173. bottom: 100rpx;
  174. display: flex;
  175. flex-direction: column;
  176. justify-content: center;
  177. align-items: center;
  178. .beat {
  179. position: absolute;
  180. bottom: 0rpx;
  181. left: 100rpx;
  182. display: flex;
  183. flex-direction: column;
  184. justify-content: center;
  185. align-items: center;
  186. font-size: 24rpx;
  187. font-weight: 400;
  188. color: #ffffff;
  189. .beatImg {
  190. width: 88rpx;
  191. height: 88rpx;
  192. margin-bottom: 30rpx;
  193. }
  194. }
  195. .inputs{
  196. position: absolute;
  197. bottom: 0rpx;
  198. right: 100rpx;
  199. display: flex;
  200. flex-direction: column;
  201. justify-content: center;
  202. align-items: center;
  203. font-size: 24rpx;
  204. font-weight: 400;
  205. color: #ffffff;
  206. .beatImg {
  207. width: 88rpx;
  208. height: 88rpx;
  209. margin-bottom: 30rpx;
  210. }
  211. }
  212. .album {
  213. display: flex;
  214. flex-direction: column;
  215. justify-content: center;
  216. align-items: center;
  217. font-size: 24rpx;
  218. font-weight: 400;
  219. color: #ffffff;
  220. .albumImg {
  221. width: 120rpx;
  222. height: 120rpx;
  223. margin-bottom: 30rpx;
  224. }
  225. }
  226. }
  227. }
  228. </style>