cardTesthtml 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>H5摄像头(新版浏览器https)(兼容老版浏览器)</title>
  6. <script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js">
  7. </script>
  8. </head>
  9. <body style="background-color: black;display: flex;flex-direction: column; margin: 0;">
  10. <!-- 说明:将网页更改为https访问才行 否者报错:NotSupportedError Only secure origins are allowed (see: https://goo.gl/Y0ZkNV). -->
  11. <!-- video用于显示媒体设备的视频流,自动播放;属性:https://zhuanlan.zhihu.com/p/535917105 -->
  12. <video id="video" autoplay webkit-playsinline="true" playsinline="true"></video>
  13. <!-- transform: rotateY(180deg); 镜像解决 -->
  14. <!-- 可以通过画布canvas渲染,获取使用默认的video也行 -->
  15. <!-- <canvas id="canvas" width="500" height="400" style="transform: rotateY(180deg);"></canvas> -->
  16. <div class="box">
  17. <canvas id="canvas"></canvas>
  18. <span class="text">请将证件完整置于取景框内</span>
  19. <div class="buttonBox">
  20. <!-- 拍照按钮 -->
  21. <img class="buttonImg" id="back" src="../images/back.png" />
  22. <img class="buttonImg" id="capture" src="../images/pai.png" />
  23. <img class="buttonImg" id="fanzhuan" style="visibility: hidden" src="../images/fan.png" />
  24. </div>
  25. </div>
  26. <div id="popup">
  27. <img id="popupImg" src="" style="transform: rotateY(180deg);">
  28. <div class="popupBox">
  29. <button id="closeBtn">取消</button>
  30. <button id="okBtn">确认</button>
  31. </div>
  32. </div>
  33. <script type="text/javascript">
  34. // 获取弹窗元素
  35. var popup = document.getElementById('popup');
  36. var popupImg = document.getElementById('popupImg');
  37. popup.style.display = 'none';
  38. // 获取关闭按钮元素
  39. var closeBtn = document.getElementById('closeBtn');
  40. var okBtn = document.getElementById('okBtn');
  41. var video = document.getElementById("video");
  42. var canvas = document.getElementById("canvas");
  43. var context = canvas.getContext("2d");
  44. var ratio = 1;
  45. var v_t_h = window.screen.height - 300,
  46. v_t_w = window.screen.width;
  47. var mode = 'environment';
  48. var mediaStreamTrack;
  49. canvas.width = v_t_w;
  50. canvas.height = v_t_h;
  51. video.height = v_t_h
  52. document.addEventListener('UniAppJSBridgeReady', function() {
  53. okBtn.addEventListener('click', function() {
  54. uni.postMessage({
  55. data: {
  56. base64: popupImg.src
  57. }
  58. });
  59. window.history.back(-1)
  60. });
  61. });
  62. // 弹出弹窗
  63. function openPopup() {
  64. popup.style.display = 'block';
  65. }
  66. // 关闭弹窗
  67. function closePopup() {
  68. takePhoto();
  69. popup.style.display = 'none';
  70. }
  71. // 绑定关闭按钮的点击事件
  72. closeBtn.addEventListener('click', closePopup);
  73. // 访问用户媒体设备的兼容方法
  74. function getUserMedia(constrains, successFun, errorFun) {
  75. //like12 modified,20210628,bug,navigator.mediaDevices为空会导致后面卡死
  76. if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  77. //最新标准API(新版浏览器https)
  78. navigator.mediaDevices.getUserMedia(constrains).then(successFun).catch(errorFun);
  79. } else if (navigator.webkitGetUserMedia) {
  80. //like12 modified,20210628,不是这种调用方法 应该为后者
  81. //webkit内核浏览器(老版浏览器)
  82. //navigator.webkitGetUserMedia(constrains).then(successFun).catch(errorFun);
  83. navigator.webkitGetUserMedia({
  84. "video": true
  85. }, successFun, errorFun);
  86. } else if (navigator.mozGetUserMedia) {
  87. //Firefox浏览器
  88. navagator.mozGetUserMedia(constrains).then(successFun).catch(errorFun);
  89. } else if (navigator.getUserMedia) {
  90. //旧版API
  91. navigator.getUserMedia(constrains).then(successFun).catch(errorFun);
  92. }
  93. }
  94. // 成功的回调函数
  95. function successFun(stream) {
  96. //like12 modifed,20210618,Chrome升级后,新版本不再支持该用法
  97. //摄像头视频流显示报错Failed to execute 'createObjectURL' on 'URL'
  98. //研究即时通信的过程中需要调用摄像头,发现报错,原来是谷歌弃用了这个方法,根据官方提示修改即可
  99. //所以原先的代码:video.src = URL.createObjectURL(stream);
  100. //需要被修改为:video.srcObject = stream;
  101. //(新版浏览器https)
  102. if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  103. video.srcObject = stream;
  104. }
  105. //(老版浏览器)
  106. else {
  107. //兼容webkit内核浏览器
  108. var CompatibleURL = window.URL || window.webkitURL;
  109. //将视频流设置为video元素的源
  110. //此处的代码将会报错 解决的办法是将video的srcObject属性指向stream即可
  111. video.src = CompatibleURL.createObjectURL(stream);
  112. }
  113. mediaStreamTrack = stream.getTracks()[0];
  114. let settings = mediaStreamTrack.getSettings()
  115. const { height, width } = settings
  116. // ratio = width / height
  117. // v_t_w = v_t_h * ratio
  118. // canvas.width = v_t_w;
  119. // canvas.height = v_t_h;
  120. // 播放视频
  121. video.play();
  122. // 可以通过画布canvas渲染,获取使用默认的video也行
  123. setInterval(function() {
  124. context.drawImage(video, 0, 0, v_t_w, v_t_h);
  125. // context.beginPath();
  126. // context.arc(centerX, centerY, 70, 0, Math.PI * 2, false); // 绘制
  127. // context.stroke();
  128. }, 10);
  129. }
  130. // 异常的回调函数
  131. function errorFun(error) {
  132. console.log("访问用户媒体设备失败:", error.name, error.message);
  133. alert("访问用户媒体设备失败:" + error.name + " " + error.message);
  134. }
  135. document.getElementById('back').addEventListener('click', function() {
  136. window.history.back(-1)
  137. })
  138. document.getElementById('fanzhuan').addEventListener('click', function() {
  139. changeMode();
  140. })
  141. // 注册拍照按钮的单击事件-截图
  142. document.getElementById("capture").addEventListener("click", function() {
  143. mediaStreamTrack && mediaStreamTrack.stop();
  144. var base64Img = canvas.toDataURL('image/jpg');
  145. //var base64 = canvas.toDataURL('image/jpeg',0.5);// 图片质量0.5
  146. popupImg.src = base64Img;
  147. openPopup()
  148. });
  149. function takePhoto() {
  150. // 开始调用摄像头
  151. //like12 modified,20210628,bug,navigator.mediaDevices为空会导致后面卡死
  152. if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia ||
  153. navigator.getUserMedia ||
  154. navigator.webkitGetUserMedia ||
  155. navigator.mozGetUserMedia) {
  156. // 调用用户媒体设备,访问摄像头
  157. getUserMedia({
  158. // video: {
  159. // width: { min: 640 },
  160. // height: { min: 480 },
  161. // facingMode: mode //设置使用后置摄像头,user为前置摄像头
  162. // },
  163. video: true,
  164. }, successFun, errorFun);
  165. } else {
  166. alert("你的浏览器不支持访问用户媒体设备");
  167. }
  168. }
  169. takePhoto();
  170. function changeMode() {
  171. console.log("翻转摄像头");
  172. mode = mode === 'user' ? 'environment' : 'user';
  173. mediaStreamTrack.stop();
  174. takePhoto();
  175. }
  176. </script>
  177. </body>
  178. <style>
  179. video {
  180. transform: rotateY(180deg);
  181. /* display: none; */
  182. }
  183. .box {
  184. margin: 0 auto;
  185. display: flex;
  186. flex-direction: column;
  187. text-align: center;
  188. width: 100%;
  189. }
  190. canvas {
  191. display: none;
  192. position: fixed;
  193. top: 10%;
  194. left: 10%;
  195. height: 200px;
  196. width: 200px;
  197. border: 1px solid blue;
  198. transform: rotateY(180deg);
  199. background: transparent;
  200. /* margin-top: 5vh; */
  201. /* border-radius: 50%; */
  202. }
  203. .text {
  204. margin-top: 3vh;
  205. color: #888;
  206. }
  207. .buttonBox {
  208. position: fixed;
  209. bottom: 10%;
  210. left: 0%;
  211. width: 100%;
  212. display: flex;
  213. justify-content: space-around;
  214. margin-top: 15vh;
  215. .buttonImg {
  216. width: 15vw;
  217. object-fit: contain;
  218. }
  219. }
  220. .noneImg {
  221. display: none;
  222. }
  223. #popup {
  224. position: fixed;
  225. top: 30%;
  226. left: 50%;
  227. transform: translate(-50%, -50%);
  228. background: #fff;
  229. padding: 20px;
  230. border-radius: 5px;
  231. box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
  232. z-index: 9999;
  233. }
  234. #popup h2 {
  235. margin-top: 0;
  236. }
  237. #closeBtn {
  238. width: 30vw;
  239. height: 4vh;
  240. border-radius: 16px;
  241. }
  242. #okBtn {
  243. width: 30vw;
  244. height: 4vh;
  245. border-radius: 16px;
  246. }
  247. .popupBox {
  248. margin-top: 2vh;
  249. width: 100%;
  250. display: flex;
  251. justify-content: space-around;
  252. }
  253. </style>
  254. </html>