├── components
├── card
│ ├── card.json
│ ├── card.wxml
│ ├── card.js
│ └── card.wxss
├── loading
│ ├── loading.json
│ ├── loading.js
│ ├── loading.wxml
│ └── loading.wxss
├── audio-player
│ ├── audio-player.json
│ ├── audio-player.wxml
│ ├── audio-player.wxss
│ ├── Player.js
│ └── audio-player.js
├── video-player
│ ├── video-player.json
│ ├── video-player.wxml
│ ├── video-player.js
│ └── video-player.wxss
└── private-modal
│ ├── private-modal.json
│ ├── private-modal.wxml
│ ├── private-modal.wxss
│ └── private-modal.js
├── static
└── images
│ ├── beef.png
│ ├── chef.png
│ ├── text.png
│ ├── close.png
│ ├── video.png
│ ├── pause-audio.png
│ ├── default-audio.png
│ ├── loading-icon.png
│ └── loading-content.png
├── sitemap.json
├── app.wxss
├── project.private.config.json
├── .gitignore
├── app.js
├── pages
└── index
│ ├── index.json
│ ├── index.wxml
│ ├── index.wxss
│ ├── index.js
│ └── Food.js
├── app.json
├── utils
├── stats.js
└── util.js
├── .eslintrc.js
├── package.json
├── README.md
├── project.config.json
├── miniprogram_npm
└── umtrack-wx
│ └── index.js
└── animate.wxss
/components/card/card.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/components/loading/loading.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/components/audio-player/audio-player.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/components/video-player/video-player.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/components/private-modal/private-modal.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/static/images/beef.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-slam-plugin-api-sample/HEAD/static/images/beef.png
--------------------------------------------------------------------------------
/static/images/chef.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-slam-plugin-api-sample/HEAD/static/images/chef.png
--------------------------------------------------------------------------------
/static/images/text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-slam-plugin-api-sample/HEAD/static/images/text.png
--------------------------------------------------------------------------------
/static/images/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-slam-plugin-api-sample/HEAD/static/images/close.png
--------------------------------------------------------------------------------
/static/images/video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-slam-plugin-api-sample/HEAD/static/images/video.png
--------------------------------------------------------------------------------
/static/images/pause-audio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-slam-plugin-api-sample/HEAD/static/images/pause-audio.png
--------------------------------------------------------------------------------
/static/images/default-audio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-slam-plugin-api-sample/HEAD/static/images/default-audio.png
--------------------------------------------------------------------------------
/static/images/loading-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-slam-plugin-api-sample/HEAD/static/images/loading-icon.png
--------------------------------------------------------------------------------
/static/images/loading-content.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-slam-plugin-api-sample/HEAD/static/images/loading-content.png
--------------------------------------------------------------------------------
/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [{
4 | "action": "allow",
5 | "page": "*"
6 | }]
7 | }
--------------------------------------------------------------------------------
/components/audio-player/audio-player.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | @import "./animate.wxss";
3 |
4 | .-kivi-dim {
5 | backdrop-filter: blur(5px);
6 | }
7 |
8 | .layer {
9 | position: absolute;
10 | left: 0;
11 | top: 0;
12 | width: 100%;
13 | height: 100%;
14 | overflow: hidden;
15 | }
--------------------------------------------------------------------------------
/project.private.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
3 | "projectname": "wechat-kivicube-slam-plugin-api-sample",
4 | "setting": {
5 | "compileHotReLoad": true
6 | }
7 | }
--------------------------------------------------------------------------------
/components/loading/loading.js:
--------------------------------------------------------------------------------
1 | Component({
2 | data: {
3 | showLoading: false,
4 | },
5 | methods: {
6 | show() {
7 | this.setData({
8 | showLoading: true,
9 | });
10 | },
11 | hidden() {
12 | this.setData({
13 | showLoading: false,
14 | });
15 | },
16 | },
17 | });
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | # /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | import uma from "umtrack-wx";
2 |
3 | // app.js
4 | App({
5 | umengConfig: {
6 | appKey: "61d50c5ae014255fcbd8c71b",
7 | useOpenid: false,
8 | autoGetOpenid: false,
9 | debug: false,
10 | uploadUserInfo: false,
11 | enableVerify: true // 测试验证数据使用
12 | },
13 | onLaunch() {},
14 | globalData: {
15 | uma,
16 | },
17 | });
18 |
--------------------------------------------------------------------------------
/components/loading/loading.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
--------------------------------------------------------------------------------
/components/audio-player/audio-player.wxss:
--------------------------------------------------------------------------------
1 | /* components/audio-player/audio-player.wxss */
2 | @import "../../app.wxss";
3 |
4 | .player-btn-layout {
5 | position: relative;
6 | width: 10.67vw;
7 | height: 10.67vw;
8 | border-radius: 50%;
9 | background-color: rgba(255, 255, 255, 0.4);
10 | }
11 |
12 | .icon-img {
13 | position: absolute;
14 | left: 50%;
15 | top: 50%;
16 | width: 6.4vw;
17 | height: 6.4vw;
18 | transform: translateX(-50%) translateY(-50%);
19 | }
--------------------------------------------------------------------------------
/components/card/card.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{detail.title}}
7 | ¥{{ detail.price }}元/份
8 |
9 |
10 |
11 |
12 | 立即下单
13 |
--------------------------------------------------------------------------------
/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "disableScroll": true,
3 | "navigationStyle": "custom",
4 | "usingComponents": {
5 | "kivicube-slam": "plugin://kivicube-slam/kivicube-slam",
6 | "Loading": "../../components/loading/loading",
7 | "food-card": "../../components/card/card",
8 | "audio-player": "../../components/audio-player/audio-player",
9 | "private-modal": "../../components/private-modal/private-modal",
10 | "video-player": "../../components/video-player/video-player"
11 | }
12 | }
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/index/index"
4 | ],
5 | "window": {
6 | "backgroundTextStyle": "light",
7 | "navigationBarBackgroundColor": "#fff",
8 | "navigationBarTitleText": "Weixin",
9 | "navigationBarTextStyle": "black"
10 | },
11 | "__usePrivacyCheck__": true,
12 | "style": "v2",
13 | "sitemapLocation": "sitemap.json",
14 | "plugins": {
15 | "kivicube-slam": {
16 | "version": "1.3.11",
17 | "provider": "wx12ad8a61f049ea02"
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/utils/stats.js:
--------------------------------------------------------------------------------
1 | const { benchmarkLevel } = wx.getSystemInfoSync();
2 | /**
3 | * 友盟埋点
4 | * @param {String} eventId 事件id
5 | * @param {Object} [params={}] 属性
6 | */
7 | export function stats(eventId, params = {}) {
8 | try {
9 | const allParams = Object.assign({ benchmarkLevel: `${benchmarkLevel}` }, params);
10 | wx.uma.trackEvent(`${eventId}2`, allParams);
11 | } catch (e) {}
12 | }
13 |
14 | /**
15 | * 计算经过的时间等级,以每0.5s为一个分界线
16 | * @param {Number} startTime 开始时间戳
17 | * @returns {Number} 时间等级
18 | */
19 | export function getTimeLevel(startTime) {
20 | try {
21 | return Math.ceil((Date.now() - startTime) / 500) + '';
22 | } catch (e) {
23 | return "1";
24 | }
25 | }
--------------------------------------------------------------------------------
/components/card/card.js:
--------------------------------------------------------------------------------
1 | // components/card/card.js
2 | import { stats } from "../../utils/stats";
3 |
4 | Component({
5 | properties: {
6 | detail: {
7 | default: {},
8 | type: Object,
9 | },
10 | },
11 | methods: {
12 | buyNow() {
13 | wx.showModal({
14 | title: "立即下单",
15 | content: "这是演示示意,实际可以跳转下单页面",
16 | showCancel: true,
17 | cancelText: "取消",
18 | confirmText: "确定",
19 | success: (result) => {
20 | if (result.confirm) {
21 | }
22 | },
23 | fail: () => {},
24 | complete: () => {},
25 | });
26 |
27 | stats("ar_click_orderNow");
28 | },
29 | },
30 | });
31 |
--------------------------------------------------------------------------------
/components/video-player/video-player.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 制作方法
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Eslint config file
3 | * Documentation: https://eslint.org/docs/user-guide/configuring/
4 | * Install the Eslint extension before using this feature.
5 | */
6 | module.exports = {
7 | env: {
8 | es6: true,
9 | browser: true,
10 | node: true,
11 | },
12 | ecmaFeatures: {
13 | modules: true,
14 | },
15 | parserOptions: {
16 | ecmaVersion: 2018,
17 | sourceType: 'module',
18 | },
19 | globals: {
20 | wx: true,
21 | App: true,
22 | Page: true,
23 | getCurrentPages: true,
24 | getApp: true,
25 | Component: true,
26 | requirePlugin: true,
27 | requireMiniProgram: true,
28 | },
29 | // extends: 'eslint:recommended',
30 | rules: {},
31 | }
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wechat-kivicube-slam-plugin-api-sample",
3 | "version": "1.0.0",
4 | "description": "此项目是基于 kivicube-slam 插件开发的示例小程序。给开发者提供了一个比较完整的示例和流程。",
5 | "private": true,
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/kivisense/wechat-kivicube-slam-plugin-api-sample.git"
12 | },
13 | "keywords": [
14 | "slam"
15 | ],
16 | "author": "bingo",
17 | "license": "ISC",
18 | "bugs": {
19 | "url": "https://github.com/kivisense/wechat-kivicube-slam-plugin-api-sample/issues"
20 | },
21 | "homepage": "https://github.com/kivisense/wechat-kivicube-slam-plugin-api-sample#readme",
22 | "dependencies": {
23 | "umtrack-wx": "^2.7.1"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/components/audio-player/Player.js:
--------------------------------------------------------------------------------
1 | import { resUrl } from "../../utils/util";
2 |
3 | class Player {
4 | constructor() {
5 | this.innerAudioContext = wx.createInnerAudioContext();
6 | this.innerAudioContext.src = resUrl("media/bgm.mp3");
7 | this.innerAudioContext.loop = true;
8 | this.type = "pause";
9 | }
10 |
11 | play() {
12 | this.innerAudioContext.play();
13 | this.type = "play";
14 | }
15 |
16 | pause() {
17 | this.innerAudioContext.pause();
18 | this.type = "pause";
19 | }
20 |
21 | stop() {
22 | this.innerAudioContext.stop();
23 | this.type = "stop";
24 | }
25 |
26 | getType() {
27 | return this.type;
28 | }
29 |
30 | destroy() {
31 | this.stop();
32 |
33 | this.innerAudioContext.destroy();
34 | }
35 | }
36 |
37 | export default Player;
38 |
--------------------------------------------------------------------------------
/components/private-modal/private-modal.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 隐私保护指引
4 |
5 | 在使用当前小程序服务之前,请仔细阅读《{{privacyContractName}}》。如你同意《{{privacyContractName}}》,请点击“同意”开始使用。
8 |
9 |
10 |
11 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/components/video-player/video-player.js:
--------------------------------------------------------------------------------
1 | // components/video-player/video-player.js
2 | import { resUrl } from "../../utils/util";
3 | import { stats } from "../../utils/stats";
4 |
5 | Component({
6 | lifetimes: {
7 | async attached() {
8 | this.videoContext = wx.createVideoContext("kivi-video", this);
9 | },
10 | async detached() {
11 | this.videoContext.stop();
12 | this.videoContext = null;
13 | },
14 | },
15 | data: {
16 | showVideo: false,
17 | videoPath: resUrl("media/movie.mp4"),
18 | },
19 | methods: {
20 | play() {
21 | this.setData({ showVideo: true });
22 | this.videoContext.play();
23 | this.triggerEvent("play");
24 |
25 | stats("ar_click_videoPlay");
26 | },
27 | stop() {
28 | this.setData({ showVideo: false });
29 | this.videoContext.stop();
30 | this.triggerEvent("close");
31 | },
32 | },
33 | });
34 |
--------------------------------------------------------------------------------
/components/loading/loading.wxss:
--------------------------------------------------------------------------------
1 | .-kivi-loading-layout {
2 | position: fixed;
3 | left: 0;
4 | top: 0;
5 | z-index: 9999;
6 | width: 100vw;
7 | height: 100vh;
8 | background-color: #0A001E;
9 | }
10 |
11 | .-kivi-loading-content {
12 | position: absolute;
13 | left: 0;
14 | top: 50%;
15 | width: 100%;
16 | transform: translateY(-50%);
17 | }
18 |
19 | .-kivi-loading-content-img {
20 | display: block;
21 | width: 69.87vw;
22 | height: 44.8vw;
23 | margin: 0 auto;
24 | }
25 |
26 |
27 | .-kivi-loading-footer {
28 | position: absolute;
29 | bottom: 10vw;
30 | color: #fff;
31 | left: 50%;
32 | transform: translateX(-50%);
33 | }
34 |
35 | .-kivi-loading-icon {
36 | display: block;
37 | width: 31.73vw;
38 | height: 9.07vw;
39 | margin: 0 auto;
40 | }
41 |
42 | .-kivi-loading-text {
43 | margin-top: 1.05vw;
44 | text-align: center;
45 | font-size: 3.2vw;
46 | line-height: 4.53vw;
47 | letter-spacing: 2px;
48 | }
--------------------------------------------------------------------------------
/components/audio-player/audio-player.js:
--------------------------------------------------------------------------------
1 | import Player from "./Player";
2 |
3 | const defaultIcon = "/static/images/default-audio.png";
4 | const pauseIcon = "/static/images/pause-audio.png";
5 |
6 | Component({
7 | properties: {},
8 | data: {
9 | icon: defaultIcon,
10 | },
11 | lifetimes: {
12 | async attached() {
13 | this.player = new Player();
14 | },
15 | async detached() {
16 | this.player.destroy();
17 | this.player = null;
18 | },
19 | },
20 | methods: {
21 | touch() {
22 | const type = this.player.getType();
23 | if (type === "play") {
24 | this.pause();
25 | } else {
26 | this.play();
27 | }
28 | },
29 | play() {
30 | this.setData({
31 | icon: defaultIcon,
32 | });
33 | this.player.play();
34 | this.triggerEvent("play");
35 | },
36 | pause() {
37 | this.setData({
38 | icon: pauseIcon,
39 | });
40 | this.player.pause();
41 | this.triggerEvent("pause");
42 | },
43 | },
44 | });
45 |
--------------------------------------------------------------------------------
/components/video-player/video-player.wxss:
--------------------------------------------------------------------------------
1 | /* components/video-player/video-player.wxss */
2 | @import "../../app.wxss";
3 |
4 | .player-btn-layout {
5 | position: relative;
6 | width: 10.67vw;
7 | height: 10.67vw;
8 | border-radius: 50%;
9 | background-color: rgba(255, 255, 255, 0.4);
10 | overflow: visible;
11 | }
12 |
13 | .icon-img {
14 | position: absolute;
15 | left: 50%;
16 | top: 50%;
17 | width: 6.4vw;
18 | height: 6.4vw;
19 | transform: translateX(-50%) translateY(-50%);
20 | }
21 |
22 | .icon-text {
23 | position: absolute;
24 | left: 50%;
25 | bottom: -4.5vw;
26 | width: 15vw;
27 | color: #fff;
28 | font-size: 10px;
29 | text-align: center;
30 | transform: translateX(-50%);
31 | text-shadow: 2px 0px 7px rgba(0, 0, 0, 0.37);
32 | }
33 |
34 | .-kivi-video {
35 | position: fixed;
36 | width: 100vw;
37 | height: 100vh;
38 | left: 0;
39 | top: 0;
40 | }
41 |
42 | .video-close {
43 | position: fixed;
44 | top: 15%;
45 | right: 4.8vw;
46 | z-index: 2;
47 | }
48 |
49 | .hidden {
50 | left: -1000%;
51 | }
--------------------------------------------------------------------------------
/components/card/card.wxss:
--------------------------------------------------------------------------------
1 | .-kivi-dim {
2 | backdrop-filter: blur(5px);
3 | }
4 |
5 | .-kivi-card-layout {
6 | display: flex;
7 | margin: 0 auto;
8 | width: 77.33vw;
9 | height: 15.73vw;
10 | border-radius: 7.87vw;
11 | color: #fff;
12 | /* background-color: #ccc; */
13 | overflow: hidden;
14 | }
15 |
16 | .-kivi-card-layout .-kivi-card-content {
17 | display: flex;
18 | align-items: center;
19 |
20 | width: 48.93vw;
21 | padding: 0 2.4vw;
22 | background-color: rgba(204, 204, 204, 0.5);
23 | }
24 |
25 | .card-img {
26 | width: 10.93vw;
27 | height: 10.93vw;
28 | border-radius: 50%;
29 | overflow: hidden;
30 | /* background-color: #000; */
31 | }
32 |
33 | .card-desc {
34 | margin-left: 2.4vw;
35 | }
36 |
37 | .card-title {
38 | font-size: 4.27vw;
39 | font-weight: 500;
40 | line-height: 5.87vw;
41 | }
42 |
43 | .card-price {
44 | font-size: 3.2vw;
45 | font-weight: 500;
46 | color: #FFFFFF;
47 | line-height: 4.53vw;
48 | }
49 |
50 | .-kivi-card-btn {
51 | width: 28.4vw;
52 | font-size: 4.8vw;
53 | line-height: 15.73vw;
54 | letter-spacing: 1px;
55 | font-weight: bold;
56 | text-align: center;
57 | background-color: #FF4141;
58 | }
--------------------------------------------------------------------------------
/components/private-modal/private-modal.wxss:
--------------------------------------------------------------------------------
1 | .privacy {
2 | position: fixed;
3 | z-index: 9999999;
4 | top: 0;
5 | right: 0;
6 | bottom: 0;
7 | left: 0;
8 | display: flex;
9 | align-items: center;
10 | justify-content: center;
11 | background: rgba(0, 0, 0, .5);
12 | }
13 |
14 | .content {
15 | width: 632rpx;
16 | box-sizing: border-box;
17 | padding: 48rpx;
18 | background: #fff;
19 | border-radius: 16rpx;
20 | }
21 |
22 | .content .title {
23 | color: #333;
24 | font-size: 32rpx;
25 | font-weight: bold;
26 | text-align: center;
27 | }
28 |
29 | .content .des {
30 | margin-top: 40rpx;
31 | color: #666;
32 | font-size: 26rpx;
33 | line-height: 1.6;
34 | text-align: justify;
35 | }
36 |
37 | .content .des .link {
38 | color: #07c160;
39 | text-decoration: underline;
40 | }
41 |
42 | .btns {
43 | display: flex;
44 | margin-top: 48rpx;
45 | }
46 |
47 | .btns .item {
48 | display: flex;
49 | width: 244rpx;
50 | height: 80rpx;
51 | box-sizing: border-box;
52 | align-items: center;
53 | justify-content: space-between;
54 | justify-content: center;
55 | padding-right: 1px;
56 | padding-left: 1px;
57 | border: none;
58 | border-radius: 16rpx;
59 | }
60 |
61 | .btns .reject {
62 | background: #f4f4f5;
63 | color: #909399;
64 | }
65 |
66 | .btns .agree {
67 | background: #07c160;
68 | color: #fff;
69 | }
70 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # wechat-kivicube-slam-plugin-api-sample
2 |
3 | > 描述:此项目是基于 **[kivicube-slam](https://mp.weixin.qq.com/wxopen/plugindevdoc?appid=wx12ad8a61f049ea02&token=561137318&lang=zh_CN)** 插件 开发的示例小程序。给开发者提供了一个比较完整的示例和流程。
4 |
5 |
6 | ---
7 |
8 | >声明:所有的示例代码仅供大家开发参考,若移植到自己的项目后有任何问题,请先自行检查和确认问题来源。确实为组件问题的,请创建Issues反馈。
9 |
10 | ## 目录说明
11 |
12 | .
13 | |
14 | ├──components // 组件
15 | │ ├── loading // loading组件
16 | │ ├── audio-player // 音频播放组件
17 | │ ├── video-player // 视频频播放组件
18 | │ ├── card // 商品详情的card
19 | │
20 | ├── pages // 页面
21 | │ ├── index // 默认页面
22 | │ ├── Food.js // 封装的食物的类
23 | ├── static // 一些静态资源
24 | ├── utils // 一些工具方法
25 |
26 |
27 | ## 快速体验
28 |
29 | 1. 使用git克隆此仓库至本地,可使用命令```git clone git@github.com:kivisense/wechat-kivicube-slam-plugin-api-sample.git```,或者点击右上角按钮Code -> Download ZIP下载代码。
30 | 2. 使用微信开发者工具导入本项目。订购 **[kivicube 企业版](https://www.kivicube.com/blog/pricing/)** 可去除水印。
31 | 3. 如果是企业版 打开app.js文件,替换为我们给予你的license。
32 | 4. 服务器域名配置。有两种方案,一是直接在手机上打开小程序的“开发调试”模式,参考vConsole;二是在小程序后台,将域名“ https://kivicube-resource.kivisense.com ”配置到request和downloadFile两项中,参考微信官方文档 - 网络。推荐第二种。
33 | 5. 之后,可在微信开发者工具上,点击“预览”按钮,用微信扫描打开体验。【Slam功能不支持在开发者工具上运行,也不支持真机调试。】
34 |
35 |
--------------------------------------------------------------------------------
/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 | 请寻找一个平面
15 |
16 |
17 | 选择最佳位置,点击屏幕放置菜品
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件",
3 | "packOptions": {
4 | "ignore": [
5 | {
6 | "value": ".eslintrc.js",
7 | "type": "file"
8 | }
9 | ],
10 | "include": []
11 | },
12 | "setting": {
13 | "urlCheck": true,
14 | "es6": true,
15 | "enhance": true,
16 | "postcss": true,
17 | "preloadBackgroundData": false,
18 | "minified": true,
19 | "newFeature": false,
20 | "coverView": true,
21 | "nodeModules": false,
22 | "autoAudits": false,
23 | "showShadowRootInWxmlPanel": true,
24 | "scopeDataCheck": false,
25 | "uglifyFileName": false,
26 | "checkInvalidKey": true,
27 | "checkSiteMap": true,
28 | "uploadWithSourceMap": true,
29 | "compileHotReLoad": false,
30 | "lazyloadPlaceholderEnable": false,
31 | "useMultiFrameRuntime": true,
32 | "useApiHook": true,
33 | "useApiHostProcess": true,
34 | "babelSetting": {
35 | "ignore": [],
36 | "disablePlugins": [],
37 | "outputPath": ""
38 | },
39 | "useIsolateContext": false,
40 | "userConfirmedBundleSwitch": false,
41 | "packNpmManually": false,
42 | "packNpmRelationList": [],
43 | "minifyWXSS": true,
44 | "disableUseStrict": false,
45 | "minifyWXML": true,
46 | "showES6CompileOption": false,
47 | "useCompilerPlugins": false,
48 | "ignoreUploadUnusedFiles": true,
49 | "condition": false
50 | },
51 | "compileType": "miniprogram",
52 | "libVersion": "2.21.2",
53 | "appid": "wx6afd88ea0cafab69",
54 | "projectname": "wechat-kivicube-slam-plugin-api-sample",
55 | "condition": {},
56 | "editorSetting": {
57 | "tabIndent": "auto",
58 | "tabSize": 2
59 | }
60 | }
--------------------------------------------------------------------------------
/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | background-color: #0A001E;
3 | }
4 |
5 | .slam {
6 | display: block;
7 | width: 100vw;
8 | height: 100vh;
9 | }
10 |
11 | .scan-box {
12 | position: absolute;
13 | top: 45%;
14 | left: 50%;
15 | z-index: 1;
16 | transform: translateX(-50%);
17 | }
18 |
19 | .scan-box .scan-img {
20 | width: 46.93vw;
21 | height: 18.67vw;
22 | }
23 |
24 | .scan-box .scan-txt {
25 | margin-top: 2.93vw;
26 | line-height: 6.4vw;
27 | font-size: 4.53vw;
28 | color: rgba(255, 255, 255, 0.9);
29 | text-align: center;
30 | }
31 |
32 | .find-plane-tip {
33 | position: absolute;
34 | top: 20%;
35 | left: 50%;
36 | z-index: 1;
37 |
38 | width: 85.6vw;
39 | height: 9.07vw;
40 | line-height: 9.07vw;
41 | transform: translateX(-50%);
42 | text-align: center;
43 | color: #fff;
44 | font-weight: bold;
45 | text-shadow: 2px 0px 7px rgba(0, 0, 0, 0.37);
46 | }
47 |
48 | .food-card {
49 | position: absolute;
50 | left: 0;
51 | right: 0;
52 | bottom: 14.13vw;
53 | z-index: 3;
54 | margin: 0 auto;
55 | }
56 |
57 | .-kivi-chef-box {
58 | position: absolute;
59 | left: 0;
60 | top: 20%;
61 | z-index: 1;
62 | }
63 |
64 | .-kivi-chef-box .chef-img {
65 | position: absolute;
66 | left: -12.26vw;
67 | top: 0;
68 | width: 37.33vw;
69 | height: 37.33vw;
70 | }
71 |
72 | .-kivi-chef-box .chef-text {
73 | position: absolute;
74 | top: 16.77vw;
75 | left: 12.8vw;
76 | width: 30.93vw;
77 | height: 13.87vw;
78 | }
79 |
80 | .-kivi-btn-box {
81 | position: absolute;
82 | top: 21%;
83 | right: 4.8vw;
84 | /* background-color:aqua; */
85 | }
86 |
87 | .audio-player {
88 | display: block;
89 | margin-bottom: 4vw;
90 | }
91 |
92 | .video-player {
93 | position: relative;
94 | z-index: 2;
95 | }
--------------------------------------------------------------------------------
/components/private-modal/private-modal.js:
--------------------------------------------------------------------------------
1 | let privacyHandler;
2 | let privacyResolves = new Set();
3 | let closeOtherPagePopUpHooks = new Set();
4 |
5 | if (wx.onNeedPrivacyAuthorization) {
6 | wx.onNeedPrivacyAuthorization((resolve) => {
7 | console.log(
8 | "触发 onNeedPrivacyAuthorization",
9 | typeof privacyHandler === "function"
10 | );
11 | if (typeof privacyHandler === "function") {
12 | privacyHandler(resolve);
13 | }
14 | });
15 | }
16 |
17 | const closeOtherPagePopUp = (closePopUp) => {
18 | closeOtherPagePopUpHooks.forEach((hook) => {
19 | if (closePopUp !== hook) {
20 | hook();
21 | }
22 | });
23 | };
24 |
25 | Component({
26 | properties: {
27 | currentBtnText: {
28 | type: String,
29 | value: "同意",
30 | },
31 | },
32 | data: {
33 | innerShow: false,
34 | privacyContractName: "AR空间定位示例小程序隐私保护指引",
35 | },
36 | lifetimes: {
37 | attached() {
38 | const closePopUp = () => {
39 | this.disPopUp();
40 | };
41 | privacyHandler = (resolve) => {
42 | privacyResolves.add(resolve);
43 | this.popUp();
44 | // 额外逻辑:当前页面的隐私弹窗弹起的时候,关掉其他页面的隐私弹窗
45 | closeOtherPagePopUp(closePopUp);
46 | };
47 |
48 | this.closePopUp = closePopUp;
49 | closeOtherPagePopUpHooks.add(this.closePopUp);
50 | },
51 | detached() {
52 | closeOtherPagePopUpHooks.delete(this.closePopUp);
53 | },
54 | },
55 | pageLifetimes: {
56 | show() {
57 | if (this.closePopUp) {
58 | privacyHandler = (resolve) => {
59 | privacyResolves.add(resolve);
60 | this.popUp();
61 | // 额外逻辑:当前页面的隐私弹窗弹起的时候,关掉其他页面的隐私弹窗
62 | closeOtherPagePopUp(this.closePopUp);
63 | };
64 | }
65 | },
66 | },
67 | methods: {
68 | handleAgree() {
69 | this.disPopUp();
70 | // 这里演示了同时调用多个wx隐私接口时要如何处理:让隐私弹窗保持单例,点击一次同意按钮即可让所有pending中的wx隐私接口继续执行 (看page/index/index中的 wx.getClipboardData 和 wx.startCompass)
71 | privacyResolves.forEach((resolve) => {
72 | resolve({
73 | event: "agree",
74 | buttonId: "agree-btn",
75 | });
76 | });
77 | privacyResolves.clear();
78 | },
79 | handleDisagree() {
80 | this.disPopUp();
81 | privacyResolves.forEach((resolve) => {
82 | resolve({
83 | event: "disagree",
84 | });
85 | });
86 | privacyResolves.clear();
87 | },
88 | popUp() {
89 | if (this.data.innerShow === false) {
90 | this.setData({
91 | innerShow: true,
92 | });
93 | }
94 | },
95 | disPopUp() {
96 | if (this.data.innerShow === true) {
97 | this.setData({
98 | innerShow: false,
99 | });
100 | }
101 | },
102 | openPrivacyContract() {
103 | wx.openPrivacyContract({
104 | success: () => {
105 | console.log("openPrivacyContract success");
106 | },
107 | fail: (res) => {
108 | console.error("openPrivacyContract fail", res);
109 | },
110 | });
111 | },
112 | getPrivateInfo() {
113 | if (wx.getPrivacySetting) {
114 | wx.getPrivacySetting({
115 | success: (res) => {
116 | console.log(
117 | "是否需要授权:",
118 | res.needAuthorization,
119 | "隐私协议的名称为:",
120 | res.privacyContractName
121 | );
122 | },
123 | fail: () => {},
124 | complete: () => {},
125 | });
126 | } else {
127 | console.log("不需要隐私授权");
128 | }
129 | },
130 | },
131 | });
132 |
--------------------------------------------------------------------------------
/pages/index/index.js:
--------------------------------------------------------------------------------
1 | import { errorHandler, showAuthModal, getCameraAuth, resUrl, getSlamV2Support, getPrivate } from "../../utils/util";
2 | import { stats, getTimeLevel } from "../../utils/stats";
3 | import Food from "./Food";
4 |
5 | const steps = ["findPlane", "showPoint", "startScene"]; // 一些UI限制的步骤
6 |
7 | Page({
8 | data: {
9 | showSlam: false,
10 | // 去除水印需要申请license,见 README.md
11 | license:
12 | "ad51dc82b4846b28943338eeaac37f560345bbdba05a91a7aa5da0768d87ca5fea23cbbf1a4772785d92c7d2baaf0b88f373a0dd9c4a1c8bd8184a2f53bd59e0",
13 | scanImg: resUrl("images/scaning.png"),
14 | step: "",
15 | version: "v1",
16 |
17 | detail: {
18 | img: "/static/images/beef.png",
19 | title: "火焰炙烤牛排",
20 | price: 138,
21 | },
22 | },
23 | async onLoad() {
24 | try {
25 | const isSupportV2 = getSlamV2Support();
26 | if(isSupportV2) {
27 | this.setData({version: "v2"});
28 | }
29 |
30 | this.loading = this.selectComponent("#loading");
31 |
32 | this.loading.show();
33 |
34 | await getPrivate(); // 隐私权限判定
35 |
36 | // 此处使用会获取摄像头的权限,直到同意后才会初始化slam以免摄像头报错导致无法初始化。
37 | await getCameraAuth();
38 |
39 | this.setData({ showSlam: true });
40 |
41 | // 设置屏幕常亮
42 | wx.setKeepScreenOn({
43 | keepScreenOn: true,
44 | });
45 |
46 | this.food = new Food();
47 | // 提前下载素材
48 | this.food.loadAssets();
49 |
50 | // 此处是埋点
51 | this.startInitTime = Date.now();
52 | stats("loading_start");
53 | } catch (error) {
54 | console.log(error);
55 | }
56 | },
57 |
58 | onUnload() {
59 | this.food.clear();
60 |
61 | this.food = null;
62 | this.loading = null;
63 | this.videoPlayer = null;
64 | this.audioPlayer = null;
65 | },
66 |
67 | async ready({ detail: slam }) {
68 | try {
69 | // 初始化场景
70 | const loadingTime = await this.food.initScene(slam);
71 | // console.warn("isSlamV2", this.food.slam.isSlamV2())
72 |
73 | this.findPlane();
74 | this.loading.hidden();
75 |
76 | stats("ar_start", { ...loadingTime, loadingDuration: getTimeLevel(this.startInitTime) });
77 | this.readyTime = Date.now();
78 | } catch (e) {
79 | this.loading.hidden();
80 | errorHandler(e);
81 | }
82 | },
83 |
84 | // 寻找屏幕
85 | findPlane() {
86 | this.setData({ step: steps[0] });
87 |
88 | if (this.data.version === "v1") {
89 | setTimeout(() => {
90 | this.setData({ step: steps[1] });
91 | this.food.findPlane();
92 | }, 3000);
93 | }
94 | },
95 |
96 | // v2模式下有平面新增
97 | addAnchors() {
98 | this.setData({ step: steps[1] });
99 | this.food.findPlane();
100 | },
101 |
102 | // 开始场景展示
103 | startScene() {
104 | if (this.data.step !== steps[1]) {
105 | return;
106 | }
107 | try {
108 | this.food.startScene();
109 | this.setData({ step: "" });
110 |
111 | setTimeout(() => {
112 | this.setData({ step: steps[2] });
113 |
114 | wx.nextTick(() => {
115 | this.audioPlayer = this.selectComponent("#audioPlayer");
116 | this.videoPlayer = this.selectComponent("#videoPlayer");
117 | this.audioPlayer.play();
118 | });
119 | }, 2000);
120 |
121 | stats("ar_show_arScene", { arAnchorDuration: getTimeLevel(this.readyTime) });
122 | } catch (err) {
123 | wx.showToast({ title: "放置模型失败,请对准平面", icon: "none" });
124 | }
125 | },
126 |
127 | playVideo() {
128 | this.audioPlayer.pause();
129 | },
130 |
131 | closeVideo() {
132 | this.audioPlayer.play();
133 | },
134 |
135 | error({ detail }) {
136 | // 判定是否camera权限问题,是则向用户申请权限。
137 | if (detail?.isCameraAuthDenied) {
138 | showAuthModal(this);
139 | } else {
140 | errorHandler(detail);
141 | }
142 | },
143 |
144 | onShareAppMessage() {
145 | return {
146 | title: "即刻体验2022微信公开课餐饮AR演示",
147 | path: "pages/index/index",
148 | imageUrl: resUrl("images/share.jpg"),
149 | };
150 | },
151 | });
152 |
--------------------------------------------------------------------------------
/utils/util.js:
--------------------------------------------------------------------------------
1 | export function resUrl(filename) {
2 | return `https://kivicube-resource.kivisense.com/projects/wechat-kivicube-slam-plugin-api-sample-assets/${filename}`;
3 | }
4 |
5 | export function errorHandler(errInfo) {
6 | let message = errInfo;
7 | if (typeof errInfo === "object") {
8 | if (errInfo instanceof Error) {
9 | message = errInfo.message;
10 | console.warn(errInfo.stack);
11 | } else if (errInfo.errMsg) {
12 | message = errInfo.errMsg;
13 | } else {
14 | message = Object.values(errInfo).join("; ");
15 | }
16 | }
17 | console.error(errInfo);
18 | wx.showToast({
19 | title: message,
20 | icon: "none",
21 | });
22 | }
23 |
24 | export function showAuthModal(page) {
25 | wx.showModal({
26 | title: "提示",
27 | content: "请给予“摄像头”权限",
28 | showCancel: false,
29 | success() {
30 | wx.openSetting({
31 | success({ authSetting: { "scope.camera": isGrantedCamera } }) {
32 | if (isGrantedCamera) {
33 | wx.redirectTo({ url: "/" + page.__route__ });
34 | } else {
35 | wx.showToast({ title: "获取“摄像头”权限失败!", icon: "none" });
36 | }
37 | },
38 | });
39 | },
40 | });
41 | }
42 |
43 | export function requestFile(url) {
44 | return new Promise((resolve, reject) => {
45 | wx.request({
46 | url,
47 | dataType: "",
48 | responseType: "arraybuffer",
49 | success({ statusCode, data }) {
50 | if (statusCode === 200) {
51 | resolve(data);
52 | } else {
53 | reject(new Error(`下载素材(${url})发生错误(状态码-${statusCode})`));
54 | }
55 | },
56 | fail: reject,
57 | });
58 | });
59 | }
60 |
61 | export function downloadFile(url) {
62 | return new Promise((resolve, reject) => {
63 | wx.downloadFile({
64 | url,
65 | success({ statusCode, tempFilePath }) {
66 | if (statusCode === 200) {
67 | resolve(tempFilePath);
68 | } else {
69 | reject(new Error(`下载文件:${url} 失败。statusCode:${statusCode}`));
70 | }
71 | },
72 | fail: reject,
73 | });
74 | });
75 | }
76 |
77 | function openCameraSetting(callback = () => {}) {
78 | wx.showModal({
79 | title: "提示",
80 | content: "请给予“摄像头”权限,并开始体验。",
81 | showCancel: false,
82 | success() {
83 | wx.openSetting({
84 | success({ authSetting: { "scope.camera": isGrantedCamera } }) {
85 | if (isGrantedCamera) {
86 | callback();
87 | } else {
88 | openCameraSetting(callback);
89 | }
90 | },
91 | });
92 | },
93 | });
94 | }
95 |
96 | // 获取摄像头的权限,直到成功后才会跳出
97 | export function getCameraAuth() {
98 | return new Promise((resolve) => {
99 | wx.authorize({
100 | scope: "scope.camera",
101 | success: () => {
102 | resolve();
103 | },
104 | fail: () => {
105 | openCameraSetting(resolve);
106 | },
107 | });
108 | });
109 | }
110 |
111 | export function compareVersion(v1, v2) {
112 | v1 = v1.split('.')
113 | v2 = v2.split('.')
114 | var len = Math.max(v1.length, v2.length)
115 |
116 | while (v1.length < len) {
117 | v1.push('0')
118 | }
119 | while (v2.length < len) {
120 | v2.push('0')
121 | }
122 |
123 | for (var i = 0; i < len; i++) {
124 | var num1 = parseInt(v1[i])
125 | var num2 = parseInt(v2[i])
126 |
127 | if (num1 > num2) {
128 | return 1
129 | } else if (num1 < num2) {
130 | return -1
131 | }
132 | }
133 | return 0
134 | }
135 |
136 | export function getSlamV2Support() {
137 | // 注意:目前只有iOS设备,微信版本>=8.0.17且基础库>=2.22.0才支持v2版本。 插件版本>=1.3.0支持
138 | console.warn(wx.getSystemInfoSync())
139 | const {system, SDKVersion, version} = wx.getSystemInfoSync();
140 | const isIos = system.toLowerCase().includes("ios");
141 | if(isIos && compareVersion(version, "8.0.17") >= 0 && compareVersion(SDKVersion, "2.22.0") >= 0) {
142 | return true;
143 | }
144 | return false;
145 | }
146 |
147 | export function getPrivate() {
148 | if (wx.requirePrivacyAuthorize) {
149 | return new Promise((resolve, reject) => {
150 | wx.requirePrivacyAuthorize({
151 | success: (res) => {
152 | console.log("用户同意了隐私协议");
153 | resolve(res);
154 | },
155 | fail: (res) => {
156 | reject(res);
157 | console.log("用户拒绝了隐私协议");
158 | },
159 | });
160 | });
161 | } else {
162 | return Promise.resolve();
163 | }
164 | }
--------------------------------------------------------------------------------
/pages/index/Food.js:
--------------------------------------------------------------------------------
1 | import { requestFile, downloadFile, resUrl } from "../../utils/util";
2 | import { getTimeLevel } from "../../utils/stats";
3 |
4 | class Food {
5 | constructor() {}
6 |
7 | /**
8 | * 下载场景必要素材
9 | * @return Promise
10 | * @memberof Food
11 | */
12 | loadAssets() {
13 | if (this.downloadAssets) {
14 | return this.downloadAssets;
15 | }
16 | const downloadStartTime = Date.now();
17 |
18 | this.downloadAssets = Promise.all([
19 | requestFile(resUrl("models/beef.glb")),
20 | requestFile(resUrl("hdr/default.hdr")),
21 | downloadFile(resUrl("models/point.mp4")),
22 | downloadFile(resUrl("models/fire.mp4")),
23 | ]).then((res) => {
24 | this.assetDownloadDuration = getTimeLevel(downloadStartTime); // 统计下载持续时间
25 | return res;
26 | });
27 |
28 | return this.downloadAssets;
29 | }
30 |
31 | /**
32 | * 初始化场景和模型,但此时还没有将模型加入到场景内。
33 | * 只能在slam组件ready后使用
34 | * @param {*} slam 传入的slam对象
35 | * @memberof Food
36 | */
37 | async initScene(slam) {
38 | try {
39 | const [
40 | modelArrayBuffer,
41 | envMapArrayBuffer,
42 | planeAlphaVideoPath,
43 | fireAlphaVideoPath,
44 | ] = await this.loadAssets();
45 |
46 | const modelLoadStartTime = Date.now();
47 |
48 | // 当视频因为特殊原因不能显示时,会使用此处指定的缩略图展示。为空则降级缩略图功能无效。
49 | const defaultThumbnailUrl = "";
50 | const [beef, envMap, indicatorModel, fireModel] = await Promise.all([
51 | slam.createGltfModel(modelArrayBuffer),
52 | slam.createEnvMapByHDR(envMapArrayBuffer),
53 | slam.createAlphaVideo(planeAlphaVideoPath, defaultThumbnailUrl),
54 | slam.createAlphaVideo(fireAlphaVideoPath, defaultThumbnailUrl),
55 | ]);
56 |
57 | const assetLoadDuration = getTimeLevel(modelLoadStartTime);
58 |
59 | // 模型使用上环境贴图,可加强真实效果。实物类模型推荐使用。
60 | beef.useEnvMap(envMap);
61 |
62 | // 开启模型投射阴影属性是否投射。true为开启投射,false为关闭投射。
63 | beef.setCastShadow(true);
64 |
65 | fireModel.loop = true; // 设置为循环播放
66 | fireModel.position.set(0, 1, 0);
67 | fireModel.scale.setScalar(0.5);
68 |
69 | this.beef = beef;
70 | this.fire = fireModel;
71 |
72 | // 创建一个模型组
73 | const group = slam.createGroup();
74 | group.add(beef);
75 | group.add(fireModel);
76 |
77 | // v2版本放置到空间中的模型大小更精准,这里需要做下处理
78 | const initScale = slam.isSlamV2() ? 0.23 : 0.75;
79 | const initRotation = 0; // 角度
80 | /**
81 | * 将创建好的3D对象,放入组件之中显示。
82 | * @param {Base3D} base3D - 3D对象
83 | * @param {Number} [scale=0] - 3D对象初始大小,0代表不指定大小,使用模型原始大小。单位“米”,默认值为0。注意:此大小仅供参考,不能视作精准值,会存在一定的误差。
84 | * @param {Number} [rotation=0] - 3D对象初始Y轴旋转朝向,0代表不进行旋转。单位“角度”,默认值为0。
85 | * @returns {void}
86 | */
87 | slam.add(group, initScale, initRotation);
88 |
89 | group.visible = false; // 在没有将模型放到平面前需要先隐藏模型
90 |
91 | // 让模型可用手势进行操作。默认点击移动到平面上的新位置,单指旋转,双指缩放。
92 | slam.setGesture(group);
93 |
94 | this.model = group;
95 |
96 | // 增加指示器
97 | indicatorModel.name = "indicatorModel";
98 | indicatorModel.loop = true; // 设置为循环播放
99 | const indicatorScale = slam.isSlamV2() ? 0.075 : 0.25;
100 | indicatorModel.scale.setScalar(indicatorScale);
101 |
102 | /**
103 | * 此指示器模型使用的是透明视频模型,
104 | * 透明视频模型默认是垂直于Z轴,所以需要旋转为平方状态
105 | * **/
106 | indicatorModel.rotation.x = Math.PI / 2;
107 |
108 | // 由于slam放置时内部会改变模型的旋转,所以这里使用一个父级group进行包裹
109 | const indicatorGroup = slam.createGroup();
110 | indicatorGroup.add(indicatorModel);
111 |
112 | this.indicatorModel = indicatorGroup;
113 |
114 | slam.enableShadow(); // 开启阴影功能
115 | await slam.start();
116 |
117 | this.slam = slam;
118 |
119 | return {
120 | assetDownloadDuration: this.assetDownloadDuration,
121 | assetLoadDuration,
122 | };
123 | } catch (e) {
124 | throw new Error(e.message);
125 | }
126 | }
127 |
128 | /**
129 | * 找平面
130 | * @memberof Food
131 | */
132 | findPlane() {
133 | const { slam, indicatorModel } = this;
134 | // 增加一个3d素材作为平面指示器显示。
135 | slam.addPlaneIndicator(indicatorModel, {
136 | // camera画面中心,可以映射到平面上某一个点时调用
137 | onPlaneShow() {
138 | // console.log("指示器出现");
139 | },
140 | // camera画面中心,**不可以**映射到平面上某一个点时调用。
141 | onPlaneHide() {
142 | // console.log("指示器隐藏");
143 | },
144 | // camera画面中心,可以映射到平面上某一个点时,**持续**调用。
145 | // 因此可以用此方法,让指示器旋转起来。
146 | onPlaneShowing() {},
147 | });
148 |
149 | // indicatorModel.videoContext.play();
150 | indicatorModel.visible = true;
151 | }
152 |
153 | /**
154 | * 开始场景,将设定好的模型加入到场景内
155 | * @memberof Food
156 | */
157 | startScene() {
158 | const { slam, model, indicatorModel, beef, fire } = this;
159 |
160 | // 注意:只有开启slam平面追踪(slam.start())之后,才能让模型去尝试站在平面上。
161 | const { windowWidth, windowHeight } = wx.getSystemInfoSync();
162 | // 主动让模型站在屏幕中心映射到平面上的位置点。
163 | // 此处组件全屏展示,所以窗口宽度除以2
164 | const x = Math.round(windowWidth / 2);
165 | // 此处组件全屏展示,所以窗口高度除以2
166 | const y = Math.round(windowHeight / 2);
167 | // 首次调用standOnThePlane,resetPlane参数必须设为true,以便确定一个平面。
168 | // 如果为false,代表使用已经检测到的平面。默认为true。
169 | const resetPlane = true;
170 | /**
171 | * 让3D素材对象,站立在检测出来的平面之上。
172 | * @param {Base3D} base3D - 3D对象
173 | * @param {Number} x - kivicube-slam组件上的x轴横向坐标点
174 | * @param {Number} y - kivicube-slam组件上的y轴纵向坐标点
175 | * @param {Boolean} [resetPlane=true] - 是否重置平面。
176 | * @returns {Boolean} 是否成功站立在平面上
177 | */
178 | const success = slam.standOnThePlane(model, x, y, resetPlane);
179 |
180 | if (!success) {
181 | // 如果返回false,代表尝试站在平面上失败。有可能是平面检测失败。
182 | throw new Error("find plane failed");
183 | }
184 |
185 | // indicatorModel.videoContext.stop();
186 | slam.removePlaneIndicator(); // 移除指示器
187 |
188 | model.visible = true;
189 |
190 | beef.playAnimation({
191 | animationName: "start",
192 | loop: false, // 是否循环播放
193 | });
194 |
195 | // 播放牛排的动画
196 | beef.playAnimation({ animationName: "loop", loop: true });
197 |
198 | fire.videoContext.play();
199 |
200 | // 模型动画监听
201 | beef.addEventListener("animationEnded", (e) => {
202 | if (e.animationName === "start") {
203 | beef.stopAnimation("start");
204 | beef.playAnimation({ animationName: "loop2", loop: true });
205 | }
206 | });
207 | }
208 |
209 | // 清理
210 | clear() {
211 | this.slam = null;
212 | this.model = null;
213 | this.downloadAssets = null;
214 | }
215 | }
216 |
217 | export default Food;
218 |
--------------------------------------------------------------------------------
/miniprogram_npm/umtrack-wx/index.js:
--------------------------------------------------------------------------------
1 | "use strict";var e="[UMENG] -- ",t=function(){var t=null,n=!1;function i(){this.setDebug=function(e){n=e};this.d=function(){if(n)try{"string"==typeof arguments[0]&&(arguments[0]=e+arguments[0]);console.debug.apply(console,arguments)}catch(e){}};this.i=function(){try{if(n)try{"string"==typeof arguments[0]&&(arguments[0]=e+arguments[0]);console.info.apply(console,arguments)}catch(e){}}catch(e){}};this.e=function(){if(n)try{"string"==typeof arguments[0]&&(arguments[0]=e+arguments[0]);console.error.apply(console,arguments)}catch(e){}};this.w=function(){if(n)try{"string"==typeof arguments[0]&&(arguments[0]=e+arguments[0]);console.warn.apply(console,arguments)}catch(e){}};this.v=function(){if(n)try{"string"==typeof arguments[0]&&(arguments[0]=e+arguments[0]);console.log.apply(console,arguments)}catch(e){}};this.t=function(){if(n)try{console.table.apply(console,arguments)}catch(e){}};this.tip=function(){try{"string"==typeof arguments[0]&&(arguments[0]=e+arguments[0]);console.log.apply(console,arguments)}catch(e){}};this.tip_w=function(e){try{console.log("%c [UMENG] -- "+e,"background:red; padding: 4px; padding-right: 8px; border-radius: 4px; color: #fff;")}catch(e){}};this.err=function(){try{"string"==typeof arguments[0]&&(arguments[0]=e+arguments[0]);console.error.apply(console,arguments)}catch(e){}};this.repeat=function(e){for(var t=e;t.length<86;)t+=e;return t}}return function(){null===t&&(t=new i);return t}}(),n=function(){var e=null;function t(){var e={};this.useOpenid=function(){return!!e.useOpenid};this.useSwanid=function(){return!!e.useSwanid};this.autoGetOpenid=function(){return!!e.autoGetOpenid};this.appKey=function(){return e.appKey};this.uploadUserInfo=function(){return e.uploadUserInfo};this.enableVerify=function(){return e.enableVerify};this.set=function(t){e=t};this.get=function(){return e};this.setItem=function(t,n){e[t]=n};this.getItem=function(t){return e[t]}}return function(){e||(e=new t);return e}}();function i(){}i.prototype={on:function(e,t,n){var i=this.e||(this.e={});(i[e]||(i[e]=[])).push({fn:t,ctx:n});return this},once:function(e,t,n){var i=this;function r(){i.off(e,r);t.apply(n,arguments)}r._=t;return this.on(e,r,n)},emit:function(e){for(var t=[].slice.call(arguments,1),n=((this.e||(this.e={}))[e]||[]).slice(),i=0,r=n.length;is?o+"*"+s:s+"*"+o;"function"==typeof e&&e(i)},fail:function(){"function"==typeof e&&e()}})};e.prototype.getDeviceInfo=function(e){"function"==typeof e&&e("")};e.prototype.checkNetworkAvailable=function(e){wx.getNetworkType({success:function(t){"function"==typeof e&&e(t&&"none"!==t.networkType)},fail:function(){"function"==typeof e&&e(!1)}})};e.prototype.getNetworkInfo=function(e){wx.getNetworkType({success:function(t){"function"==typeof e&&e({networkAvailable:"none"!==t.networkType,networkType:t.networkType})},fail:function(){"function"==typeof e&&e()}})};e.prototype.getDeviceId=function(e){e("")};e.prototype.getAdvertisingId=function(e){"function"==typeof e&&e("")};e.prototype.onNetworkStatusChange=function(e){wx.onNetworkStatusChange((function(t){"function"==typeof e&&e(t.isConnected)}))};e.prototype.request=function(e){var t=e.success,n=e.fail,i=!1,r=null;e.success=function(e){if(!i){r&&clearTimeout(r);"function"==typeof t&&t(e)}};e.fail=function(){if(!i){r&&clearTimeout(r);"function"==typeof n&&n(!1)}};wx.request(e);r=setTimeout((function(){r&&clearTimeout(r);i=!0;"function"==typeof n&&n(i)}),e.timeout||5e3)};e.prototype.getSdkType=function(){return"wxmp"};e.prototype.getPlatform=function(){return"wx"};e.prototype.getUserInfo=function(e){e()};e.prototype.getAppInfoSync=function(){if(wx.getAccountInfoSync){var e=wx.getAccountInfoSync(),t=e&&e.miniProgram?e.miniProgram:{};return{appId:t.appId,appEnv:t.envVersion,appVersion:t.version}}return{}};e.prototype.onShareAppMessage=function(e){wx.onShareAppMessage(e)};e.prototype.shareAppMessage=function(e){wx.shareAppMessage(e)};e.prototype.getLaunchOptionsSync=function(){var e=null;if(e)return e;if(!wx.getLaunchOptionsSync)return{};try{e=wx.getLaunchOptionsSync()}catch(t){e=null}return e||{}};return e}()),s=function(e,t){return(s=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function a(e,t){s(e,t);function n(){this.constructor=e}e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var u={SESSION_INTERVAL:3e4,LOG_URL:"/wxm_logs",GET_OPENID_URL:"/uminiprogram_logs/wx/getuut",USERINFO_URL:"/uminiprogram_logs/comm/uif",ENDPOINT:"https://umini.shujupie.com",ENDPOINTB:"https://ulogs.umeng.com",DEVICE_INFO_KEY:"device_info",ADVERTISING_ID:"mobile_ad_id",ANDROID_ID:"android_id",CURRENT_SESSION:"current_session",SESSION_PAUSE_TIME:"session_pause_time",EVENT_SEND_DEFAULT_INTERVAL:15e3,EVENT_LAST_SEND_TIME:"last_send_time",MAX_EVENTID_LENGTH:128,MAX_PROPERTY_KEY_LENGTH:256,MAX_PROPERTY_KEYS_COUNT:100,REPORT_POLICY:"report_policy",REPORT_INTERVAL_TIME:"report_interval_time",REPORT_POLICY_START_SEND:"1",REPORT_POLICY_INTERVAL:"6",IMPRINT:"imprint",SEED_VERSION:"1.0.0",IMPL_VERSION:"2.7.1",ALIPAY_AVAILABLE_VERSION:"10.1.52",SHARE_PATH:"um_share_path",SHARES:"shares",REQUESTS:"requests",UUID:"um_uuid",UUID_SUFFIX:"ud",OPENID:"um_od",UNIONID:"um_unid",ALIPAYID:"um_alipayid",USERID:"um_userid",PROVIDER:"um_provider",SWANID:"um_swanid",ANONYMOUSID:"um_anonymousid",LAUNCH_OPTIONS:"LAUNCH_OPTIONS",UM_SSRC:"_um_ssrc",USER_INFO:"user_info",IS_ALIYUN:!1};var c,f={isNumber:function(e){return!Number.isNaN(parseInt(e,10))},compareVersion:function(e,t){for(var n=String(e).split("."),i=String(t).split("."),r=0;rs)return 1;if(oe.length)&&e.substr(0,t.length)===t},endsWith:function(e,t){return!(!t||0===e.length||t.length>e.length)&&e.substring(e.length-t.length)===t},assign:function(e){if(null==e)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(e),n=1;n1&&f.startsWith(o.path,"/")&&(o.path=f.trimStart(o.path,"/"));var s=e.path||"",a=l().getId();if(a){var u=i.split(","),c=(u=u.filter((function(e){return e.length>0}))).indexOf(a);c>=0&&(u=u.slice(0,c));u.length<3&&u.push(a);var p=u.join(",");-1!==s.indexOf("?")?s+="&_um_ssrc="+p:s+="?_um_ssrc="+p;var h=Date.now();s+="&_um_sts="+h;if(r){var g=function(e){var t=[];for(var n in e)"_um_ssrc"!==n&&"_um_sts"!==n&&t.push(n+"="+e[n]);return t.join("&")}(d),v=g?g+"&_um_ssrc="+p+"&_um_sts="+h:"_um_ssrc="+p+"&_um_sts="+h;e.query=e.query?e.query+"&_um_ssrc="+p+"&_um_sts="+h:v}else e.path=s;o._um_ssrc=p;o._um_sts=h}n.push(o);t().v("share: %o",e);return e},setShareSource:function(e){i=e},clear:function(){n.length=0},get:function(){return n}}}return function(){e||(e=new r);return e}}(),v=function(e){if(e)try{return JSON.stringify(e)}catch(e){}return""},_=function(e){if(e)try{return JSON.parse(e)}catch(e){}return null},y=function(){var e=null,t="",i=null,r=!1;function s(){this.load=function(e){if(i){o.removeStorage(t);e()}else{t="um_cache_"+n().appKey();o.getStorage(t,(function(n){i=_(n)||{};r=!0;o.removeStorage(t);e()}))}};this.save=function(){i&&o.setStorage(t,v(i))};this.set=function(e,t){i&&(i[e]=t)};this.get=function(e){return(i||{})[e]};this.remove=function(e){i&&i[e]&&delete i[e]};this.getAll=function(){return i};this.clear=function(){i=null};this.has=function(e){return!!this.get(e)};this.isLoaded=function(){return r}}return function(){e||(e=new s);return e}}(),m=function(){var e,n,i=[],r=[];function o(){if(i.length){var e=y().get("ekvs");if(function(e){var t=0;for(var n in e)Array.isArray(e[n])&&(t+=e[n].length);return t}(e)+i.length<=1e4){e=s(e,i);y().set("ekvs",e)}}}function s(e,t){var i=(e=e||{})[n];Array.isArray(i)&&i.length?e[n]=i.concat(t):e[n]=[].concat(t);return e}return function(){e||(e={addEvent:function(e){if(n){i.unshift(e);if(i.length>1){o();i.length=0}}else{t().w("session id is null: ",n);r.unshift(e)}},setSessionId:function(e){n=e;t().v("setSessionId: ",n);if(Array.isArray(r)&&r.length&&n){for(var i=0;iu.SESSION_INTERVAL){r=!0;!function(e){try{var n=(i||{}).options||{},r=f.assign({},function(e){var n={};for(var i in e)0===i.indexOf("_um_")&&(n[i]=e[i]);t().v("query: ",e);t().v("_um_params: ",n);return n}(e.query));r.path=e.path||n.path;r.scene=e.scene?o.getPlatform()+"_"+e.scene:n.scene;var s=e.referrerInfo;s&&(r.referrerAppId=s.appId);t().v("session options: ",r);var a=r[u.UM_SSRC];a&&g().setShareSource(a);var c=Date.now();i={id:f.getRandomStr(10)+c,start_time:c,options:r}}catch(e){t().e("生成新session失败: ",e)}}(e);t().v("开始新的session(%s): ",i.id,i)}else t().v("延续上一次session(%s): %s ",i.id,s.toLocaleTimeString(),i);return r},pause:function(){!function(){if(i){var e=new Date;i.end_time=e.getTime();"number"!=typeof i.duration&&(i.duration=0);i.duration=i.end_time-n;y().set(u.CURRENT_SESSION,i);t().v("退出会话(%s): %s ",i.id,e.toLocaleTimeString(),i)}}()},getCurrentSessionId:function(){return(i||{}).id},getCurrentSession:function(){return i},cloneCurrentSession:function(){return f.clone(i)}}}return function(){e||(e=r());return e}}();function b(e){var t=null;switch(e){case O:t=function(){var e=null,t=k().cloneCurrentSession();t&&(e={header:{st:"1"},analytics:{sessions:[t]}});return e}();break;case E:t=function(){var e=null,t={},n=k().cloneCurrentSession();if(n){var i=h().get(),r=g().get();Array.isArray(i)&&i.length&&(n.pages=f.clone(i));Array.isArray(r)&&r.length&&(n.shares=f.clone(r));h().clear();g().clear();t.sessions=[n]}var o=m().getEkvs();if(o){t.ekvs=f.clone(o);m().clear()}(t.sessions||t.ekvs)&&(e={analytics:t});return e}();break;case N:t=function(){var e=null,t=m().getEkvs();if(t){e={analytics:{ekvs:f.clone(t)}};m().clear()}return e}()}return t}var D={sessions:"sn",ekvs:"e",active_user:"active_user"},U={sdk_type:"sdt",access:"ac",access_subtype:"acs",device_model:"dm",language:"lang",device_type:"dt",device_manufacturer:"dmf",device_name:"dn",platform_version:"pv",id_type:"it",font_size_setting:"fss",os_version:"ov",device_manuid:"did",platform_sdk_version:"psv",device_brand:"db",appkey:"ak",_id:"id",id_tracking:"itr",imprint:"imp",sdk_version:"sv",resolution:"rl",testToken:"ttn",theme:"t5",benchmark_level:"bml",screen_width:"sw",screen_height:"sh",status_bar_height:"sbh",safe_area_top:"sat",safe_area_left:"sal",safe_area_right:"sar",safe_area_bottom:"sab",safe_area_height:"sah",safe_area_width:"saw",pixel_ratio:"pr",storage:"s7",host:"hs"},P={uuid:"ud",unionid:"und",openid:"od",anonymousid:"nd",alipay_id:"ad",device_id:"dd",userid:"puid"};function R(e,t){var n=C(e,t);e&&e.id_tracking&&(n[t.id_tracking||"id_tracking"]=C(e.id_tracking,P));return n}function C(e,t){var n={};for(var i in e)t[i]?n[t[i]]=e[i]:n[i]=e[i];return n}function L(e,t){var n={};if(e)for(var i in e)e[i]&&(n[t[i]]=e[i]);return n}var M="";function x(){return M}var V="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",j=function(e){for(var t={},n=0,i=e.length;n>>6)+F(128|63&t):F(224|t>>>12&15)+F(128|t>>>6&63)+F(128|63&t)}var t=65536+1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320);return F(240|t>>>18&7)+F(128|t>>>12&63)+F(128|t>>>6&63)+F(128|63&t)},q=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,K=function(e){var t=[0,2,1][e.length%3],n=e.charCodeAt(0)<<16|(e.length>1?e.charCodeAt(1):0)<<8|(e.length>2?e.charCodeAt(2):0);return[V.charAt(n>>>18),V.charAt(n>>>12&63),t>=2?"=":V.charAt(n>>>6&63),t>=1?"=":V.charAt(63&n)].join("")},H=function(e){return function(e){return e.replace(q,G)}(e).replace(/[\s\S]{1,3}/g,K)},Y=new RegExp(["[À-ß][-¿]","[à-ï][-¿]{2}","[ð-÷][-¿]{3}"].join("|"),"g"),J=function(e){switch(e.length){case 4:var t=((7&e.charCodeAt(0))<<18|(63&e.charCodeAt(1))<<12|(63&e.charCodeAt(2))<<6|63&e.charCodeAt(3))-65536;return F(55296+(t>>>10))+F(56320+(1023&t));case 3:return F((15&e.charCodeAt(0))<<12|(63&e.charCodeAt(1))<<6|63&e.charCodeAt(2));default:return F((31&e.charCodeAt(0))<<6|63&e.charCodeAt(1))}},B=function(e){var t=e.length,n=t%4,i=(t>0?j[e.charAt(0)]<<18:0)|(t>1?j[e.charAt(1)]<<12:0)|(t>2?j[e.charAt(2)]<<6:0)|(t>3?j[e.charAt(3)]:0),r=[F(i>>>16),F(i>>>8&255),F(255&i)];r.length-=[0,0,2,1][n];return r.join("")},X=function(e){return function(e){return e.replace(/[\s\S]{1,4}/g,B)}(e).replace(Y,J)},W=function(e,t){return t?H(String(e)).replace(/[+\/]/g,(function(e){return"+"==e?"-":"_"})).replace(/=/g,""):H(String(e))},z=function(e){return X(String(e).replace(/[-_]/g,(function(e){return"-"==e?"+":"/"})).replace(/[^A-Za-z0-9\+\/]/g,""))};var Q=new function(){var e="",t=this;this.set=function(t){e=t};this.get=function(){return e};this.getImpObj=function(){return _(z(e))};this.getItem=function(e){var n=t.getImpObj();return n&&n[e]||""};this.load=function(){e=y().get(u.IMPRINT)};this.save=function(){e&&y().set(u.IMPRINT,e)}};function Z(e,n,i,r){w.instance().setIdType(l().getIdType());w.instance().setIdTracking(l().getIdTracking());var s=l().getUserId();s&&e.analytics&&(e.analytics.active_user={puid:s,provider:l().getProvider()});var a=f.clone(w.instance().get());e.header=f.assign(a,e.header,{ts:Date.now(),testToken:x(),traceId:f.getRandomStr(10)+Date.now()+f.getRandomStr(9)});var c,p=function(e){return{h:R(e.header,U),a:L(e.analytics,D)}}(e),h=v(p),d={url:u.ENDPOINT+u.LOG_URL,method:"POST",data:W(h),success:function(r){var o=r.code||r.status||r.statusCode;if(200===o||413===o){t().i("数据发送成功: ",e,h);!function(e){if(e){w.instance().setItem(u.IMPRINT,e);Q.set(e);Q.save();t().v("imprint: ",Q.getImpObj());Q.getItem("ttn_invalid")&&(M="")}}((r.data||{}).imprint);"function"==typeof n&&n(r)}else{t().w("数据发送失败: ",h);"function"==typeof i&&i()}},fail:function(e){t().w("超时: ",h);"function"==typeof i&&i()},complete:function(){"function"==typeof r&&r()}};o.request(f.assign(d,{header:{"Content-Type":c=o.getSdkType()+"/json","Msg-Type":c}}))}function $(e){var t=e,n=[];this.enqueue=function(e){"number"==typeof t&&this.size()>=t&&this.dequeue();n.push(e)};this.dequeue=function(){return n.shift()};this.front=function(){return n[0]};this.isEmpty=function(){return 0===n.length};this.clear=function(){n.length=0};this.size=function(){return n.length};this.items=function(){return n};this.print=function(){console.log(n.toString())}}var ee=function(){var e=null,n=!1,i=[],r=new $(50);function o(e,t,n){if(w.instance().isLoaded()){t=t||{};var i=b(e);if(i){var s=w.instance().getRealtimeFields();i.header=f.assign({},i.header,s);i.noCache=t.noCache;r.enqueue(i)}"function"==typeof n&&n()}else setTimeout((function(){o(e,t,n)}),100)}function s(e){var t=r.front();if(t)Z(t,(function(){r.dequeue();s(e)}),(function(){var t=r.dequeue();t&&!t.noCache&&i.push(t);s(e)}));else{!function(){i.forEach((function(e){r.enqueue(e)}));i.length=0}();e()}}function a(e){if(l().getId())if(n)t().i("队列正在发送中");else{n=!0;s((function(){n=!1;"function"==typeof e&&e()}))}else{t().i("获取id标识失败,暂缓发送");"function"==typeof e&&e()}}function c(){this.send=function(e,t,n){e?this.add(e,t,(function(){a(n)})):a(n)};this.add=function(e,t,n){o(e,t,n)};this.load=function(){var e=y().get(u.REQUESTS);e&&e.length&&e.forEach((function(e){r.enqueue(e)}));y().remove(u.REQUESTS)};this.save=function(){y().set(u.REQUESTS,f.clone(r.items()));r.clear()}}return function(){e||(e=new c);return e}}(),te=function(){var e=null,i=null;function r(){this.setUserInfo=function(e){i=e};this.update=function(){e(i)||o.getUserInfo((function(t){e(t)}))};function e(e){if(e&&"object"==typeof e){var i=y().get(u.USER_INFO);i&&f.deepEqual(e,i)||function(e,i){var r=n().appKey(),s=o.getSdkType(),a=l().getId(),c=l().getIdType();if(!(r&&s&&a&&c))return;var f={ak:n().appKey(),sdt:o.getSdkType(),uin:e.nickName,uia:e.avatar||e.avatarUrl,uig:e.gender,uit:e.country,uip:e.province,uic:e.city,uil:e.language,id:l().getId(),it:l().getIdType(),age:e.age,cln:e.constellation},p=JSON.stringify(f);p=W(p);o.request({url:u.ENDPOINT+u.USERINFO_URL,method:"POST",header:{"content-type":"application/x-www-form-urlencoded"},data:"ui="+p,success:function(n){t().v("用户信息上传成功: ",e);i&&i(n&&n.data&&200===n.data.code)},fail:function(){t().e("用户信息上传失败: ",e);i&&i(!1)}})}(e,(function(t){t&&y().set(u.USER_INFO,e)}));return!0}return!1}}return function(){e||(e=new r);return e}}();function ne(e,t){this.id=e;this.ts=Date.now();var n=typeof t;if("string"===n&&t)this[e]=t;else if("object"===n)for(var i in t)({}).hasOwnProperty.call(t,i)&&(this[i]=t[i])}function ie(){var e=!1,i=!1,r=0;this.init=function(i){t().v("sdk version: "+u.IMPL_VERSION);e?t().v("Lib重复实例化"):y().load((function(){t().v("cache初始化成功: ",y().getAll());!function(){l().setUseOpenid&&l().setUseOpenid(n().useOpenid());l().init((function(){w.instance().init();t().v("Header初始化成功")}))}();e=!0;"function"==typeof i&&i();t().tip("SDK集成成功")}))};this.resume=function(r){if(e&&!i){t().v("showOptions: ",r);var o;i=!0;n().enableVerify()&&r&&r.query&&(o=r.query._ttn,M=o||M);this._resume(r)}};this._resume=function(e){ee().load();var i=k().resume(e),r=k().getCurrentSessionId();m().setSessionId(r);i&&ee().add(O,{},(function(){l().setUseOpenid&&l().setUseOpenid(n().useOpenid());if(n().useOpenid()&&n().autoGetOpenid()&&!l().getId()){t().v("get id async");o(10,3e3)}else{t().v("session auto send");ee().send()}}));function o(e,i){l().getId()||e<=0||l().getOpenIdAsync(n().appKey(),(function(n){if(n){t().v("获取id成功");ee().send()}else{t().v("获取openid失败,启动重试,剩余可用次数",e-1);setTimeout((function(){o(e-1,i)}),i)}}))}};this.pause=function(o){if(e){i=!1;r=0;k().pause();n().uploadUserInfo()&&te().update();ee().send(E,{},(function(){ee().save();y().save();t().v("cache save success");"function"==typeof o&&o()}))}};this.setOpenid=function(e){t().v("setOpenId: %s",e);l().setOpenid(e);ee().send()};this.setUnionid=function(e){t().v("setUnionid: %s",e);l().setUnionid(e)};this.setUserid=function(e,n){t().v("setUserid: %s",e,n);l().setUserid(e,n)};this.setUserInfo=function(e){t().v("setUserInfo: %s",e);te().setUserInfo(e)};this.setAnonymousid=function(e){t().v("setAnonymousId: %s",e);l().setAnonymousid(e);ee().send()};this.setAppVersion=function(e){e&&"string"!=typeof e?t().w("setAppVersion方法只接受字符串类型参数"):w.instance().setAppVersion(e)};this.setAlipayUserid=function(e){if(e&&"string"!=typeof e)t().w("setAlipayUserid方法只接受字符串类型参数");else{t().v("setAlipayUserid: %s",e);l().setAlipayUserid(e)}};this.setDeviceId=function(e){if("string"==typeof e){l().setDeviceId(e);return e}};this.setSuperProperty=function(e){if(e&&"string"!=typeof e)t().w("超级属性只支持字符串类型");else{var n=this;if(w.instance().getSuperProperty()!==e){w.instance().setSuperProperty(e);n.pause((function(){n.resume()}))}}};this.trackEvent=function(n,i){if(e){t().v("event: ",n,i);if(function(e,n){if(!e||"string"!=typeof e){t().e('please check trackEvent id. id should be "string" and not null');return!1}var i=["id","ts","du"],r={};i.forEach((function(e){r[e]=1}));if(r[e]){t().e("eventId不能与以下保留字冲突: "+i.join(","));return!1}if(e.length>u.MAX_EVENTID_LENGTH){t().e("The maximum length of event id shall not exceed "+u.MAX_EVENTID_LENGTH);return!1}if(n&&("object"!=typeof n||Array.isArray(n))&&"string"!=typeof n){t().e("please check trackEvent properties. properties should be string or object(not include Array)");return!1}if("object"==typeof n){var o=0;for(var s in n)if({}.hasOwnProperty.call(n,s)){if(s.length>u.MAX_PROPERTY_KEY_LENGTH){t().e("The maximum length of property key shall not exceed "+u.MAX_PROPERTY_KEY_LENGTH);return!1}if(o>=u.MAX_PROPERTY_KEYS_COUNT){t().e("The maximum count of properties shall not exceed "+u.MAX_PROPERTY_KEYS_COUNT);return!1}if(r[s]){t().e("属性中的key不能与以下保留字冲突: "+i.join(","));return!1}o+=1}}return!0}(n,i)){var o=new ne(n,i);m().addEvent(o);var s=!!x(),a=s?0:u.EVENT_SEND_DEFAULT_INTERVAL,c=Date.now();if(function(e,t){return"number"!=typeof r||"number"!=typeof t||r<=0||e-r>t}(c,a)){r=c;ee().send(N,{noCache:s},(function(){}))}}}};this.trackShare=function(n){if(e)try{if(o.getSdkType().indexOf("game")>-1){n=g().add(n,!0);t().v("shareQuery: ",n)}else{n=g().add(n,!1);t().v("sharePath: ",n.path)}}catch(e){t().v("shareAppMessage: ",e)}return n};this.trackPageStart=function(t){e&&h().addPageStart(t)};this.trackPageEnd=function(t){e&&h().addPageEnd(t)};this.onShareAppMessage=function(e){var t=this;o.onShareAppMessage((function(){return t.trackShare(e())}))};this.shareAppMessage=function(e){this.trackShare(e);o.shareAppMessage(e)}}var re=[];function oe(){}oe.prototype={createMethod:function(e,n,i){try{e[n]=i&&i[n]?function(){return i[n].apply(i,arguments)}:function(){re.push([n,[].slice.call(arguments)])}}catch(e){t().v("create method errror: ",e)}},installApi:function(e,n){try{var i,r,o="resume,pause,trackEvent,trackPageStart,trackPageEnd,trackShare,setUserid,setOpenid,setUnionid,setSuperProperty,setUserInfo".split(",");for(i=0,r=o.length;i=se.length||n){n&&(r=i,u.ENDPOINT=r);n&&t().v("命中可用服务",i);!n&&t().tip_w("未命中可用服务");return!1}o.request({url:u.ENDPOINT+"/uminiprogram_logs/ckdh",success:function(t){200===(t.code||t.status||t.statusCode)&&t.data&&200===t.data.code?ae(e+1,!0):ae(e+1,!1)},fail:function(){ae(e+1,!1)}})}({init:function(e){u.ENDPOINTB&&setTimeout((function(){ae(0,!1)}),e)}}).init(3e3);var ue=new oe,ce={_inited:!1,_log:t(),preinit:function(e){if(e&&"object"==typeof e)for(var t in e)u[t]=e[t];return u},use:function(e,t){e&&f.isFunction(e.install)?e.install(ce,t):f.isFunction(e)&&e(ce,t);return ce},messager:r,init:function(e){if(this._inited)t().v("已经实例过,请避免重复初始化");else if(e)if(e.appKey){"boolean"!=typeof e.useOpenid&&(e.useOpenid=!0);n().set(e);t().setDebug(e.debug);this._inited=!0;var i=this;r.emit(r.messageType.CONFIG_LOADED,e);try{var o=new ie;t().v("成功创建Lib对象");o.init((function(){t().v("Lib对象初始化成功");ue.installApi(i,o);t().v("安装Lib接口成功");r.emit(r.messageType.UMA_LIB_INITED,e)}))}catch(e){t().w("创建Lib对象异常: "+e)}}else t().err("请确保传入正确的appkey");else t().err("请正确设置相关信息!")}};try{ue.installApi(ce,null)}catch(e){t().w("uma赋值异常: ",e)}var fe="https://ucc.umeng.com/v1/mini/fetch",pe="https://pslog.umeng.com/mini_ablog",le="2.7.1",he="none",de={},ge=Array.isArray;de.isArray=ge||function(e){return"[object Array]"===toString.call(e)};de.isObject=function(e){return e===Object(e)&&!de.isArray(e)};de.isEmptyObject=function(e){if(de.isObject(e)){for(var t in e)if(hasOwnProperty.call(e,t))return!1;return!0}return!1};de.isUndefined=function(e){return void 0===e};de.isString=function(e){return"[object String]"===toString.call(e)};de.isDate=function(e){return"[object Date]"===toString.call(e)};de.isNumber=function(e){return"[object Number]"===toString.call(e)};de.each=function(e,t,n){if(null!=e){var i={},r=Array.prototype.forEach;if(r&&e.forEach===r)e.forEach(t,n);else if(e.length===+e.length){for(var o=0,s=e.length;o