Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

viewfinder.vue 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <template>
  2. <view style="width: 100%;height: 100vh;position: fixed;left: 0;top:0;z-index: 111111;">
  3. <view class="viewfinder">
  4. <view v-if="phoneType == 1"
  5. style="display: flex;align-items: center;justify-content: flex-end;width: 100%;height: 100%;">
  6. <image src="/static/image/etc_bd_ocr_id_card_locator_front.png"
  7. style="height: 220rpx;margin-right: 30rpx;" mode="heightFix"></image>
  8. </view>
  9. <view v-if="phoneType == 2" style="margin: 30rpx 0 0 30rpx;">
  10. <image src="/static/image/etc_bd_ocr_id_card_locator_back.png" style="height: 160rpx;" mode="heightFix">
  11. </image>
  12. </view>
  13. <view v-if="phoneType == 3"
  14. style="margin: -30rpx 0 0 30rpx;display: flex;height: 100%;align-self: flex-end;flex-direction: column;justify-content: flex-end;">
  15. <view style="border: 1px solid #fff;height: 160rpx;width: 160rpx;">
  16. </view>
  17. </view>
  18. <view v-if="phoneType == 4"
  19. style="margin: -30rpx 30rpx 0 0;display: flex;height: 100%;justify-content: flex-end;align-items: flex-end;">
  20. <view style="border: 1px solid #fff;height: 60rpx;width: 300rpx;">
  21. </view>
  22. </view>
  23. </view>
  24. <!-- camera -->
  25. <camera v-if="showStartPhoto" id="camera" style="height: 70vh;width: 100vh;background-color: black;width: 100%;"
  26. mode="normal" :device-position="cameraPosition" :flash="flash" @stop="cameraStop" @error="cameraError" />
  27. <view v-if="!showStartPhoto" style="height: 70vh;background-color: black;">
  28. <image style="position: absolute;top: 20%;left: 10%;touch-action: none;" :src="srcImg"
  29. @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd"
  30. :style="{ transform: `translate(${offsetX}px, ${offsetY}px) rotate(${rotateDegree}deg) scale(${scale})`, transition: 'transform ' + transitionDuration + 's' }">
  31. </image>
  32. </view>
  33. <view style="background-color: #A5A5A5;top: 60%;width: 100%;height: 40%;position: absolute;">
  34. <view style="display: flex;flex-direction: row;justify-content: center;align-items: center;height: 100%;">
  35. <view style="flex: 1;"></view>
  36. <image v-if="!showStartPhoto" @click="camera" src="/static/image/etc_bd_ocr_cancel.png"
  37. style="width: 50rpx;height: 50rpx;"></image>
  38. <view style="flex: 1;"></view>
  39. <image @click="takePhoto"
  40. :src="showStartPhoto ? '/static/image/etc_bd_ocr_take_photo_normal.png': '/static/etc_bd_ocr_rotate.png'"
  41. :style="showStartPhoto ? 'width: 140rpx;height: 140rpx;' : 'width: 80rpx;height: 80rpx;'"></image>
  42. <view style="flex: 1;"></view>
  43. <image v-if="!showStartPhoto" @click="success" src="/static/image/etc_bd_ocr_confirm.png"
  44. style="width: 50rpx;height: 50rpx;"></image>
  45. <view style="flex: 1;"></view>
  46. </view>
  47. </view>
  48. </view>
  49. </template>
  50. <script setup lang="ts">
  51. import {
  52. ref
  53. } from 'vue'
  54. let prop = defineProps({
  55. phoneType: {
  56. type: Number,
  57. default: function () {
  58. return 3 //1 身份证正面 2 身份证反面 3 行驶证正面 4 行驶证反面
  59. }
  60. },
  61. showStartPhoto: {
  62. type: Boolean,
  63. default: function () {
  64. return true
  65. }
  66. },
  67. images: {
  68. type: String
  69. }
  70. });
  71. console.log('输出内容', prop.phoneType)
  72. const emit = defineEmits<{
  73. (e : "confirmReturn", content : any) : void;
  74. (e : "failReturn", content : any) : void;
  75. (e : "camera") : void;
  76. }>();
  77. let cameraPosition = 'back' // 'back'为后置摄像头,'front'为前置摄像头
  78. let flash = 'off' // 'off'为关闭闪光灯,'on'为打开闪光灯
  79. let scaleStep = 0.5 //每次缩放的最大增量
  80. let srcImg = ref(prop.images)
  81. let rotateDegree = ref(0)
  82. let touchStartDistance = ref(0)
  83. let touchMoveDistance = ref(0)
  84. let scale = ref(1)
  85. let transitionDuration = ref(0)
  86. const startX = ref(0);
  87. const startY = ref(0);
  88. const offsetX = ref(0);
  89. const offsetY = ref(0);
  90. const dragging = ref(false);
  91. const handleTouchStart = (event : TouchEvent) => {
  92. console.log('手柄触摸启动', '==1')
  93. if (event.touches.length === 1) {
  94. startX.value = event.changedTouches[0].pageX - offsetX.value;
  95. startY.value = event.changedTouches[0].pageY - offsetY.value;
  96. dragging.value = true;
  97. transitionDuration.value = 0.15
  98. } else if (event.touches.length === 2) {
  99. touchStartDistance.value = getTouchDistance(event.touches);
  100. transitionDuration.value = 0.5
  101. }
  102. };
  103. const handleTouchMove = (event : TouchEvent) => {
  104. console.log('手柄触摸启动', '==2')
  105. if (event.touches.length === 2) {
  106. touchMoveDistance.value = getTouchDistance(event.touches);
  107. updateScale();
  108. } else {
  109. if (dragging.value) {
  110. offsetX.value = event.changedTouches[0].pageX - startX.value;
  111. offsetY.value = event.changedTouches[0].pageY - startY.value;
  112. }
  113. }
  114. };
  115. function getTouchDistance(touches) {
  116. const x = touches[0].clientX - touches[1].clientX;
  117. const y = touches[0].clientY - touches[1].clientY;
  118. return Math.sqrt(x * x + y * y);
  119. }
  120. const handleTouchEnd = () => {
  121. console.log('手柄触摸启动', '==3')
  122. touchStartDistance.value = 0;
  123. touchMoveDistance.value = 0;
  124. dragging.value = false;
  125. };
  126. function updateScale() {
  127. // 计算缩放的增量
  128. const scales = (touchMoveDistance.value - touchStartDistance.value) * scaleStep;
  129. scale.value = Math.max(0.5, Math.min(scale.value + scales, 1)); // 设置缩放的范围,这里设置最小为1,最大为3
  130. }
  131. function takePhoto() {
  132. console.log('输出内容', rotateDegree.value)
  133. if (prop.showStartPhoto) {
  134. let cameraContext = null
  135. // #ifdef MP-WEIXIN
  136. cameraContext = uni.createCameraContext();
  137. // #endif
  138. // #ifdef MP-ALIPAY
  139. cameraContext = my.createCameraContext('camera');
  140. // #endif
  141. // 调用拍照方法
  142. cameraContext.takePhoto({
  143. quality: 'normal',
  144. success: (res) => {
  145. // 在这里处理拍照成功后的逻辑,res.tempImagePath 为拍照的图片路径
  146. console.log('拍照成功:', res.tempImagePath);
  147. srcImg.value = res.tempImagePath
  148. // showStartPhoto.value = false
  149. cameraContext.stopRecord();
  150. emit('confirmReturn', res)
  151. console.log("1111")
  152. },
  153. fail: (error) => {
  154. console.error('拍照失败:', error);
  155. emit('failReturn', error);
  156. },
  157. });
  158. } else {
  159. rotateDegree.value += 90
  160. }
  161. // console.log('输出内容', '===123')
  162. }
  163. //成功
  164. function success() {
  165. console.log('图片地址', srcImg.value);
  166. emit('confirmReturn', {
  167. tempImagePath: srcImg.value
  168. })
  169. }
  170. //重新拍摄
  171. function camera() {
  172. emit('camera')
  173. }
  174. function cameraStop() {
  175. // 相机停止时的回调
  176. console.log('相机已停止');
  177. }
  178. function cameraError(e) {
  179. // 相机出错时的回调
  180. console.error('相机错误:', e.detail.errMsg);
  181. }
  182. </script>
  183. <style>
  184. .viewfinder {
  185. pointer-events: none;
  186. position: absolute;
  187. top: 20%;
  188. left: 10%;
  189. width: 80%;
  190. height: 400rpx;
  191. border: 2px solid #fff;
  192. box-sizing: border-box;
  193. border-radius: 16rpx;
  194. z-index: 2;
  195. }
  196. .container {
  197. position: relative;
  198. height: 100vh;
  199. }
  200. .content {
  201. position: absolute;
  202. top: 50%;
  203. left: 50%;
  204. transform: translate(-50%, -50%);
  205. /* 这是你要垂直居中的内容 */
  206. }
  207. </style>