碧桂园
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 line
9.5 KiB

  1. import {CrsClient} from "./crsClient";
  2. import {CryptoJS} from "./CryptoJS";
  3. const systemInfo = wx.getSystemInfoSync();
  4. const SELECT_TYPE = {
  5. NONE: 0,
  6. IMAGE: 1,
  7. VIDEO: 2,
  8. };
  9. let timer = null
  10. Page({
  11. data: {
  12. showtoast: false,
  13. showOverlay: true,
  14. showSelect: false,
  15. SELECT_TYPE: SELECT_TYPE,
  16. selectType: 0,
  17. //CRS配置
  18. config: {
  19. apiKey: 'a9abd99b2dfb3a5bee964cbb0bced0ae', // EasyAR开发中心 - API KEY - API Key
  20. apiSecret: '483e000a38265687c058efb7ab66cbc0917a3331b6dbf5482df46c76cb749529', // EasyAR开发中心 - API KEY - API Secret
  21. crsAppId: '8911f4b8f03725e300ca4130c01f27e9', // EasyAR开发中心 - 云服务 - 云识别管理 - 云识别库信息 - CRS AppId
  22. token: '',
  23. clientHost: 'https://bd9b3490fe845642e600cf53f0cd64b8.cn1.crs.easyar.com:8443', //服务器一般不变
  24. jpegQuality: 0.7, //JPEG压缩质量,建议不低于70%
  25. minInterval: 2000, //最短的两次CRS请求间隔
  26. },
  27. //识别到这个数组中的ID就触发内容
  28. targetIds: [
  29. "6c27e0a1-e4ca-424d-9062-4c8ec676a5ad",
  30. "ec72a9a2-20d5-4b86-82db-05f29e1c0fbb",
  31. "f0bdba05-e610-4d1c-811a-5034ccc0d1f7",
  32. "79014ee9-60c7-4a0c-81ed-0d5889a7ecc9"
  33. ],
  34. showLoading: false,
  35. showLoadingText: "",
  36. },
  37. /** @type {CameraFrameListener} 相机帧回调 */
  38. listener: undefined,
  39. /** @type {HTMLCanvasElement} canvas对象 */
  40. canvas: undefined,
  41. /** @type {boolean} 是否需要持续识别,在点击“识别体验”之后和识别成功之前为true */
  42. runningCrs: undefined,
  43. /** @type {boolean} 当前是否正在进行CRS请求 */
  44. busy: undefined,
  45. /** @type {CrsClient} 负责发起CRS请求的对象 */
  46. crsClient: undefined,
  47. /** @type {number} 最后一次CRS请求的事件,用于判断是否满足最短请求间隔 */
  48. last: undefined,
  49. onLoad: function () {
  50. this.daojishi() // 默认进入页面10S后退出
  51. },
  52. onReady: function () {
  53. if (systemInfo.platform === "devtools") { //开发工具不会触发initdone事件,于是在onReady手动触发
  54. this.onCameraInit();
  55. }
  56. // 获取token
  57. this.queryToken().then(msg => {
  58. console.log(msg)
  59. this.data.config.token = msg;
  60. }).catch(err => {
  61. console.info(err);
  62. });
  63. },
  64. onHide(){
  65. this.listener =null
  66. this.busy=false
  67. this.runningCrs=false
  68. clearInterval(timer);
  69. },
  70. onUnload: function () {
  71. this.listener =null
  72. this.busy=false
  73. this.runningCrs=false
  74. clearInterval(timer);
  75. },
  76. daojishi: function(){
  77. let that = this
  78. let seconds = 10
  79. timer = setInterval(function(){
  80. seconds--;
  81. if(seconds<2){
  82. that.setData({
  83. showtoast: true
  84. })
  85. }
  86. if(seconds<=0){
  87. clearInterval(timer);
  88. this.listener = null
  89. wx.navigateBack({
  90. delta: 1,
  91. })
  92. }
  93. }, 1000)
  94. },
  95. showLoading(text) {
  96. this.setData({
  97. showLoading: true,
  98. showLoadingText: text,
  99. });
  100. },
  101. hideLoading() {
  102. this.setData({
  103. showLoading: false,
  104. });
  105. },
  106. //图像识别部分:
  107. onShow: function () {
  108. if (this.listener) this.listener.start(); //页面隐藏时相机帧的监听会自动停止,但恢复展示时不会自动启动,这里手动启动
  109. this.scan()
  110. },
  111. scan: function () {
  112. this.runningCrs = true;
  113. this.setData({
  114. showOverlay: false,
  115. showContent: false,
  116. selectType: SELECT_TYPE.NONE,
  117. });
  118. this.showLoading("识别中");
  119. },
  120. onCameraInit: function () {
  121. //找到canvas对象
  122. const query = wx.createSelectorQuery();
  123. query.select('#capture')
  124. .fields({node: true})
  125. .exec((res) => {
  126. const canvas = res[0].node;
  127. //设置canvas内部尺寸为480*640,frame-size="medium"的设置下相机帧大多是480*640
  128. canvas.width = 480;
  129. canvas.height = 640;
  130. this.canvas = canvas;
  131. this.crsClient = new CrsClient(this.data.config, this.canvas);
  132. //开始监听相机帧
  133. let cameraContext = wx.createCameraContext();
  134. this.listener = cameraContext.onCameraFrame(frame => {
  135. if (!this.canvas) return;
  136. let canvas = this.canvas;
  137. //如果尺寸不匹配,就修改canvas尺寸以适应相机帧
  138. if (canvas.width !== frame.width || canvas.height !== frame.height) {
  139. canvas.width = frame.width;
  140. canvas.height = frame.height;
  141. }
  142. this.queryImage(frame);
  143. });
  144. this.listener.start();
  145. });
  146. },
  147. queryImage: function (frame) {
  148. if (!this.runningCrs || this.busy || !this.crsClient) return;
  149. //最短的两次CRS请求间隔
  150. let now = new Date().getTime();
  151. if (this.last && (now - this.last < this.data.config.minInterval)) return;
  152. this.last = now;
  153. this.busy = true; //如果正在进行CRS请求,就不允许再次请求
  154. this.crsClient.queryImage(frame).then(res => {
  155. if (!this.runningCrs) return; //避免在停止后仍然触发
  156. let result = res.result;
  157. if (!result) return;
  158. if (result.target) {
  159. console.log("识别成功");
  160. this.runningCrs = false;
  161. this.hideLoading();
  162. let base64 = result.target.meta
  163. let web = this.base64_decode(base64)
  164. console.log(web)
  165. // 解析跳转链接
  166. wx.navigateTo({
  167. url: '/pages/out/index?web=' + web + '&index=2',
  168. })
  169. // todo: 解析meta中的信息,触发业务逻辑
  170. //如果待触发的id列表中存在识别到的这个id,就触发
  171. if (this.data.targetIds.find(targetId => targetId === result.target.meta)) {
  172. this.onResult(result.target.meta);
  173. }
  174. } else {
  175. console.log("识别失败");
  176. }
  177. this.busy = false;
  178. }).catch(e => {
  179. this.busy = false;
  180. }); //小程序iOS端不支持finally,所以在then和catch里分别设置busy = false
  181. },
  182. onResult: function (target) {
  183. console.log("触发内容!");
  184. console.log(target);
  185. if (target) {
  186. console.log("meta base64:", target);
  187. }
  188. this.setData({
  189. showOverlay: false,
  190. showContent: true,
  191. selectType: SELECT_TYPE.IMAGE,
  192. });
  193. },
  194. //界面:
  195. back: function () {
  196. this.runningCrs = false;
  197. this.setData({
  198. showOverlay: true,
  199. showContent: false,
  200. selectType: SELECT_TYPE.NONE,
  201. });
  202. this.hideLoading();
  203. },
  204. queryToken: function() { // 获取token
  205. return new Promise((resolve, reject) => {
  206. wx.request({
  207. url: getApp().globalData.httpurl +'ar/ar/getToken',
  208. method: 'get',
  209. data: {},
  210. header: {
  211. 'content-type': 'application/json'
  212. },
  213. success: res => resolve(res.data),
  214. fail: err => reject(err)
  215. });
  216. });
  217. },
  218. base64_decode(input) { // 解码,配合decodeURIComponent使用
  219. var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  220. var output = "";
  221. var chr1, chr2, chr3;
  222. var enc1, enc2, enc3, enc4;
  223. var i = 0;
  224. input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  225. while (i < input.length) {
  226. enc1 = base64EncodeChars.indexOf(input.charAt(i++));
  227. enc2 = base64EncodeChars.indexOf(input.charAt(i++));
  228. enc3 = base64EncodeChars.indexOf(input.charAt(i++));
  229. enc4 = base64EncodeChars.indexOf(input.charAt(i++));
  230. chr1 = (enc1 << 2) | (enc2 >> 4);
  231. chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
  232. chr3 = ((enc3 & 3) << 6) | enc4;
  233. output = output + String.fromCharCode(chr1);
  234. if (enc3 != 64) {
  235. output = output + String.fromCharCode(chr2);
  236. }
  237. if (enc4 != 64) {
  238. output = output + String.fromCharCode(chr3);
  239. }
  240. }
  241. return this.utf8_decode(output);
  242. },
  243. utf8_decode(utftext) { // utf-8解码
  244. var string = '';
  245. let i = 0;
  246. let c = 0;
  247. let c1 = 0;
  248. let c2 = 0;
  249. while (i < utftext.length) {
  250. c = utftext.charCodeAt(i);
  251. if (c < 128) {
  252. string += String.fromCharCode(c);
  253. i++;
  254. } else if ((c > 191) && (c < 224)) {
  255. c1 = utftext.charCodeAt(i + 1);
  256. string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
  257. i += 2;
  258. } else {
  259. c1 = utftext.charCodeAt(i + 1);
  260. c2 = utftext.charCodeAt(i + 2);
  261. string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
  262. i += 3;
  263. }
  264. }
  265. return string;
  266. }
  267. });