zhuapai.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <template>
  2. <view id="Drop" ref="DropRef" :style="style" @touchmove="touchmove($event)" @touchstart="touchstart($event)">
  3. <view class="phone-camera-box-zhuapai" style="overflow: hidden;height: 150rpx;">
  4. <video ref="videoRef" :class="myClass" style="width:100%; height: 150rpx;position: absolute;"
  5. id="videoZhaPai" :controls="false"></video>
  6. <!-- 隐藏抓拍绘制图片 -->
  7. <canvas id="canvasZhuaPai" :class="myClass"
  8. style="width:100%; height: 150rpx;position: absolute;"></canvas>
  9. <!-- 用于抓拍切出去传递固定img-->
  10. <!-- #ifdef H5 -->
  11. <img :src="imgUrl" alt="" ref="gudingImg" v-show="false">
  12. <!-- #endif -->
  13. <!-- 测试抓拍使用 -->
  14. <button @click="handleZhua">抓拍</button>
  15. </view>
  16. <span v-show="showVideo" @click="noShowVideoBtn" class="shiti-video-hidden-btn">开<i></i></span>
  17. <span v-show="!showVideo" @click="showVideoBtn" class="shiti-video-show-btn">关<i></i></span>
  18. </view>
  19. </template>
  20. <script setup>
  21. import {
  22. ref,
  23. onUnmounted,
  24. nextTick,
  25. computed
  26. } from "vue";
  27. import {
  28. useH5Camera
  29. } from "@/components/zhuapaiConfirm/useCamera";
  30. import * as ksApi from "@/api/kaoshi.js"
  31. import {
  32. getStaticUrl
  33. } from "@/utils/common.js"
  34. const imgUrl = getStaticUrl('static/images/exam/nokaoshi.png')
  35. let zhuapaiFun = null;
  36. let stopCamera = null;
  37. const DropRef = ref(null);
  38. const DropContainerRef = ref(null);
  39. const zhuapai = ref(0); // 单位分
  40. const disX = ref(0); // 移动x
  41. const disY = ref(0); // 移动y
  42. const showVideo = ref(true);
  43. const style = ref({
  44. top: "10vh",
  45. right: "0",
  46. });
  47. const myClass = computed(() => {
  48. return {
  49. 'show-video': showVideo.value,
  50. 'hidden-video': !showVideo.value
  51. }
  52. })
  53. const emits = defineEmits(['init', 'success', 'error', 'cancel'])
  54. function noShowVideoBtn() {
  55. showVideo.value = false
  56. }
  57. function showVideoBtn() {
  58. showVideo.value = true
  59. }
  60. function touchmove(event) {
  61. // 2,获取手指移动的实时位置 需要减去位置差
  62. let moveX = event.touches[0].pageX - disX.value;
  63. let moveY = event.touches[0].pageY - disY.value;
  64. const systemInfo = uni.getSystemInfoSync();
  65. const windowHeight = systemInfo.windowHeight; // 可视区域高度 ‌:ml-citation{ref="1,3" data="citationList"}
  66. const windowWidth = systemInfo.windowWidth; // 可视区域高度 ‌:ml-citation{ref="1,3" data="citationList"}
  67. // 3,获取容器的宽高和拖动元素的宽高 每一次移动都会获取一次 ,建议放在外面进行获取
  68. let dragHeight = DropRef.value.$el.offsetHeight;
  69. let dragWidth = DropRef.value.$el.offsetWidth;
  70. // 4,控制范围:在元素 被拖拽的过程中 判断 元素的定位值 是否到达边界 如果到了 就不能在走了
  71. if (moveX <= 0) {
  72. moveX = 0;
  73. }
  74. // 上边界
  75. if (moveY <= 0) {
  76. moveY = 0;
  77. }
  78. //下边界 容器高度 - 拖动元素高度
  79. if (moveY >= windowHeight - dragHeight - 150) {
  80. moveY = windowHeight - dragHeight - 150;
  81. }
  82. //右边界 容器宽度 - 拖动元素宽度
  83. if (moveX >= windowWidth - dragWidth) {
  84. moveX = 0;
  85. }
  86. // 5,开始移动
  87. style.value.top = moveY + "px";
  88. }
  89. function touchstart(event) {
  90. disX.value = event.touches[0].pageX - DropRef.value.$el.offsetLeft;
  91. disY.value = event.touches[0].pageY - DropRef.value.$el.offsetTop;
  92. }
  93. function init(options) {
  94. zhuapai.value = options.zhuapai;
  95. if (zhuapai.value > 0) {
  96. // 启动摄像头
  97. nextTick(() => {
  98. startCamera()
  99. })
  100. // 设定计时器
  101. // setInterval(() => handleZhua(), zhuapai.value * 60 * 1000 || 6000000)
  102. }
  103. }
  104. function startCamera() {
  105. // 请求摄像头权限并获取流
  106. // #ifdef H5
  107. console.log('navigator', navigator)
  108. const {
  109. startH5Camera,
  110. handlePaiZhao,
  111. stopH5Camera
  112. } = useH5Camera({
  113. elVideoId: '#videoZhaPai',
  114. elCanvasId: '#canvasZhuaPai',
  115. onVideoSuccess,
  116. onVideoError,
  117. zhuapaiHttp: ksApi.getClientZhuaPaiUpdate
  118. })
  119. startH5Camera();
  120. zhuapaiFun = handlePaiZhao;
  121. stopCamera = stopH5Camera;
  122. // #endif
  123. }
  124. function handleZhua() {
  125. zhuapaiFun && zhuapaiFun()
  126. }
  127. function onVideoSuccess() {
  128. setTimeout(() => {
  129. // 首次运行进行抓拍一次
  130. // handleZhua();
  131. }, 3000);
  132. }
  133. function onVideoError() {
  134. emits('error')
  135. }
  136. onUnmounted(() => {
  137. // 组件销毁时停止摄像头
  138. stopCamera && stopCamera();
  139. })
  140. defineExpose({
  141. init
  142. })
  143. </script>
  144. <style lang="scss" scoped>
  145. .dropContainer {
  146. height: 200rpx;
  147. }
  148. #Drop {
  149. width: 30vw;
  150. height: 150rpx;
  151. margin: 0;
  152. padding: 0;
  153. z-index: 10;
  154. position: absolute;
  155. right: 0;
  156. top: 30%;
  157. ::v-deep .uni-video-container {
  158. position: absolute;
  159. }
  160. ::v-deep .uni-video-video {
  161. position: absolute;
  162. }
  163. ::v-deep .uni-canvas-canvas {
  164. position: absolute;
  165. }
  166. ::v-deep .show-video {
  167. z-index: 10;
  168. .uni-video-video,
  169. .uni-canvas-canvas {
  170. z-index: 10;
  171. }
  172. }
  173. ::v-deep .uni-video-container {}
  174. ::v-deep .hidden-video {
  175. z-index: -10;
  176. .uni-video-video,
  177. .uni-canvas-canvas,
  178. {
  179. z-index: -10;
  180. }
  181. }
  182. }
  183. </style>