当前位置:   article > 正文

vue使用tracking实现人脸识别/人脸侦测_multiple readback operations using getimagedata ar

multiple readback operations using getimagedata are faster with the willread

1、安装依赖

npm install tracking.js --save

2、完整代码(人脸识别功能)

以下代码实现打开摄像头识别人脸

注:

1、安卓设备的人脸识别实现规则: 打开设备摄像机后,在相机的拍摄下实时进行人脸识别,如果识别到人脸后,1.5秒后自动拍照(可自行调整拍照时间)。

2、IOS设备的人脸识别实现规则:是利用input file的方式来达到打开IOS设备摄像机的目的,此时IOS设备的相机是全屏状态,所以只能在相机拍摄以后,再利用input的change(changePic)事件来得到拍摄的照片,然后再对照片进行人脸识别(检测是否存在人脸),如果检测通过,会保留该图片并且绘制在页面上,如果未通过人脸检测,则会提示未检测到人脸。

  1. <template>
  2. <div class="camera_outer">
  3. <!--
  4. 此处代码请勿随意删除:
  5. input兼容ios无法调用摄像头的问题
  6. accept属性兼容某些华为手机调用摄像头,打开的是文件管理器的问题
  7. capture="user" 调用前置摄像头 camera 调用后置摄像头
  8. 如果使用 style="display: none" 隐藏input后,可能会出现无法吊起相册等问题
  9. -->
  10. <input
  11. type="file"
  12. id="file"
  13. accept="image/*"
  14. capture="user"
  15. style="opacity: 0;"
  16. @change="changePic"
  17. />
  18. <video
  19. id="videoCamera"
  20. :width="videoWidth"
  21. :height="videoHeight"
  22. autoplay
  23. class="img_bg_camera"
  24. />
  25. <!--
  26. 如果使用 style="display: none" 隐藏canvas后,将不会显示出人脸检测的识别框
  27. 如需要人脸识别框显示 video与canvas 样式是需要相同(目的是保持同一位置)
  28. -->
  29. <canvas
  30. id="canvasCamera"
  31. :width="videoWidth"
  32. :height="videoHeight"
  33. class="img_bg_camera"
  34. />
  35. <div v-if="imgSrc" class="img_bg_camera" :class="[isDisplay ? 'displayBlock' : 'displayNone']">
  36. <img id="imgId" :src="imgSrc" alt class="tx_img" />
  37. </div>
  38. <div class="bottomButton">
  39. <van-button id="open" type="warning" @click="getCamers()" class="marginRight10" >打开摄像机</van-button>
  40. </div>
  41. </div>
  42. </template>
  43. <script>
  44. // npm install tracking.js --save
  45. require("tracking/build/tracking-min.js");
  46. require("tracking/build/data/face-min.js");
  47. require("tracking/build/data/eye-min.js");
  48. require("tracking/build/data/mouth-min.js");
  49. require("tracking/examples/assets/stats.min.js");
  50. export default {
  51. data() {
  52. return {
  53. videoWidth: 300, //摄像机宽度
  54. videoHeight: 300, //摄像机高度
  55. imgSrc: "", //生成图片链接
  56. canvas: null, //canvas
  57. context: null, //context
  58. video: null, //video
  59. isFlag: false, //非正常拍照
  60. isDisplay: false, //生成的照片是否显示
  61. }
  62. },
  63. mounted() {
  64. // this.getCompetence();
  65. },
  66. destroyed() {
  67. this.stopNavigator();
  68. },
  69. methods: {
  70. //调用权限(打开摄像头功能)
  71. getCompetence() {
  72. var _this = this;
  73. //得到canvasCamera的元素
  74. this.canvas = document.getElementById("canvasCamera");
  75. this.context = this.canvas.getContext("2d"); // 画布
  76. this.video = document.getElementById("videoCamera");
  77. // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
  78. if (navigator.mediaDevices === undefined) {
  79. Object.defineProperty(navigator, "mediaDevices", {
  80. value: {},
  81. writable: true,
  82. configurable: true,
  83. enumerable: true,
  84. });
  85. }
  86. // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象,如果使用getUserMedia,因为它会覆盖现有的属性。如果缺少getUserMedia属性,就添加它。
  87. if (navigator.mediaDevices.getUserMedia === undefined) {
  88. navigator.mediaDevices.getUserMedia = function (constraints) {
  89. // 首先获取现存的getUserMedia(如果存在)
  90. var getUserMedia = navigator.getUserMedia || navigator.mediaDevices.getUserMedia;
  91. // 有些浏览器不支持,会返回错误信息
  92. if (!getUserMedia) {
  93. this.$toast("getUserMedia is not implemented in this browser");
  94. return Promise.reject(
  95. new Error(
  96. "getUserMedia is not implemented in this browser"
  97. )
  98. );
  99. }
  100. // 否则,使用Promise将调用包装到旧的navigator.getUserMedia
  101. return new Promise(function (resolve, reject) {
  102. getUserMedia.call(
  103. navigator,
  104. constraints,
  105. resolve,
  106. reject
  107. );
  108. });
  109. };
  110. }
  111. var constraints = {
  112. audio: false,
  113. video: {
  114. width: this.videoWidth,
  115. height: this.videoHeight,
  116. transform: "scaleX(-1)",
  117. facingMode: "user", // user 安卓前置摄像头 {exact: 'environment} 后置摄像头
  118. },
  119. }
  120. //使苹果手机和苹果ipad支持打开摄像机
  121. if (
  122. navigator.userAgent.toLowerCase().indexOf("iphone") != -1 ||
  123. navigator.userAgent.toLowerCase().indexOf("ipad") != -1
  124. ) {
  125. //使得file一定可以获取到
  126. document.getElementById("file").click();
  127. } else { // (安卓/浏览器(除safari浏览器)) 在用户允许的情况下,打开相机,得到相关的流
  128. navigator.mediaDevices
  129. .getUserMedia(constraints)
  130. .then(function (stream) {
  131. // 旧的浏览器可能没有srcObject
  132. if (!_this.video) {
  133. _this.video = {};
  134. }
  135. try {
  136. _this.video.srcObject = stream;
  137. } catch (err) {
  138. _this.video.src = window.URL.createObjectURL(stream); // window.URL || window.webkitURL
  139. }
  140. _this.isFlag = true;
  141. _this.video.onloadedmetadata = () => {
  142. _this.video.play();
  143. _this.initTracker();// 人脸捕捉
  144. }
  145. })
  146. .catch((err) => {
  147. this.$toast('访问用户媒体权限失败,请重试');
  148. });
  149. }
  150. },
  151. // 人脸捕捉 设置各种参数 实例化人脸捕捉实例对象,注意canvas上面的动画效果。
  152. // 使用 domId 来控制监听那个容器 Android 使用容器 #videoCamera,IOS使用容器 #imgId
  153. initTracker(domId) {
  154. // this.tracker = new window.tracking.ObjectTracker("face"); // tracker实例
  155. this.tracker = new window.tracking.ObjectTracker(['face', 'eye', 'mouth']); // tracker实例
  156. this.tracker.setInitialScale(4);
  157. this.tracker.setStepSize(2); // 设置步长
  158. this.tracker.setEdgesDensity(0.1);
  159. try {
  160. this.trackertask = window.tracking.track(domId ? domId :"#videoCamera", this.tracker); // 开始追踪
  161. } catch (e) {
  162. this.$toast("访问用户媒体失败,请重试")
  163. }
  164. //开始捕捉方法 一直不停的检测人脸直到检测到人脸
  165. this.tracker.on("track", (e) => {
  166. //画布描绘之前清空画布
  167. this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  168. if (e.data.length === 0) {
  169. if(domId) this.$toast("未检测到人脸,请重新拍照或上传")
  170. } else {
  171. if(!domId){ // 安卓设备
  172. e.data.forEach((rect) => { //设置canvas 方框的颜色大小
  173. this.context.strokeStyle = "#42e365";
  174. this.context.lineWidth = 2;
  175. this.context.strokeRect(rect.x, rect.y, rect.width, rect.height);
  176. });
  177. if (!this.tipFlag) {
  178. this.$toast("检测成功,正在拍照,请保持不动2秒")
  179. }
  180. }else{ // IOS设备或safari浏览器
  181. if (!this.tipFlag) {
  182. this.$toast("检测成功,正在生成,请稍等")
  183. }
  184. }
  185. // 1.5秒后拍照,仅拍一次 给用户一个准备时间
  186. // falg 限制一直捕捉人脸,只要拍照之后就停止检测
  187. if (!this.flag) {
  188. this.tipFlag = true
  189. this.flag = true;
  190. this.removePhotoID = setTimeout(() => {
  191. this.$toast("图像生成中···")
  192. this.setImage(domId ? true:false);
  193. this.stopNavigator() // 关闭摄像头
  194. this.flag = false
  195. this.tipFlag = false;
  196. clearInterval(this.removePhotoID)
  197. this.removePhotoID = null
  198. }, 1500);
  199. }
  200. }
  201. });
  202. },
  203. //苹果手机获取图片并且保存图片
  204. changePic(event) {
  205. this.isDisplay = false; // 隐藏已拍照片的展示
  206. var reader = new FileReader();
  207. var f = (document.getElementById("file")).files;
  208. reader.readAsDataURL(f[0]);
  209. reader.onload = () => {
  210. var re = reader.result;
  211. this.canvasDataURL(re, { quality: 1 }, (base64Codes) => {
  212. if (base64Codes) {
  213. this.imgSrc = base64Codes;
  214. // 此方式是为了检测图片中是否有人脸
  215. this.$nextTick(()=>{
  216. this.isFlag = true;
  217. this.initTracker('#imgId')
  218. })
  219. // 如果不需要检验拍照或上传图片中是否有人脸,可注释上方人脸检测代码,使用此种方式
  220. // this.isDisplay = true;
  221. // this.submitCollectInfo();
  222. } else {
  223. this.$toast('拍照失败');
  224. }
  225. event.target.value = ""; // 解决上传相同文件不触发change事件问题
  226. });
  227. };
  228. },
  229. //压缩图片
  230. canvasDataURL(path, obj, callback) {
  231. let img = new Image();
  232. img.src = path;
  233. const that = this;
  234. img.onload = () => {
  235. // 默认按比例压缩
  236. var w = that.videoWidth, h = that.videoHeight, scale = w / h;
  237. // 使用人脸识别video高度
  238. // w = obj.width || w;
  239. // h = obj.height || w / scale;
  240. // 使用图片真实高度(像素)图像更加清晰
  241. w = img.width;
  242. h = img.height;
  243. var quality = 0.5; // 默认图片质量为0.5
  244. //生成canvas
  245. var canvas = document.createElement("canvas");
  246. // canvas 设置宽高 使用默认宽高图片会变形、失真
  247. canvas.width = w
  248. canvas.height = h
  249. var ctx = canvas.getContext("2d");
  250. // 创建属性节点
  251. ctx.drawImage(img, 0, 0, w, h);
  252. // 图像质量 数值范围(0 ~ 1) 1表示最好品质,0基本不被辨析但有比较小的文件大小;
  253. if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
  254. quality = obj.quality;
  255. }
  256. // quality值越小,所绘制出的图像越模糊
  257. var base64 = canvas.toDataURL("image/jpeg", quality);
  258. // 回调函数返回base64的值
  259. callback(base64);
  260. };
  261. },
  262. //绘制图片(拍照功能)
  263. setImage(flag) {
  264. if(!this.context){
  265. this.$toast('请打开摄像机')
  266. return;
  267. }
  268. this.context.drawImage(
  269. flag ? document.getElementById('imgId') : this.video,
  270. 0,
  271. 0,
  272. this.videoWidth,
  273. this.videoHeight
  274. );
  275. // 获取图片base64链接
  276. var image = this.canvas.toDataURL("image/png", 0.5);
  277. if (this.isFlag) {
  278. if (image) {
  279. this.imgSrc = image;
  280. this.isDisplay = true;
  281. this.submitCollectInfo();
  282. } else {
  283. this.$toast("图像生成失败");
  284. }
  285. } else {
  286. this.$toast("图像生成失败");
  287. }
  288. },
  289. //保存图片
  290. async submitCollectInfo() { //其中可以和后端做一些交互
  291. console.log('与后端交互');
  292. },
  293. // 关闭摄像头 并且停止人脸检测
  294. stopNavigator() {
  295. if (this.video && this.video.srcObject) {
  296. this.video.srcObject.getTracks()[0].stop();
  297. }
  298. if(this.trackertask) this.trackertask.stop();
  299. this.tracker = null;
  300. this.isFlag = false
  301. },
  302. //打开摄像机
  303. getCamers() {
  304. this.isDisplay = false; // 隐藏已拍照片的展示
  305. this.getCompetence();
  306. },
  307. // 以下是提供的几种可能在优化或者与后端交互时需要使用的方法
  308. // //返回
  309. // goBack() {
  310. // this.stopNavigator();
  311. // //可以写相应的返回的一些操作,携带一些需要携带的参数
  312. // },
  313. // // 访问用户媒体设备
  314. // getUserMedias(constrains, success, error) {
  315. // if (navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { //最新标准API
  316. // navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error);
  317. // } else if (navigator && navigator.webkitGetUserMedia) { //webkit内核浏览器
  318. // navigator.webkitGetUserMedia(constrains).then(success).catch(error);
  319. // } else if (navigator && navigator.mozGetUserMedia) { //Firefox浏览器
  320. // navagator.mozGetUserMedia(constrains).then(success).catch(error);
  321. // } else if (navigator && navigator.getUserMedia) { //旧版API
  322. // navigator.getUserMedia(constrains).then(success).catch(error);
  323. // } else {
  324. // this.$toast("你的浏览器不支持访问用户媒体设备")
  325. // // error("访问用户媒体失败")
  326. // }
  327. // },
  328. // // Base64转文件
  329. // getBlobBydataURI(dataURI, type) {
  330. // var binary = window.atob(dataURI.split(",")[1]);
  331. // var array = [];
  332. // for (var i = 0; i < binary.length; i++) {
  333. // array.push(binary.charCodeAt(i));
  334. // }
  335. // return new Blob([new Uint8Array(array)], {
  336. // type: type,
  337. // });
  338. // },
  339. // compare(url) {
  340. // let blob = this.getBlobBydataURI(url, 'image/png')
  341. // let formData = new FormData()
  342. // formData.append("file", blob, "file_" + Date.parse(new Date()) + ".png")
  343. // // TODO 得到文件后进行人脸识别
  344. // },
  345. }
  346. }
  347. </script>
  348. <style lang="scss" scoped>
  349. .camera_outer {
  350. position: relative;
  351. overflow: hidden;
  352. background-size: cover;
  353. background: white;
  354. width: 100%;
  355. height: 100%;
  356. }
  357. video,
  358. canvas,
  359. .tx_img {
  360. -moz-transform: scaleX(-1);
  361. -webkit-transform: scaleX(-1);
  362. -ms-transform: scaleX(-1);
  363. -o-transform: scaleX(-1);
  364. transform: scaleX(-1);
  365. }
  366. .img_bg_camera {
  367. position: absolute;
  368. bottom: 25%;
  369. top: 25%;
  370. left: 50%;
  371. margin-left: -150px;
  372. border-radius: 50%;
  373. -webkit-border-radius: 50%;
  374. -moz-border-radius: 50%;
  375. -ms-border-radius: 50%;
  376. -o-border-radius: 50%;
  377. }
  378. .img_bg_camera img {
  379. width: 300px;
  380. height: 300px;
  381. border-radius: 50%;
  382. -webkit-border-radius: 50%;
  383. -moz-border-radius: 50%;
  384. -ms-border-radius: 50%;
  385. -o-border-radius: 50%;
  386. }
  387. .displayNone {
  388. // display: none;
  389. opacity: 0;
  390. }
  391. .displayBlock {
  392. // display: block;
  393. opacity: 1;
  394. }
  395. .marginRight10 {
  396. margin-right: 20px;
  397. }
  398. .bottomButton {
  399. position: fixed;
  400. bottom: 20px;
  401. width: 100%;
  402. text-align: center;
  403. }
  404. </style>

该项目在调试时,tracking.js相关依赖会在检测人脸时,会有两个警告频繁出现,但不会影响项目的运行

第一个问题:[Violation] 'requestAnimationFrame' handler took <N>ms 

这个警告通常是因为你的canvas或者video渲染过于复杂或者数据量过大,导致在浏览器的一帧内渲染超时。但本人目前没有太好的解决方法,如广大网友有了解或者是解决办法,希望可以在评论区讨论一下

第二个问题:Canvas2D: Multiple readback operations using getImageData are faster with the willReadFrequently attribute set to true.

这个警告大概的意思是 使用getImageData的多次读回操作会更快,建议将willReadFrequency属性设置为true。目前的解决方法是将 node_modules 依赖中的 tracking.js 和 tracking-min.js 这两个文件中的 getContext("2d") 和 getContext('2d') 整体替换为 getContext("2d",{ willReadFrequently: true })

另外如果不使用npm方式下载,也可以使用本地文件导入的方式 提供tracking.js相关文件 链接: https://pan.baidu.com/s/1oxJ2z6m5g4T9EUZG2XGgdg 提取码: emqn 

3、调试代码(无人脸识别,可自行拍照和上传任意图片)

  1. <template>
  2. <div class="camera_outer">
  3. <!--
  4. 此处代码请勿随意删除:
  5. input兼容ios无法调用摄像头的问题
  6. accept属性兼容某些华为手机调用摄像头,打开的是文件管理器的问题
  7. -->
  8. <input
  9. type="file"
  10. id="file"
  11. accept="image/*"
  12. capture="camera"
  13. style="display: none"
  14. @change="changePic"
  15. />
  16. <video
  17. id="videoCamera"
  18. :width="videoWidth"
  19. :height="videoHeight"
  20. autoplay
  21. class="img_bg_camera"
  22. />
  23. <canvas
  24. style="display: none"
  25. id="canvasCamera"
  26. :width="videoWidth"
  27. :height="videoHeight"
  28. class="img_bg_camera"
  29. />
  30. <div
  31. v-if="imgSrc"
  32. class="img_bg_camera"
  33. :class="[isDisplay ? 'displayBlock' : 'displayNone']"
  34. >
  35. <img :src="imgSrc" alt class="tx_img" />
  36. </div>
  37. <div class="bottomButton">
  38. <van-button color="#aaaaaa" @click="stopNavigator()" class="marginRight10"
  39. >关闭摄像头</van-button
  40. >
  41. <van-button
  42. id="open"
  43. type="warning"
  44. @click="getCamers()"
  45. class="marginRight10"
  46. >打开摄像机</van-button
  47. >
  48. <van-button type="warning" @click="setImage()">拍照</van-button>
  49. </div>
  50. </div>
  51. </template>
  52. <script>
  53. export default {
  54. data() {
  55. return {
  56. videoWidth: 300, //摄像机宽度
  57. videoHeight: 300, //摄像机高度
  58. imgSrc: "", //生成图片链接
  59. canvas: null, //canvas
  60. context: null, //context
  61. video: null, //video
  62. isFlag: false, //非正常拍照
  63. isDisplay: false, //生成的照片是否显示
  64. }
  65. },
  66. mounted() {
  67. // this.getCompetence();
  68. },
  69. destroyed() {
  70. this.stopNavigator();
  71. },
  72. methods: {
  73. //调用权限(打开摄像头功能)
  74. getCompetence() {
  75. var _this = this;
  76. //得到canvasCamera的元素
  77. this.canvas = document.getElementById("canvasCamera");
  78. this.context = this.canvas.getContext("2d");
  79. this.video = document.getElementById("videoCamera");
  80. // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
  81. if (navigator.mediaDevices === undefined) {
  82. Object.defineProperty(navigator, "mediaDevices", {
  83. value: {},
  84. writable: true,
  85. configurable: true,
  86. enumerable: true,
  87. });
  88. }
  89. // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象,如果使用getUserMedia,因为它会覆盖现有的属性。如果缺少getUserMedia属性,就添加它。
  90. if (navigator.mediaDevices.getUserMedia === undefined) {
  91. navigator.mediaDevices.getUserMedia = function (constraints) {
  92. // 首先获取现存的getUserMedia(如果存在)
  93. var getUserMedia = navigator.getUserMedia || navigator.mediaDevices.getUserMedia;
  94. // 有些浏览器不支持,会返回错误信息
  95. if (!getUserMedia) {
  96. console.log('getUserMedia is not implemented in this browser');
  97. return Promise.reject(
  98. new Error(
  99. "getUserMedia is not implemented in this browser"
  100. )
  101. );
  102. }
  103. // 否则,使用Promise将调用包装到旧的navigator.getUserMedia
  104. return new Promise(function (resolve, reject) {
  105. getUserMedia.call(
  106. navigator,
  107. constraints,
  108. resolve,
  109. reject
  110. );
  111. });
  112. };
  113. }
  114. var constraints = {
  115. audio: false,
  116. video: {
  117. width: this.videoWidth,
  118. height: this.videoHeight,
  119. transform: "scaleX(-1)",
  120. },
  121. }
  122. //使苹果手机和苹果ipad支持打开摄像机
  123. if (
  124. navigator.userAgent.toLowerCase().indexOf("iphone") != -1 ||
  125. navigator.userAgent.toLowerCase().indexOf("ipad") != -1
  126. ) {
  127. //使得file一定可以获取到
  128. document.getElementById("file").click();
  129. } else {
  130. //在用户允许的情况下,打开相机,得到相关的流
  131. navigator.mediaDevices
  132. .getUserMedia(constraints)
  133. .then(function (stream) {
  134. // 旧的浏览器可能没有srcObject
  135. if (!_this.video) {
  136. _this.video = {};
  137. }
  138. try {
  139. _this.video.srcObject = stream;
  140. } catch (err) {
  141. _this.video.src = window.URL.createObjectURL(stream);
  142. }
  143. _this.isFlag = true;
  144. _this.video.onloadedmetadata = () => _this.video.play();
  145. })
  146. .catch((err) => {
  147. console.log(err);
  148. });
  149. }
  150. },
  151. //苹果手机获取图片并且保存图片
  152. changePic() {
  153. var reader = new FileReader();
  154. var f = (document.getElementById("file")).files;
  155. reader.readAsDataURL(f[0]);
  156. reader.onload = () => {
  157. var re = reader.result;
  158. this.canvasDataURL(re, { quality: 0.5 }, (base64Codes) => {
  159. if (base64Codes) {
  160. this.imgSrc = base64Codes;
  161. this.isDisplay = true;
  162. this.submitCollectInfo();
  163. } else {
  164. this.$toast('拍照失败');
  165. }
  166. });
  167. };
  168. },
  169. //压缩图片
  170. canvasDataURL(path, obj, callback) {
  171. let img = new Image();
  172. img.src = path;
  173. const that = this;
  174. img.onload = () => {
  175. // 默认按比例压缩
  176. var w = that.videoWidth, h = that.videoHeight, scale = w / h;
  177. // w = obj.width || w;
  178. // h = obj.height || w / scale;
  179. w = img.width || w;
  180. h = img.height || w / scale;
  181. var quality = 0.5; // 默认图片质量为0.5
  182. //生成canvas
  183. var canvas = document.createElement("canvas");
  184. // canvas 设置宽高 使用默认宽高图片会变形、失真
  185. canvas.width = w
  186. canvas.height = h
  187. var ctx = canvas.getContext("2d");
  188. // 创建属性节点
  189. ctx.drawImage(img, 0, 0, w, h);
  190. // 图像质量
  191. if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
  192. quality = obj.quality;
  193. }
  194. // quality值越小,所绘制出的图像越模糊
  195. var base64 = canvas.toDataURL("image/jpeg", quality);
  196. // 回调函数返回base64的值
  197. callback(base64);
  198. };
  199. },
  200. //绘制图片(拍照功能)
  201. setImage() {
  202. this.context.drawImage(
  203. this.video,
  204. 0,
  205. 0,
  206. this.videoWidth,
  207. this.videoHeight
  208. );
  209. // 获取图片base64链接
  210. var image = this.canvas.toDataURL("image/png", 0.5);
  211. if (this.isFlag) {
  212. if (image) {
  213. this.imgSrc = image;
  214. this.isDisplay = true;
  215. this.submitCollectInfo();
  216. } else {
  217. console.log("拍照失败");
  218. }
  219. } else {
  220. console.log("拍照失败");
  221. }
  222. },
  223. //保存图片
  224. async submitCollectInfo() { //其中可以和后端做一些交互
  225. console.log('与后端交互');
  226. },
  227. // 关闭摄像头
  228. stopNavigator() {
  229. if (this.video && this.video.srcObject) {
  230. this.video.srcObject.getTracks()[0].stop();
  231. }
  232. },
  233. //打开摄像机
  234. getCamers() {
  235. this.isDisplay = false; // 隐藏已拍照片的展示
  236. this.getCompetence();
  237. },
  238. }
  239. }
  240. </script>
  241. <style lang="scss" scoped>
  242. .camera_outer {
  243. position: relative;
  244. overflow: hidden;
  245. background-size: cover;
  246. background: white;
  247. width: 100%;
  248. height: 100%;
  249. }
  250. video,
  251. canvas,
  252. .tx_img {
  253. -moz-transform: scaleX(-1);
  254. -webkit-transform: scaleX(-1);
  255. -ms-transform: scaleX(-1);
  256. -o-transform: scaleX(-1);
  257. transform: scaleX(-1);
  258. }
  259. .img_bg_camera {
  260. position: absolute;
  261. bottom: 25%;
  262. top: 25%;
  263. left: 50%;
  264. margin-left: -150px;
  265. border-radius: 50%;
  266. -webkit-border-radius: 50%;
  267. -moz-border-radius: 50%;
  268. -ms-border-radius: 50%;
  269. -o-border-radius: 50%;
  270. }
  271. .img_bg_camera img {
  272. width: 300px;
  273. height: 300px;
  274. border-radius: 50%;
  275. -webkit-border-radius: 50%;
  276. -moz-border-radius: 50%;
  277. -ms-border-radius: 50%;
  278. -o-border-radius: 50%;
  279. }
  280. .displayNone {
  281. display: none;
  282. }
  283. .displayBlock {
  284. display: block;
  285. }
  286. .marginRight10 {
  287. margin-right: 20px;
  288. }
  289. .bottomButton {
  290. position: fixed;
  291. bottom: 20px;
  292. width: 100%;
  293. text-align: center;
  294. }
  295. </style>
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/701612
推荐阅读
相关标签
  

闽ICP备14008679号