├── .editorconfig
├── .gitignore
├── README.md
├── assets
└── image2d-tracking
│ ├── home
│ ├── bg.jpg
│ ├── button.png
│ ├── image.png
│ ├── shadow.png
│ └── text.png
│ ├── loading.png
│ ├── loading_bg.png
│ ├── photo
│ ├── poster-frame.png
│ ├── retake.png
│ └── save.png
│ ├── progress.png
│ ├── scan
│ ├── bg.png
│ ├── focus-frame.png
│ └── id-picture.png
│ ├── share.jpg
│ └── take-photo.png
├── image2d-tracking
├── .eslintrc.js
├── app.js
├── app.json
├── app.wxss
├── components
│ ├── loading
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── private-modal
│ │ ├── private-modal.js
│ │ ├── private-modal.json
│ │ ├── private-modal.wxml
│ │ └── private-modal.wxss
│ ├── progress-bar
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ └── scanning
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
├── marker.png
├── pages
│ ├── index
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── photo
│ │ ├── photo.js
│ │ ├── photo.json
│ │ ├── photo.wxml
│ │ └── photo.wxss
│ └── scene
│ │ ├── scene.js
│ │ ├── scene.json
│ │ ├── scene.wxml
│ │ └── scene.wxss
├── project.config.json
├── sitemap.json
└── utils
│ └── util.js
├── solar-divine-bird-mp
├── .gitignore
├── Kivicube
│ └── pages
│ │ ├── offline
│ │ ├── offline.js
│ │ ├── offline.json
│ │ ├── offline.wxml
│ │ └── offline.wxss
│ │ └── online
│ │ ├── online.js
│ │ ├── online.json
│ │ ├── online.wxml
│ │ └── online.wxss
├── app.js
├── app.json
├── app.wxss
├── asset
│ ├── back.png
│ ├── bg.jpg
│ ├── button.png
│ ├── changecamera.png
│ ├── close.png
│ ├── location-icon.png
│ ├── qrcode.jpg
│ ├── qrcode.png
│ ├── share.jpg
│ ├── takephoto.png
│ ├── watermark.png
│ └── work.png
├── components
│ ├── back-button
│ │ ├── back-button.js
│ │ ├── back-button.json
│ │ ├── back-button.wxml
│ │ ├── back-button.wxss
│ │ └── images
│ │ │ └── back.png
│ ├── copyright
│ │ ├── copyright.js
│ │ ├── copyright.json
│ │ ├── copyright.wxml
│ │ ├── copyright.wxss
│ │ └── images
│ │ │ └── copyright.png
│ ├── loading
│ │ ├── images
│ │ │ ├── loading-bird.png
│ │ │ └── sun.png
│ │ ├── loading.js
│ │ ├── loading.json
│ │ ├── loading.wxml
│ │ └── loading.wxss
│ ├── poster
│ │ ├── poster.js
│ │ ├── poster.json
│ │ ├── poster.wxml
│ │ └── poster.wxss
│ ├── private-modal
│ │ ├── private-modal.js
│ │ ├── private-modal.json
│ │ ├── private-modal.wxml
│ │ └── private-modal.wxss
│ ├── scan-tips
│ │ ├── images
│ │ │ ├── corner.png
│ │ │ ├── phone.png
│ │ │ └── work.png
│ │ ├── scan-tips.js
│ │ ├── scan-tips.json
│ │ ├── scan-tips.wxml
│ │ └── scan-tips.wxss
│ ├── warning
│ │ ├── images
│ │ │ └── warning.png
│ │ ├── warning.js
│ │ ├── warning.json
│ │ ├── warning.wxml
│ │ └── warning.wxss
│ └── work-detail
│ │ ├── images
│ │ └── close.png
│ │ ├── work-detail.js
│ │ ├── work-detail.json
│ │ ├── work-detail.wxml
│ │ └── work-detail.wxss
├── pages
│ ├── index
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ └── webview
│ │ ├── webview.js
│ │ ├── webview.json
│ │ ├── webview.wxml
│ │ └── webview.wxss
├── project.config.json
├── sitemap.json
└── 识别图.jpg
├── tiger-year-red-envelopes-高级api
├── Kivicube
│ └── pages
│ │ └── exprience
│ │ ├── exprience.js
│ │ ├── exprience.json
│ │ ├── exprience.wxml
│ │ └── exprience.wxss
├── app.js
├── app.json
├── app.wxss
├── asset
│ ├── 2022.png
│ ├── button.png
│ ├── custom-photo.png
│ ├── fish.png
│ ├── home-bg-short.jpg
│ ├── home-bg.jpg
│ ├── logo.png
│ ├── poster-bg.png
│ ├── qrcode.png
│ ├── red-envelopes.png
│ ├── share-red-envelopes-button.png
│ ├── share.png
│ ├── switch-camera.png
│ └── tiger.png
├── components
│ ├── back-button
│ │ ├── back-button.js
│ │ ├── back-button.json
│ │ ├── back-button.wxml
│ │ ├── back-button.wxss
│ │ └── images
│ │ │ └── back.png
│ ├── loading
│ │ ├── loading.js
│ │ ├── loading.json
│ │ ├── loading.wxml
│ │ └── loading.wxss
│ ├── poster
│ │ ├── poster.js
│ │ ├── poster.json
│ │ ├── poster.wxml
│ │ └── poster.wxss
│ └── private-modal
│ │ ├── private-modal.js
│ │ ├── private-modal.json
│ │ ├── private-modal.wxml
│ │ └── private-modal.wxss
├── pages
│ └── index
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
├── project.config.json
└── sitemap.json
└── tiger-year-red-envelopes
├── Kivicube
└── pages
│ └── exprience
│ ├── exprience.js
│ ├── exprience.json
│ ├── exprience.wxml
│ └── exprience.wxss
├── app.js
├── app.json
├── app.wxss
├── asset
├── 2022.png
├── button.png
├── fish.png
├── home-bg-short.jpg
├── home-bg.jpg
├── logo.png
├── poster-bg.png
├── qrcode.png
├── red-envelopes.png
├── share-red-envelopes-button.png
├── share.png
└── tiger.png
├── components
├── back-button
│ ├── back-button.js
│ ├── back-button.json
│ ├── back-button.wxml
│ ├── back-button.wxss
│ └── images
│ │ └── back.png
└── private-modal
│ ├── private-modal.js
│ ├── private-modal.json
│ ├── private-modal.wxml
│ └── private-modal.wxss
├── pages
└── index
│ ├── index.js
│ ├── index.json
│ ├── index.wxml
│ └── index.wxss
├── project.config.json
└── sitemap.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | miniprogram_npm
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | pnpm-debug.log*
14 |
15 | # Editor directories and files
16 | .idea
17 | .vscode
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 |
24 | project.private.config.json
25 | assets/package.json
26 | assets/package-lock.json
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/README.md
--------------------------------------------------------------------------------
/assets/image2d-tracking/home/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/home/bg.jpg
--------------------------------------------------------------------------------
/assets/image2d-tracking/home/button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/home/button.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/home/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/home/image.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/home/shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/home/shadow.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/home/text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/home/text.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/loading.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/loading_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/loading_bg.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/photo/poster-frame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/photo/poster-frame.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/photo/retake.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/photo/retake.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/photo/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/photo/save.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/progress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/progress.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/scan/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/scan/bg.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/scan/focus-frame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/scan/focus-frame.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/scan/id-picture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/scan/id-picture.png
--------------------------------------------------------------------------------
/assets/image2d-tracking/share.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/share.jpg
--------------------------------------------------------------------------------
/assets/image2d-tracking/take-photo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/assets/image2d-tracking/take-photo.png
--------------------------------------------------------------------------------
/image2d-tracking/.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 |
--------------------------------------------------------------------------------
/image2d-tracking/app.js:
--------------------------------------------------------------------------------
1 | // app.js
2 | App({
3 | onLaunch() {},
4 |
5 | globalData: {
6 | userInfo: null,
7 | },
8 | });
9 |
--------------------------------------------------------------------------------
/image2d-tracking/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": ["pages/index/index", "pages/scene/scene", "pages/photo/photo"],
3 | "window": {
4 | "backgroundTextStyle": "light",
5 | "navigationBarBackgroundColor": "#fff",
6 | "navigationBarTitleText": "Weixin",
7 | "navigationBarTextStyle": "black",
8 | "navigationStyle": "custom"
9 | },
10 | "plugins": {
11 | "kivicube": {
12 | "version": "2.16.8",
13 | "provider": "wx3bbab3920eabccb2"
14 | }
15 | },
16 | "__usePrivacyCheck__": true,
17 | "style": "v2",
18 | "sitemapLocation": "sitemap.json"
19 | }
20 |
--------------------------------------------------------------------------------
/image2d-tracking/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | page {
3 | height: 100%;
4 | }
5 | .container {
6 | height: 100%;
7 | display: flex;
8 | flex-direction: column;
9 | align-items: center;
10 | justify-content: center;
11 | box-sizing: border-box;
12 | }
13 |
--------------------------------------------------------------------------------
/image2d-tracking/components/loading/index.js:
--------------------------------------------------------------------------------
1 | Component({
2 | options: {
3 | styleIsolation: "isolated",
4 | },
5 | properties: {
6 | progress: {
7 | type: Number,
8 | value: 0,
9 | },
10 | },
11 | data: {
12 | percent: 0,
13 | posX: 0,
14 | posY: 0,
15 | },
16 | observers: {
17 | progress() {
18 | const imageWidth = 58.67;
19 | const r = imageWidth / 2;
20 | const percent = parseInt(this.properties.progress);
21 | const posX = Math.sin((percent / 50) * Math.PI) * r;
22 | const posY = (1 - Math.cos((percent / 50) * Math.PI)) * r;
23 | this.setData({
24 | posX,
25 | posY,
26 | percent,
27 | });
28 | },
29 | },
30 | });
31 |
--------------------------------------------------------------------------------
/image2d-tracking/components/loading/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {
4 | "progress-bar": "../progress-bar/index"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/image2d-tracking/components/loading/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{percent}}%
8 |
9 |
10 |
11 |
12 | Loading...
13 |
14 |
15 |
--------------------------------------------------------------------------------
/image2d-tracking/components/loading/index.wxss:
--------------------------------------------------------------------------------
1 | .loading {
2 | height: 100%;
3 | display: flex;
4 | flex-direction: column;
5 | justify-content: center;
6 | align-items: center;
7 | background-color: rgba(239, 237, 255, 1);
8 | }
9 |
10 | .box {
11 | position: relative;
12 | display: flex;
13 | justify-content: center;
14 | align-items: center;
15 | height: 92.27vw;
16 | width: 92.27vw;
17 | }
18 |
19 | .box-image {
20 | position: absolute;
21 | height: 100%;
22 | width: 100%;
23 | }
24 |
25 | .loading-image {
26 | position: absolute;
27 | width: 58.67vw;
28 | height: 58.67vw;
29 | z-index: 10;
30 | }
31 |
32 | .text {
33 | position: absolute;
34 | bottom: 2.93vw;
35 | font-size: 3.73vw;
36 | color: rgba(179, 145, 253, 1);
37 | }
38 |
39 | .progress-bar {
40 | position: absolute;
41 | display: flex;
42 | justify-content: center;
43 | align-items: center;
44 | width: calc(58.67vw + 5px);
45 | height: calc(58.67vw + 5px);
46 | z-index: 9;
47 | }
48 |
49 | .progress {
50 | position: absolute;
51 | top: calc(14.93vw * -0.5);
52 | left: calc(100% / 2 - (14.93vw * 0.5));
53 | display: flex;
54 | justify-content: center;
55 | align-items: center;
56 | width: 14.93vw;
57 | height: 14.93vw;
58 | z-index: 1000;
59 | }
60 |
61 | .progress-text {
62 | position: absolute;
63 | font-size: 3.2vw;
64 | color: #ffffff;
65 | }
66 |
--------------------------------------------------------------------------------
/image2d-tracking/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 |
--------------------------------------------------------------------------------
/image2d-tracking/components/private-modal/private-modal.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/image2d-tracking/components/private-modal/private-modal.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 隐私保护指引
4 |
5 | 在使用当前小程序服务之前,请仔细阅读《{{privacyContractName}}》。如你同意《{{privacyContractName}}》,请点击“同意”开始使用。
8 |
9 |
10 |
11 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/image2d-tracking/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 |
--------------------------------------------------------------------------------
/image2d-tracking/components/progress-bar/index.js:
--------------------------------------------------------------------------------
1 | Component({
2 | options: {
3 | styleIsolation: "isolated",
4 | },
5 | properties: {
6 | progress: {
7 | type: Number,
8 | value: 0,
9 | },
10 | },
11 | data: {
12 | rotateRight: "",
13 | rotateLeft: "",
14 | },
15 | observers: {
16 | progress() {
17 | const progress = parseInt(this.properties.progress);
18 | const rotateRight = `transform: rotate(${
19 | progress > 50 ? 180 : (progress / 50) * 180
20 | }deg)`;
21 | const rotateLeft = `transform: rotate(${
22 | progress < 50 ? 0 : ((progress - 50) / 50) * 180
23 | }deg)`;
24 | this.setData({
25 | rotateRight,
26 | rotateLeft,
27 | });
28 | },
29 | },
30 | });
31 |
--------------------------------------------------------------------------------
/image2d-tracking/components/progress-bar/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/image2d-tracking/components/progress-bar/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/image2d-tracking/components/progress-bar/index.wxss:
--------------------------------------------------------------------------------
1 | .circle {
2 | position: absolute;
3 | border-radius: 50%;
4 | background-color: #ffffff;
5 | width: 100%;
6 | height: 100%;
7 | display: flex;
8 | justify-content: center;
9 | align-items: center;
10 | }
11 |
12 | .sm {
13 | width: calc(100% - 5px);
14 | height: calc(100% - 5px);
15 | }
16 |
17 | .left,
18 | .right {
19 | width: 50%;
20 | height: 100%;
21 | overflow: hidden;
22 | position: relative;
23 | float: left;
24 | background-color: #ffffff;
25 | }
26 | .left {
27 | border-radius: 10000px 0 0 10000px;
28 | }
29 | .right {
30 | border-radius: 0 10000px 10000px 0;
31 | }
32 | .ring {
33 | content: "";
34 | position: absolute;
35 | display: block;
36 | width: 100%;
37 | height: 100%;
38 | background-color: #000000;
39 | }
40 | .right .ring {
41 | transform-origin: left center;
42 | }
43 | .left .ring {
44 | transform-origin: right center;
45 | }
46 |
--------------------------------------------------------------------------------
/image2d-tracking/components/scanning/index.js:
--------------------------------------------------------------------------------
1 | Component({
2 | options: {
3 | styleIsolation: "isolated",
4 | },
5 | });
6 |
--------------------------------------------------------------------------------
/image2d-tracking/components/scanning/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/image2d-tracking/components/scanning/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 请对准海报识别
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/image2d-tracking/components/scanning/index.wxss:
--------------------------------------------------------------------------------
1 | .scanning {
2 | position: absolute;
3 | top: 0;
4 | display: flex;
5 | justify-content: center;
6 | align-items: center;
7 | height: 100%;
8 | width: 100%;
9 | }
10 | .focus-frame {
11 | position: relative;
12 | display: flex;
13 | justify-content: center;
14 | align-items: center;
15 | font-size: 3.73vw;
16 | color: rgba(255, 255, 255, 1);
17 | width: 75.47vw;
18 | height: 109.6vw;
19 | }
20 |
21 | .text {
22 | position: absolute;
23 | top: 0;
24 | }
25 |
26 | .focus-frame-image1 {
27 | position: absolute;
28 | z-index: -1;
29 | width: 100%;
30 | height: 100%;
31 | }
32 |
33 | .focus-frame-image2 {
34 | position: absolute;
35 | z-index: -1;
36 | width: 44vw;
37 | height: 78.13vw;
38 | }
39 |
40 | .shadow {
41 | position: absolute;
42 | width: 100%;
43 | z-index: -2;
44 | }
45 |
--------------------------------------------------------------------------------
/image2d-tracking/marker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/image2d-tracking/marker.png
--------------------------------------------------------------------------------
/image2d-tracking/pages/index/index.js:
--------------------------------------------------------------------------------
1 | import {
2 | setAuth,
3 | getPrivate
4 | } from "../../utils/util";
5 |
6 | // 获取应用实例
7 | const app = getApp();
8 |
9 | Page({
10 | data: {},
11 | shareInfo: {
12 | path: "/pages/index/index",
13 | title: "AR元宇宙开启 伊弥戟王者出击",
14 | imageUrl: "https://meta.kivisense.com/wechat-kivicube-plugin-cases/image2d-tracking/share.jpg",
15 | },
16 | async start() {
17 | try {
18 | await getPrivate();
19 | const userAuthorize = await setAuth(
20 | "scope.camera",
21 | "摄像头权限被拒绝",
22 | "AR体验需要您授予摄像头权限,摄像头权限仅用作AR体验时的本地实景画面预览"
23 | );
24 | if (!userAuthorize) return;
25 | wx.navigateTo({
26 | url: "../scene/scene",
27 | });
28 | } catch (error) {
29 | console.log(error);
30 | }
31 | },
32 | onShareAppMessage() {
33 | return this.shareInfo;
34 | },
35 | });
36 |
--------------------------------------------------------------------------------
/image2d-tracking/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "disableScroll": true,
3 | "usingComponents": {
4 | "private-modal": "../../components/private-modal/private-modal"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/image2d-tracking/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 点击体验AR
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/image2d-tracking/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | display: flex;
3 | flex-direction: column;
4 | justify-content: flex-end;
5 | }
6 | .bg,
7 | .mask {
8 | position: absolute;
9 | width: 100%;
10 | height: 100%;
11 | z-index: -10;
12 | }
13 | .mask {
14 | background-color: rgba(36, 36, 36, 0.64);
15 | }
16 |
17 | .text-box {
18 | display: inline-flex;
19 | flex-direction: column;
20 | width: 66.4vw;
21 | margin-bottom: 8.53vw;
22 | }
23 |
24 | .image {
25 | width: 13vw;
26 | height: 3.2vw;
27 | margin-bottom: 4.8vw;
28 | }
29 |
30 | .text {
31 | width: 48vw;
32 | height: 20vw;
33 | }
34 |
35 | .button {
36 | position: relative;
37 | display: inline-flex;
38 | justify-content: center;
39 | align-items: center;
40 | width: 75vw;
41 | height: 24vw;
42 | font-size: 4vw;
43 | font-family: PingFangSC-Semibold, PingFang SC;
44 | color: #ffffff;
45 | line-height: 5.6vw;
46 | letter-spacing: 1px;
47 | margin-bottom: 1.87vw;
48 | }
49 |
50 | .button image {
51 | position: absolute;
52 | width: 100%;
53 | height: 100%;
54 | z-index: -1;
55 | }
56 |
57 | .link {
58 | font-size: 4vw;
59 | font-family: PingFangSC-Medium, PingFang SC;
60 | color: #ffffff;
61 | line-height: 5.6vw;
62 | margin-bottom: 20.27vw;
63 | border-bottom: 1px solid #ffffff;
64 | }
65 |
66 | .shadow {
67 | position: fixed;
68 | bottom: 0;
69 | width: 100%;
70 | z-index: -2;
71 | }
72 |
--------------------------------------------------------------------------------
/image2d-tracking/pages/photo/photo.js:
--------------------------------------------------------------------------------
1 | const { setAuth } = require("../../utils/util");
2 |
3 | Page({
4 | data: {
5 | photo: "",
6 | marginTop: 0,
7 | },
8 | shareInfo: {
9 | path: "/pages/index/index",
10 | title: "AR元宇宙开启 伊弥戟王者出击",
11 | imageUrl: "https://meta.kivisense.com/wechat-kivicube-plugin-cases/image2d-tracking/share.jpg",
12 | },
13 | async onLoad({ photo: photoUrl }) {
14 | const menu = wx.getMenuButtonBoundingClientRect();
15 | this.setData({
16 | marginTop: menu.bottom + 19,
17 | });
18 | wx.showLoading({ title: "加载中...", mask: true });
19 | await this.drawPhoto(photoUrl);
20 | wx.hideLoading();
21 | },
22 |
23 | async drawPhoto(photoUrl) {
24 | const res = await new Promise((resolve) => {
25 | wx.createSelectorQuery()
26 | .select("#canvas")
27 | .fields({
28 | node: true,
29 | size: true,
30 | })
31 | .exec((els) => resolve(els[0]));
32 | });
33 | const canvas = res.node;
34 | const ctx = canvas.getContext("2d");
35 | const { width, height } = res;
36 | canvas.width = width;
37 | canvas.height = height;
38 |
39 | // 海报相框image
40 | const frameImg = canvas.createImage();
41 | await new Promise((resolve) => {
42 | frameImg.onload = resolve;
43 | frameImg.src = "https://meta.kivisense.com/wechat-kivicube-plugin-cases/image2d-tracking/photo/poster-frame.png";
44 | });
45 |
46 | // 照片image
47 | const photoImg = canvas.createImage();
48 | await new Promise((resolve) => {
49 | photoImg.onload = resolve;
50 | photoImg.src = decodeURIComponent(photoUrl);
51 | });
52 | // 照片展示的高度
53 | let photoHeight = photoImg.height;
54 | // 照片展示的宽度
55 | let photoWidth = photoImg.width;
56 | // 画布的宽高比
57 | const ratio = width / height;
58 | if (photoImg.height * ratio < width) {
59 | // 比frame窄, 截取高度
60 | photoHeight = photoHeight - (photoHeight - photoWidth * (height / width));
61 | } else {
62 | // 比frame宽,截取宽度
63 | photoWidth = photoWidth - (photoWidth - photoHeight * (width / height));
64 | }
65 | // 将照片裁切后画入canvas
66 | ctx.drawImage(
67 | photoImg,
68 | (photoImg.width - photoWidth) / 2,
69 | (photoImg.height - photoHeight) / 2,
70 | photoWidth,
71 | photoHeight,
72 | 0,
73 | 0,
74 | width,
75 | height
76 | );
77 | // 将相框画入canvas
78 | ctx.drawImage(
79 | frameImg,
80 | 0,
81 | 0,
82 | frameImg.width,
83 | frameImg.height,
84 | 0,
85 | 0,
86 | width,
87 | height
88 | );
89 |
90 | await new Promise((resolve) => {
91 | setTimeout(resolve, 500);
92 | });
93 |
94 | const pic = await new Promise((resolve) => {
95 | wx.canvasToTempFilePath({
96 | fileType: "jpg",
97 | canvas,
98 | success: (res) => {
99 | resolve(res.tempFilePath);
100 | },
101 | fail: (e) => {
102 | console.warn("生成图像失败", e);
103 | },
104 | });
105 | });
106 | this.setData({
107 | photo: pic,
108 | });
109 | },
110 |
111 | async save() {
112 | const userAuth = await setAuth(
113 | "scope.writePhotosAlbum",
114 | "相册权限被拒绝",
115 | "保存照片需要您授予相册权限"
116 | );
117 | if (!userAuth) {
118 | return wx.showToast({ title: "保存照片失败, 需要相机权限", icon: none });
119 | }
120 | wx.saveImageToPhotosAlbum({
121 | filePath: this.data.photo,
122 | success() {
123 | wx.showToast({ title: "保存照片成功" });
124 | },
125 | fail(e) {
126 | console.error("保存照片失败", e);
127 | wx.showToast({ title: "保存照片失败", icon: none });
128 | },
129 | });
130 | },
131 |
132 | retake() {
133 | wx.navigateBack();
134 | },
135 |
136 | onShareAppMessage() {
137 | return this.shareInfo;
138 | },
139 | });
140 |
--------------------------------------------------------------------------------
/image2d-tracking/pages/photo/photo.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
4 |
--------------------------------------------------------------------------------
/image2d-tracking/pages/photo/photo.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 重拍
10 |
11 |
12 |
13 | 保存
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/image2d-tracking/pages/photo/photo.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | overflow: hidden;
3 | }
4 | .photo {
5 | display: flex;
6 | flex-direction: column;
7 | align-items: center;
8 | height: 100%;
9 | background: linear-gradient(134deg, #0e345f 0%, #411a46 100%);
10 | box-sizing: border-box;
11 | margin-bottom: 1000px;
12 | }
13 | .container {
14 | display: flex;
15 | flex-direction: column;
16 | align-items: center;
17 | }
18 | .picture {
19 | position: relative;
20 | width: 86.93vw;
21 | height: 147.2vw;
22 | max-height: calc(100% - 36vw);
23 | overflow: hidden;
24 | }
25 |
26 | .picture image {
27 | display: block;
28 | width: 100%;
29 | height: 100%;
30 | }
31 |
32 | .btns {
33 | display: flex;
34 | align-items: center;
35 | flex: 1;
36 | gap: 15.2vw;
37 | transform: translateY(-6vw);
38 | }
39 |
40 | .btn {
41 | position: relative;
42 | display: inline-flex;
43 | justify-content: center;
44 | align-items: center;
45 | width: 26.67vw;
46 | height: 12.8vw;
47 | color: #ffffff;
48 | font-size: 4vw;
49 | }
50 |
51 | .btn image {
52 | width: 100%;
53 | height: 100%;
54 | }
55 | .btn text {
56 | position: absolute;
57 | }
58 |
59 | #canvas {
60 | width: 652px;
61 | height: 1104px;
62 | }
63 |
--------------------------------------------------------------------------------
/image2d-tracking/pages/scene/scene.js:
--------------------------------------------------------------------------------
1 | import { setAuth } from "../../utils/util";
2 | Page({
3 | playing: false,
4 | data: {
5 | scanning: false,
6 | loading: false,
7 | photoing: false,
8 | showScene: false,
9 | progress: 0,
10 | },
11 | shareInfo: {
12 | path: "/pages/scene/scene",
13 | title: "AR元宇宙开启 伊弥戟王者出击",
14 | imageUrl: "https://meta.kivisense.com/wechat-kivicube-plugin-cases/image2d-tracking/share.jpg",
15 | },
16 |
17 | onLoad: async function () {
18 | wx.setKeepScreenOn({
19 | keepScreenOn: true,
20 | });
21 | wx.showLoading({
22 | title: "加载中...",
23 | });
24 | const userAuthorize = await setAuth(
25 | "scope.camera",
26 | "摄像头权限被拒绝",
27 | "AR体验需要您授予摄像头权限,摄像头权限仅用作AR体验时的本地实景画面预览"
28 | );
29 | if (!userAuthorize) {
30 | wx.navigateTo({
31 | url: "../index/index",
32 | });
33 | return;
34 | }
35 | this.setData({
36 | showScene: true,
37 | });
38 | },
39 |
40 | onUnload: function () {
41 | this.stopAllAnim();
42 | wx.setKeepScreenOn({
43 | keepScreenOn: false,
44 | });
45 | },
46 |
47 | ready({ detail: view }) {
48 | this.view = view;
49 | wx.hideLoading();
50 | this.setData({
51 | loading: true,
52 | });
53 | },
54 |
55 | sceneStart() {
56 | this.stopAllAnim();
57 | this.setData({
58 | scanning: true,
59 | loading: false,
60 | });
61 | if (typeof this.view.getObject === "function") {
62 | this.model = this.view.getObject("image");
63 | this.mask = this.view.getObject("image-mask");
64 | this.model.addEventListener("animationEnded", ({ animationName }) => {
65 | if (animationName !== "start") return;
66 | this.play(this.model, "loop", true);
67 | });
68 | }
69 |
70 | this.mask && this.mask.setEnableMask();
71 | },
72 |
73 | downloadAssetProgress({ detail }) {
74 | this.setData({
75 | progress: detail.progress * 100,
76 | });
77 | },
78 |
79 | tracked() {
80 | this.startAnim();
81 | },
82 |
83 | lostTrack() {
84 | this.stopAllAnim();
85 | },
86 |
87 | startAnim() {
88 | if (!this.playing) {
89 | this.playing = true;
90 | const { model, mask } = this;
91 | this.play(model, "start", false);
92 | this.play(mask, "start", false);
93 | this.setData({
94 | scanning: false,
95 | photoing: true,
96 | });
97 | }
98 | },
99 |
100 | stopAllAnim() {
101 | this.playing = false;
102 | this.stop(this.model);
103 | this.stop(this.mask);
104 | this.setData({
105 | scanning: true,
106 | photoing: false,
107 | });
108 | },
109 |
110 | play(model, name, loop) {
111 | if (!model) return false;
112 | this.stop(model);
113 | const names = model.getAnimationNames();
114 | if (!Array.isArray(names)) return;
115 | if (!names.includes(name)) return false;
116 | model.playAnimation({
117 | name, // 动画名称
118 | loop, // 是否循环播放
119 | clampWhenFinished: true, // 播放完毕后是否停留在动画最后一帧
120 | });
121 | },
122 |
123 | stop(model) {
124 | if (!model) return;
125 | const names = model.getAnimationNames();
126 | if (!Array.isArray(names)) return;
127 | names.forEach((name) => {
128 | model.stopAnimation(name);
129 | });
130 | },
131 |
132 | takePhoto: async function () {
133 | wx.showLoading({ title: "拍照中...", mask: true });
134 | const photoPath = await this.view.takePhoto();
135 | wx.navigateTo({
136 | url: `/pages/photo/photo?photo=${encodeURIComponent(photoPath)}`,
137 | });
138 | },
139 |
140 | onShareAppMessage() {
141 | return this.shareInfo;
142 | },
143 | });
144 |
--------------------------------------------------------------------------------
/image2d-tracking/pages/scene/scene.json:
--------------------------------------------------------------------------------
1 | {
2 | "disableScroll": true,
3 | "usingComponents": {
4 | "kivicube-scene": "plugin://kivicube/kivicube-scene",
5 | "loading": "/components/loading/index",
6 | "scanning": "/components/scanning/index"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/image2d-tracking/pages/scene/scene.wxml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
24 |
25 |
--------------------------------------------------------------------------------
/image2d-tracking/pages/scene/scene.wxss:
--------------------------------------------------------------------------------
1 | .kivicube {
2 | position: absolute;
3 | display: block;
4 | width: 100%;
5 | height: 100%;
6 | }
7 |
8 | .loading {
9 | position: absolute;
10 | height: 100%;
11 | width: 100%;
12 | z-index: 1000;
13 | }
14 | .scan {
15 | position: absolute;
16 | height: 100%;
17 | width: 100%;
18 | z-index: 10;
19 | }
20 |
21 | .photo {
22 | position: absolute;
23 | bottom: 14.4vw;
24 | left: 50%;
25 | transform: translateX(-50%);
26 | width: 21.87vw;
27 | height: 21.87vw;
28 | z-index: 10;
29 | }
30 |
--------------------------------------------------------------------------------
/image2d-tracking/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件",
3 | "packOptions": {
4 | "ignore": [
5 | {
6 | "value": ".eslintrc.js",
7 | "type": "file"
8 | },
9 | {
10 | "value": "marker.png",
11 | "type": "file"
12 | }
13 | ],
14 | "include": []
15 | },
16 | "setting": {
17 | "urlCheck": true,
18 | "es6": true,
19 | "enhance": true,
20 | "postcss": true,
21 | "preloadBackgroundData": false,
22 | "minified": true,
23 | "newFeature": false,
24 | "coverView": true,
25 | "nodeModules": false,
26 | "autoAudits": false,
27 | "showShadowRootInWxmlPanel": true,
28 | "scopeDataCheck": false,
29 | "uglifyFileName": false,
30 | "checkInvalidKey": true,
31 | "checkSiteMap": true,
32 | "uploadWithSourceMap": true,
33 | "compileHotReLoad": false,
34 | "lazyloadPlaceholderEnable": false,
35 | "useMultiFrameRuntime": true,
36 | "useApiHook": true,
37 | "useApiHostProcess": true,
38 | "babelSetting": {
39 | "ignore": [],
40 | "disablePlugins": [],
41 | "outputPath": ""
42 | },
43 | "enableEngineNative": false,
44 | "useIsolateContext": true,
45 | "userConfirmedBundleSwitch": false,
46 | "packNpmManually": false,
47 | "packNpmRelationList": [],
48 | "minifyWXSS": true,
49 | "disableUseStrict": false,
50 | "minifyWXML": true,
51 | "showES6CompileOption": false,
52 | "useCompilerPlugins": false,
53 | "condition": false,
54 | "compileWorklet": false,
55 | "localPlugins": false,
56 | "swc": false,
57 | "disableSWC": true
58 | },
59 | "compileType": "miniprogram",
60 | "libVersion": "3.7.9",
61 | "appid": "wx03800a762308862c",
62 | "projectname": "image2d-tracking",
63 | "condition": {},
64 | "editorSetting": {
65 | "tabIndent": "insertSpaces",
66 | "tabSize": 2
67 | },
68 | "simulatorPluginLibVersion": {}
69 | }
--------------------------------------------------------------------------------
/image2d-tracking/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [{
4 | "action": "allow",
5 | "page": "*"
6 | }]
7 | }
--------------------------------------------------------------------------------
/image2d-tracking/utils/util.js:
--------------------------------------------------------------------------------
1 | // 获取用户设备权限
2 | async function setAuth(scope, title, content) {
3 | const { authSetting } = await wx.getSetting();
4 | if (authSetting[scope]) return true;
5 | try {
6 | await wx.authorize({
7 | scope,
8 | });
9 | return true;
10 | } catch (error) {
11 | const res = await new Promise((resolve) => {
12 | wx.showModal({
13 | title,
14 | content,
15 | cancelText: "不授权",
16 | cancelColor: "#999999",
17 | confirmText: "去授权",
18 | confirmColor: "#f94218",
19 | success: resolve,
20 | });
21 | });
22 | if (res.confirm) {
23 | const { authSetting } = await wx.openSetting();
24 | if (authSetting[scope]) return true;
25 | return false;
26 | } else {
27 | return false;
28 | }
29 | }
30 | }
31 |
32 | function getPrivate() {
33 | if (wx.requirePrivacyAuthorize) {
34 | return new Promise((resolve, reject) => {
35 | wx.requirePrivacyAuthorize({
36 | success: (res) => {
37 | console.log("用户同意了隐私协议");
38 | resolve(res);
39 | },
40 | fail: (res) => {
41 | reject(res);
42 | console.log("用户拒绝了隐私协议");
43 | },
44 | });
45 | });
46 | } else {
47 | return Promise.resolve();
48 | }
49 | }
50 |
51 | module.exports = {
52 | setAuth,
53 | getPrivate,
54 | };
--------------------------------------------------------------------------------
/solar-divine-bird-mp/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows
2 | [Dd]esktop.ini
3 | Thumbs.db
4 | $RECYCLE.BIN/
5 |
6 | # macOS
7 | .DS_Store
8 | .fseventsd
9 | .Spotlight-V100
10 | .TemporaryItems
11 | .Trashes
12 |
13 | # Node.js
14 | node_modules/
15 | miniprogram_npm/
16 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/Kivicube/pages/offline/offline.js:
--------------------------------------------------------------------------------
1 | Page({
2 | data: {
3 | showLoading: true,
4 | showAR: false,
5 | progress: 0,
6 | showInfo: false,
7 | showWarning: false,
8 | showScanTips: false,
9 | showPoster: false,
10 | tempUrl: "",
11 | },
12 | async onLoad() {
13 | //获取用户授权信息
14 | const { authSetting } = await wx.getSetting();
15 |
16 | if (!authSetting["scope.camera"]) {
17 | try {
18 | await wx.authorize({
19 | scope: "scope.camera",
20 | });
21 | this.setData({
22 | showAR: true,
23 | });
24 | } catch (error) {
25 | wx.showModal({
26 | title: "摄像头权限被拒绝",
27 | content:
28 | "AR体验需要您授予摄像头权限,摄像头权限仅用作AR体验时的本地实景画面预览",
29 | cancelText: "不授权",
30 | cancelColor: "#999",
31 | confirmText: "授权",
32 | confirmColor: "#f94218",
33 | success: async (res) => {
34 | if (res.confirm) {
35 | const { authSetting } = await wx.openSetting();
36 | if (authSetting["scope.camera"]) {
37 | this.setData({
38 | showAR: true,
39 | });
40 | } else {
41 | wx.navigateBack();
42 | }
43 | } else if (res.cancel) {
44 | wx.navigateBack();
45 | }
46 | },
47 | });
48 | }
49 | } else {
50 | this.setData({
51 | showAR: true,
52 | });
53 | }
54 | },
55 |
56 | onShow() {
57 | wx.setKeepScreenOn({
58 | keepScreenOn: true,
59 | });
60 | },
61 |
62 | ready({ detail: view }) {
63 | this.view = view;
64 | },
65 |
66 | downloadProgress({ detail }) {
67 | this.setData({
68 | progress: parseInt(detail.progress * 100),
69 | });
70 | },
71 |
72 | loadEnd() {
73 | const alphaVideos = this.view.sceneInfo.objects;
74 | const { name: startName } = alphaVideos[0];
75 | const { name: loopName } = alphaVideos[1];
76 | this.startVideo = this.view.getObject(startName);
77 | this.loopVideo = this.view.getObject(loopName);
78 |
79 | this.startVideo.addEventListener("ended", () => {
80 | this.startVideoEnded = true;
81 | this.startVideo.visible = false;
82 | this.loopVideo.visible = true;
83 | this.loopVideo.loop = true; // 是否循环播放
84 | this.loopVideo.videoContext.play();
85 | });
86 |
87 | this.startVideo.visible = false;
88 | this.loopVideo.visible = false;
89 | this.setData({
90 | showLoading: false,
91 | showWarning: true,
92 | });
93 | },
94 |
95 | tracked() {
96 | //此标志位为true时(已经track到图像时),点击“知道了”可以直接播放startVideo
97 | this.imgTracked = true;
98 | if (!this.data.showWarning) {
99 | //startVideo未播放完,再次track时,继续播放startVideo。
100 | //startVideo播放完后,再次track时,循环播放loopVideo
101 | if (this.startVideoEnded) {
102 | this.loopVideo.loop = true;
103 | this.loopVideo.videoContext.play();
104 | } else {
105 | this.startVideo.visible = true;
106 | this.startVideo.loop = false; // 是否循环播放
107 | this.startVideo.videoContext.play();
108 | }
109 | this.setData({
110 | showInfo: true,
111 | showScanTips: false,
112 | });
113 | }
114 | },
115 |
116 | lostTrack() {
117 | this.imgTracked = false;
118 | if (!this.data.showWarning) {
119 | this.startVideo.videoContext.pause();
120 | this.loopVideo.videoContext.pause();
121 | this.setData({
122 | showInfo: false,
123 | showScanTips: true,
124 | });
125 | }
126 | },
127 | error(e) {
128 | const { detail } = e;
129 | // 判定是否camera权限问题,是则向用户申请权限。
130 | if (detail && detail.isCameraAuthDenied) {
131 | const page = this;
132 | wx.showModal({
133 | title: "提示",
134 | content: "请给予“摄像头”权限",
135 | success() {
136 | wx.openSetting({
137 | success({ authSetting: { "scope.camera": isGrantedCamera } }) {
138 | if (isGrantedCamera) {
139 | wx.redirectTo({ url: "/" + page.__route__ });
140 | } else {
141 | wx.showToast({ title: "获取“摄像头”权限失败!", icon: "none" });
142 | }
143 | },
144 | });
145 | },
146 | });
147 | }
148 | console.error(detail);
149 | },
150 |
151 | //自定义拍照按钮需要2步操作:1,在kivicube-scene上设置hideTakePhoto;2给自定义的点击按钮绑定方法
152 | takePhoto() {
153 | wx.showLoading({
154 | title: "拍照中",
155 | });
156 | this.view
157 | .takePhoto()
158 | .then((photoPath) => {
159 | this.setData({
160 | tempUrl: photoPath,
161 | showPoster: true,
162 | });
163 | })
164 | .catch((e) => {
165 | wx.showToast({
166 | icon: "none",
167 | title: "照片生成失败,请稍后再试",
168 | duration: 1000,
169 | });
170 | console.error(e);
171 | });
172 | },
173 | rePhoto() {
174 | this.setData({
175 | showPoster: false,
176 | tempUrl: "",
177 | });
178 | },
179 | closeWarning() {
180 | if (this.imgTracked) {
181 | this.startVideo.visible = true;
182 | this.startVideo.loop = false;
183 | this.startVideo.videoContext.play();
184 | this.setData({
185 | showInfo: true,
186 | });
187 | } else {
188 | this.setData({
189 | showScanTips: true,
190 | });
191 | }
192 | this.setData({
193 | showWarning: false,
194 | });
195 | },
196 | //分享小程序到微信聊天界面
197 | onShareAppMessage() {
198 | return {
199 | title: "扫描线下“The Sun”壁画查看AR效果",
200 | path: "/pages/index/index",
201 | imageUrl: "/asset/share.jpg",
202 | };
203 | },
204 | //分享小程序到朋友圈
205 | onShareTimeline() {
206 | return {
207 | title: "扫描线下“The Sun”壁画查看AR效果",
208 | path: "/pages/index/index",
209 | imageUrl: "/asset/share.jpg",
210 | };
211 | },
212 | });
213 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/Kivicube/pages/offline/offline.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationStyle": "custom",
3 | "disableScroll": true,
4 | "usingComponents": {
5 | "kivicube-scene": "plugin://kivicube/kivicube-scene",
6 | "back-button": "/components/back-button/back-button",
7 | "loading": "/components/loading/loading",
8 | "warning": "/components/warning/warning",
9 | "copyright": "/components/copyright/copyright",
10 | "work-detail": "/components/work-detail/work-detail",
11 | "scan-tips": "/components/scan-tips/scan-tips",
12 | "poster": "/components/poster/poster"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/Kivicube/pages/offline/offline.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
25 |
31 |
32 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/Kivicube/pages/offline/offline.wxss:
--------------------------------------------------------------------------------
1 | /* 写在分包里的css样式无法生效,所以样式写在了app.wxss,分包中使用的样式以subpkg开头 */
2 | /* 详情见https://developers.weixin.qq.com/community/develop/doc/0004a84f8149b842802c298a650800 */
3 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/Kivicube/pages/online/online.js:
--------------------------------------------------------------------------------
1 | Page({
2 | data: {
3 | showLoading: true,
4 | progress: 0,
5 | showAR: false,
6 | cameraPos: "front",
7 | },
8 | async onLoad() {
9 | const { authSetting } = await wx.getSetting();
10 | if (!authSetting["scope.camera"]) {
11 | try {
12 | await wx.authorize({
13 | scope: "scope.camera",
14 | });
15 | this.setData({
16 | showAR: true,
17 | });
18 | } catch (error) {
19 | wx.showModal({
20 | title: "摄像头权限被拒绝",
21 | content:
22 | "AR体验需要您授予摄像头权限,摄像头权限仅用作AR体验时的本地实景画面预览",
23 | cancelText: "取消",
24 | cancelColor: "#999",
25 | confirmText: "去授权",
26 | confirmColor: "#f94218",
27 | success: async (res) => {
28 | if (res.confirm) {
29 | const { authSetting } = await wx.openSetting();
30 | if (authSetting["scope.camera"]) {
31 | this.setData({
32 | showAR: true,
33 | });
34 | } else {
35 | wx.navigateBack();
36 | }
37 | } else if (res.cancel) {
38 | wx.navigateBack();
39 | }
40 | },
41 | });
42 | }
43 | } else {
44 | this.setData({
45 | showAR: true,
46 | });
47 | }
48 | },
49 |
50 | onShow() {
51 | wx.setKeepScreenOn({
52 | keepScreenOn: true,
53 | });
54 | },
55 | ready({ detail: view }) {
56 | this.view = view;
57 | },
58 | downloadProgress({ detail: progress }) {
59 | this.setData({
60 | progress: parseInt(progress * 100),
61 | });
62 | },
63 | loadEnd() {
64 | this.setData({
65 | showLoading: false,
66 | });
67 | },
68 |
69 | error(e) {
70 | const { detail } = e;
71 | // 判定是否camera权限问题,是则向用户申请权限。
72 | if (detail && detail.isCameraAuthDenied) {
73 | const page = this;
74 | wx.showModal({
75 | title: "提示",
76 | content: "请给予“摄像头”权限",
77 | success() {
78 | wx.openSetting({
79 | success({ authSetting: { "scope.camera": isGrantedCamera } }) {
80 | if (isGrantedCamera) {
81 | wx.redirectTo({ url: "/" + page.__route__ });
82 | } else {
83 | wx.showToast({ title: "获取“摄像头”权限失败!", icon: "none" });
84 | }
85 | },
86 | });
87 | },
88 | });
89 | }
90 | console.error(detail);
91 | },
92 | //自定义拍照按钮需要2步操作:1,在kivicube-scene上设置hideTakePhoto;2给自定义的点击按钮绑定方法
93 | takePhoto() {
94 | wx.showLoading({
95 | title: "拍照中",
96 | mask: true,
97 | });
98 | this.view
99 | .takePhoto()
100 | .then((photoPath) => {
101 | this.setData({
102 | tempUrl: photoPath,
103 | showPoster: true,
104 | });
105 | })
106 | .catch((e) => {
107 | wx.showToast({
108 | icon: "none",
109 | title: "照片生成失败,请稍后再试",
110 | duration: 1000,
111 | });
112 | console.error(e);
113 | });
114 | },
115 |
116 | rePhoto() {
117 | this.setData({
118 | showPoster: false,
119 | tempUrl: "",
120 | });
121 | },
122 |
123 | //切换前后置摄像头的逻辑
124 | changeCamera() {
125 | const position = this.data.cameraPos === "front" ? "back" : "front";
126 | this.view.switchCamera(position);
127 | this.setData({
128 | cameraPos: position,
129 | });
130 | },
131 | //分享小程序到微信聊天界面
132 | onShareAppMessage() {
133 | return {
134 | title: "扫描线下“The Sun”壁画查看AR效果",
135 | path: "/pages/index/index",
136 | imageUrl: "/asset/share.jpg",
137 | };
138 | },
139 | //分享小程序到朋友圈
140 | onShareTimeline() {
141 | return {
142 | title: "扫描线下“The Sun”壁画查看AR效果",
143 | path: "/pages/index/index",
144 | imageUrl: "/asset/share.jpg",
145 | };
146 | },
147 | });
148 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/Kivicube/pages/online/online.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationStyle": "custom",
3 | "disableScroll": true,
4 | "usingComponents": {
5 | "kivicube-scene": "plugin://kivicube/kivicube-scene",
6 | "back-button": "/components/back-button/back-button",
7 | "loading": "/components/loading/loading",
8 | "work-detail": "/components/work-detail/work-detail",
9 | "poster": "/components/poster/poster",
10 | "copyright": "/components/copyright/copyright"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/Kivicube/pages/online/online.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/Kivicube/pages/online/online.wxss:
--------------------------------------------------------------------------------
1 | /* 写在分包里的css样式无法生效,所以样式写在了app.wxss,分包中使用的样式以subpkg开头 */
2 | /* 详情见https://developers.weixin.qq.com/community/develop/doc/0004a84f8149b842802c298a650800 */
3 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/app.js:
--------------------------------------------------------------------------------
1 | App({});
2 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": ["pages/index/index", "pages/webview/webview"],
3 | "subpackages": [
4 | {
5 | "root": "Kivicube",
6 | "pages": ["pages/offline/offline", "pages/online/online"],
7 | "plugins": {
8 | "kivicube": {
9 | "version": "2.16.8",
10 | "provider": "wx3bbab3920eabccb2"
11 | }
12 | }
13 | }
14 | ],
15 | "preloadRule": {
16 | "pages/index/index": {
17 | "network": "wifi",
18 | "packages": ["Kivicube"]
19 | }
20 | },
21 | "__usePrivacyCheck__": true,
22 | "style": "v2",
23 | "sitemapLocation": "sitemap.json",
24 | "lazyCodeLoading": "requiredComponents"
25 | }
26 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/app.wxss:
--------------------------------------------------------------------------------
1 | /* 写在分包里的css样式无法生效,所以样式写在了app.wxss,分包中使用的样式以subpkg开头 */
2 | /* 详情见https://developers.weixin.qq.com/community/develop/doc/0004a84f8149b842802c298a650800 */
3 |
4 | .subpkg-scene {
5 | display: block;
6 | width: 100vw;
7 | height: 100vh;
8 | }
9 |
10 | .subpkg-takephoto {
11 | position: absolute;
12 | z-index: 3;
13 | bottom: 60px;
14 | left: 50%;
15 | transform: translateX(-50%);
16 | width: 21.87vw;
17 | height: 21.87vw;
18 | }
19 |
20 | .subpkg-changeamera {
21 | display: flex;
22 | justify-content: center;
23 | align-items: center;
24 | position: absolute;
25 | bottom: 19.73vw;
26 | right: 14.13vw;
27 | width: 11.2vw;
28 | height: 11.2vw;
29 | background: rgba(255, 238, 228, 0.41);
30 | box-shadow: 0vw 0.53vw 1.87vw 0vw rgba(58, 40, 40, 0.25);
31 | backdrop-filter: blur(15px);
32 | border-radius: 50%;
33 | z-index: 2;
34 | }
35 |
36 | .subpkg-changeamera image {
37 | width: 5.33vw;
38 | height: 5.33vw;
39 | }
40 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/back.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/bg.jpg
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/button.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/changecamera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/changecamera.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/close.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/location-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/location-icon.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/qrcode.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/qrcode.jpg
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/qrcode.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/share.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/share.jpg
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/takephoto.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/takephoto.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/watermark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/watermark.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/asset/work.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/asset/work.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/back-button/back-button.js:
--------------------------------------------------------------------------------
1 | Component({
2 | data: {
3 | // 胶囊按钮高度
4 | menuButtonHeight: "32px",
5 | // 左边返回按钮距屏幕顶部的距离
6 | capsuleTop: "48px",
7 | },
8 | lifetimes: {
9 | attached() {
10 | const { top, height } = wx.getMenuButtonBoundingClientRect();
11 | this.setData({
12 | // 胶囊按钮高度
13 | menuButtonHeight: height + "px",
14 | //返回按钮的位置
15 | capsuleTop: top + "px",
16 | });
17 | },
18 | },
19 | methods: {
20 | async goBack() {
21 | try {
22 | await wx.navigateBack();
23 | } catch (error) {
24 | wx.navigateTo({
25 | url: "/pages/index/index",
26 | });
27 | }
28 | },
29 | },
30 | });
31 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/back-button/back-button.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/back-button/back-button.wxml:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/back-button/back-button.wxss:
--------------------------------------------------------------------------------
1 | .back {
2 | position: absolute;
3 | left: 2.67vw;
4 | z-index: 10;
5 | }
6 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/back-button/images/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/components/back-button/images/back.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/copyright/copyright.js:
--------------------------------------------------------------------------------
1 | Component({
2 | properties: {
3 | onPageLeft: {
4 | type: Boolean,
5 | value: true,
6 | },
7 | },
8 |
9 | data: {
10 | animationData: {},
11 | },
12 |
13 | lifetimes: {
14 | attached() {
15 | let animation = wx.createAnimation({
16 | duration: 500,
17 | timingFunction: "ease-out",
18 | transformOrigin: this.properties.onPageLeft ? "0 0" : "100% 0",
19 | });
20 | this.animation = animation;
21 | this.copyrightDetailShowing = false;
22 | },
23 | },
24 |
25 | methods: {
26 | onIconClicked() {
27 | if (this.copyrightDetailShowing) {
28 | this.animation.scale(0, 0).step();
29 | this.setData({
30 | animationData: this.animation.export(),
31 | });
32 | this.copyrightDetailShowing = false;
33 | } else {
34 | this.animation.scale(1, 1).step();
35 | this.setData({
36 | animationData: this.animation.export(),
37 | });
38 | this.copyrightDetailShowing = true;
39 | }
40 | },
41 | },
42 | });
43 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/copyright/copyright.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
4 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/copyright/copyright.wxml:
--------------------------------------------------------------------------------
1 |
2 |
7 | 版权声明
8 | 该作品“太阳”(The Sun),其版权属于原创作者Key Detail所有。
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/copyright/copyright.wxss:
--------------------------------------------------------------------------------
1 | .copyright-container {
2 | position: absolute;
3 | top: 30.13vw;
4 | width: 8.53vw;
5 | height: 8.53vw;
6 | z-index: 2;
7 | }
8 |
9 | .copyright-icon-container {
10 | display: flex;
11 | justify-content: center;
12 | align-items: center;
13 | width: 8.53vw;
14 | height: 8.53vw;
15 | border-radius: 50%;
16 | background-color: rgba(255, 238, 228, 0.41);
17 | color: #ffffff;
18 | font-size: 3.73vw;
19 | text-align: center;
20 | line-height: 8.53vw;
21 | z-index: 3;
22 | backdrop-filter: blur(15px);
23 | box-shadow: 0vw 0.53vw 1.87vw 0vw rgba(58, 40, 40, 0.25);
24 | }
25 |
26 | .copyright-icon-container .copyright-image {
27 | height: auto;
28 | width: 4.27vw;
29 | }
30 |
31 | .copyright-detail {
32 | position: absolute;
33 | top: 4.265vw;
34 | width: 35.47vw;
35 | height: 32vw;
36 | background-color: rgba(255, 255, 255, 0.53);
37 | text-align: center;
38 | border-radius: 4.8vw;
39 | box-shadow: 0vw 0.53vw 1.87vw 0vw rgba(58, 40, 40, 0.25);
40 | backdrop-filter: blur(27px);
41 | z-index: 0;
42 | transform: scale(0);
43 | }
44 |
45 | .copyright-title {
46 | margin-top: 2.93vw;
47 | color: rgba(70, 70, 70, 1);
48 | font-size: 3.73vw;
49 | font-weight: bold;
50 | line-height: 5.33vw;
51 | }
52 |
53 | .copyright-content {
54 | margin-top: 1.33vw;
55 | margin-left: 1.7vw;
56 | color: rgba(80, 80, 80, 1);
57 | font-size: 3.47vw;
58 | line-height: 4.8vw;
59 | text-align: left;
60 | }
61 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/copyright/images/copyright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/components/copyright/images/copyright.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/loading/images/loading-bird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/components/loading/images/loading-bird.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/loading/images/sun.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/components/loading/images/sun.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/loading/loading.js:
--------------------------------------------------------------------------------
1 | Component({
2 | properties: {
3 | progress: {
4 | type: Number,
5 | value: 0,
6 | },
7 | isOnlineLoading: {
8 | type: Boolean,
9 | value: false,
10 | },
11 | },
12 | });
13 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/loading/loading.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
4 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/loading/loading.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
13 |
14 |
15 | 加载中{{progress}}%
16 |
17 |
18 | 在天气晴朗的白天进行体验
19 |
20 |
21 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/loading/loading.wxss:
--------------------------------------------------------------------------------
1 | .loading-warper {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | position: absolute;
6 | width: 100vw;
7 | height: 100%;
8 | z-index: 5;
9 | overflow: hidden;
10 | }
11 |
12 | .bg {
13 | position: absolute;
14 | top: 0;
15 | left: 0;
16 | vertical-align: middle;
17 | width: 100%;
18 | height: 100%;
19 | }
20 |
21 | .mask {
22 | position: absolute;
23 | top: 0;
24 | left: 0;
25 | width: 100%;
26 | height: 100%;
27 | background: linear-gradient(
28 | 180deg,
29 | rgba(90, 136, 157, 0) 0%,
30 | rgba(45, 73, 86, 0.54) 42%,
31 | #e57850 100%
32 | );
33 | backdrop-filter: blur(27px);
34 | }
35 |
36 | .loading-bird {
37 | position: absolute;
38 | top: 64.8vw;
39 | left: 17.33vw;
40 | width: 60.27vw;
41 | height: 56vw;
42 | }
43 |
44 | .loading-warper .progress {
45 | margin-top: 3.2vw;
46 | width: 17.87vw;
47 | height: 4.53vw;
48 | font-size: 3.2vw;
49 | font-weight: normal;
50 | color: #ffffff;
51 | line-height: 4.53vw;
52 | z-index: 10;
53 | }
54 |
55 | @media screen and (min-aspect-ratio: 375/668) {
56 | .loading-warper text {
57 | top: 117.33vw;
58 | }
59 | }
60 |
61 | .loading-warper .notice {
62 | display: flex;
63 | align-items: center;
64 | margin-top: 9.33vw;
65 | width: 54vw;
66 | height: 5.33vw;
67 | font-size: 3.73vw;
68 | font-weight: normal;
69 | color: #ffffff;
70 | line-height: 5.33vw;
71 | z-index: 10;
72 | }
73 |
74 | .loading-warper .notice .sun-image {
75 | width: 6.93vw;
76 | height: 6.93vw;
77 | }
78 |
79 | .loading-warper .notice text {
80 | margin-left: 1.87vw;
81 | }
82 |
83 | .loadingcircle-left {
84 | border: 1vw solid #b7b7b7;
85 | border-radius: 50%;
86 | clip: rect(0, 27.5vw, 55vw, 0);
87 | }
88 |
89 | .loadingcircle-right {
90 | border: 1vw solid #b7b7b7;
91 | border-radius: 50%;
92 | clip: rect(0, 55vw, 55vw, 27.5vw);
93 | }
94 |
95 | .loadingcircle-box {
96 | position: relative;
97 | margin-top: 62.67vw;
98 | width: 55vw;
99 | height: 55vw;
100 | border-radius: 50%;
101 | box-shadow: inset 0 0 0 1vw rgb(255, 138, 70);
102 | }
103 |
104 | .loadingcircle-box view {
105 | position: absolute;
106 | left: 0;
107 | right: 0;
108 | top: 0;
109 | bottom: 0;
110 | margin: auto;
111 | }
112 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/poster/poster.js:
--------------------------------------------------------------------------------
1 | Component({
2 | properties: {
3 | tempUrl: {
4 | type: String,
5 | value: "",
6 | },
7 | },
8 | data: {
9 | posterUrl: "",
10 | showPoster: false,
11 | },
12 | lifetimes: {
13 | async attached() {
14 | //因为图像追踪造成部分机型运算压力过大,如果用RenderingContext来进行canvas渲染,会造成渲染还未完成就调用了wx.canvasToTempFilePath,这会生成空图片或不完整的图片,
15 | //所以改用wx.createCanvasContext创建上下文,并使用ctx.draw(),保证生成canvas后再调用wx.canvasToTempFilePath
16 | const ctx = wx.createCanvasContext("poster-canvas", this);
17 |
18 | const { pixelRatio: dpr, windowWidth } = wx.getSystemInfoSync();
19 |
20 | const vwToPx = (vw) => (windowWidth / 100) * vw;
21 |
22 | const handleImageGeneratingError = () => {
23 | wx.hideLoading();
24 | wx.showToast({
25 | icon: "none",
26 | title: "照片生成失败,请稍后再试",
27 | duration: 1000,
28 | });
29 | };
30 |
31 | //生成海报背景色
32 | ctx.setFillStyle("white");
33 | ctx.fillRect(0, 0, vwToPx(100), vwToPx(173.28));
34 |
35 | try {
36 | //获取照片的长宽信息(像素值)
37 | const { width: picWidth, height: picHeight } = await wx.getImageInfo({
38 | src: this.properties.tempUrl,
39 | });
40 | //生成海报内容图
41 | let imgTotalHeight = (picWidth / 100) * 141.98;
42 | let imgStartY = (picHeight - imgTotalHeight) / 2;
43 |
44 | ctx.drawImage(
45 | this.properties.tempUrl,
46 | 0,
47 | imgStartY,
48 | picWidth,
49 | imgTotalHeight,
50 | 0,
51 | 0,
52 | windowWidth,
53 | vwToPx(141.98)
54 | );
55 | } catch (error) {
56 | handleImageGeneratingError();
57 | }
58 |
59 | //生成渐变
60 | let lingrad = ctx.createLinearGradient(
61 | 0,
62 | vwToPx(93.89),
63 | 0,
64 | vwToPx(141.98)
65 | );
66 | lingrad.addColorStop(0, "rgba(90, 136, 157, 0)");
67 | lingrad.addColorStop(1, "#66483B");
68 | ctx.setFillStyle(lingrad);
69 | ctx.fillRect(0, vwToPx(93.89), vwToPx(100), vwToPx(48.09));
70 |
71 | //水印
72 | ctx.drawImage(
73 | "/asset/watermark.png",
74 | vwToPx(70.23),
75 | vwToPx(130.15),
76 | vwToPx(26.72),
77 | vwToPx(8.78)
78 | );
79 |
80 | //生成二维码
81 | ctx.drawImage(
82 | "/asset/qrcode.jpg",
83 | vwToPx(74),
84 | vwToPx(146.95),
85 | vwToPx(21.76),
86 | vwToPx(21.76)
87 | );
88 |
89 | //生成文本
90 | ctx.setFillStyle("#51585C");
91 | ctx.setFontSize(vwToPx(5.4));
92 | ctx.fillText("扫描“太阳”", vwToPx(6.49), vwToPx(150 + 5.4));
93 | ctx.fillText(
94 | "即刻体验AR实境动态壁画。",
95 | vwToPx(6.49),
96 | vwToPx(157.63 + 5.4)
97 | );
98 |
99 | ctx.draw(true, () => {
100 | wx.canvasToTempFilePath(
101 | {
102 | x: 0,
103 | y: 0,
104 | width: windowWidth,
105 | height: windowWidth * 1.7328,
106 | destWidth: windowWidth * dpr,
107 | destHeight: windowWidth * 1.7328 * dpr,
108 | canvasId: "poster-canvas",
109 | success: (res) => {
110 | this.setData({
111 | posterUrl: res.tempFilePath,
112 | showPoster: true,
113 | });
114 | wx.hideLoading();
115 | },
116 | fail(e) {
117 | wx.showToast({
118 | title: "海报生成失败,请稍后重试",
119 | icon: "none",
120 | duration: 1000,
121 | });
122 | console.error(e);
123 | },
124 | },
125 | this
126 | );
127 | });
128 | },
129 | },
130 | methods: {
131 | //获取保存图片权限后,保存图片
132 | async savePhoto() {
133 | //保存图片到本地
134 | const savePhotoToAlbum = () => {
135 | wx.saveImageToPhotosAlbum({
136 | filePath: this.data.posterUrl,
137 | success() {
138 | wx.showToast({
139 | icon: "none",
140 | title: "照片已保存到相册",
141 | duration: 1000,
142 | });
143 | },
144 | fail(e) {
145 | wx.showToast({
146 | icon: "none",
147 | title: "照片保存失败,请稍后再试",
148 | duration: 1000,
149 | });
150 | console.error(e);
151 | },
152 | });
153 | };
154 |
155 | const { authSetting } = await wx.getSetting();
156 | if (!authSetting["scope.writePhotosAlbum"]) {
157 | try {
158 | await wx.authorize({
159 | scope: "scope.writePhotosAlbum",
160 | });
161 | savePhotoToAlbum();
162 | } catch (error) {
163 | wx.showModal({
164 | title: "相册权限被拒绝",
165 | content: "保存照片需要您授予相册权限",
166 | cancelText: "取消",
167 | cancelColor: "#999",
168 | confirmText: "去授权",
169 | confirmColor: "#f94218",
170 | success: async (res) => {
171 | if (res.confirm) {
172 | const { authSetting } = await wx.openSetting();
173 | if (authSetting["scope.writePhotosAlbum"]) {
174 | savePhotoToAlbum();
175 | } else {
176 | return;
177 | }
178 | } else if (res.cancel) {
179 | return;
180 | }
181 | },
182 | });
183 | }
184 | } else {
185 | // 有权限则直接存
186 | savePhotoToAlbum();
187 | }
188 | },
189 |
190 | rePhoto() {
191 | this.triggerEvent("rephoto");
192 | },
193 | },
194 | });
195 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/poster/poster.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/poster/poster.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 重 拍
7 | 保 存
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/poster/poster.wxss:
--------------------------------------------------------------------------------
1 | .photo-container {
2 | overflow: hidden;
3 | }
4 |
5 | .poster-canvas {
6 | position: absolute;
7 | top: -50vw;
8 | left: 1000vw;
9 | width: 100vw;
10 | height: 173.28vw;
11 | z-index: 100;
12 | }
13 |
14 | .poster-warper {
15 | display: flex;
16 | flex-direction: column;
17 | justify-content: center;
18 | align-items: center;
19 | position: absolute;
20 | left: 0;
21 | right: 0;
22 | bottom: 0;
23 | top: 0;
24 | z-index: 5;
25 | }
26 |
27 | @supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {
28 | .poster-warper {
29 | -webkit-backdrop-filter: blur(50px);
30 | backdrop-filter: blur(50px);
31 | }
32 | }
33 |
34 | .poster-img {
35 | width: 69.87vw;
36 | height: 121.07vw;
37 | z-index: 10;
38 | border-radius: 3.48vw;
39 | }
40 |
41 | .btn-warper {
42 | margin-top: 8vw;
43 | width: 68vw;
44 | display: flex;
45 | justify-content: space-between;
46 | }
47 |
48 | .btn {
49 | display: flex;
50 | justify-content: center;
51 | align-items: center;
52 | width: 26.13vw;
53 | height: 12.27vw;
54 | border-radius: 6.27vw;
55 | border: 0.27vw solid #ffffff;
56 | font-size: 4.27vw;
57 | font-weight: bold;
58 | color: #ffffff;
59 | line-height: 12.27vw;
60 | }
61 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/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 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/private-modal/private-modal.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/private-modal/private-modal.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 隐私保护指引
4 |
5 | 在使用当前小程序服务之前,请仔细阅读《{{privacyContractName}}》。如你同意《{{privacyContractName}}》,请点击“同意”开始使用。
8 |
9 |
10 |
11 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/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 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/scan-tips/images/corner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/components/scan-tips/images/corner.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/scan-tips/images/phone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/components/scan-tips/images/phone.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/scan-tips/images/work.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/components/scan-tips/images/work.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/scan-tips/scan-tips.js:
--------------------------------------------------------------------------------
1 | Component({
2 | data: {
3 | animationData: {},
4 | },
5 | lifetimes: {
6 | attached() {
7 | setTimeout(() => {
8 | let animation = wx.createAnimation({
9 | duration: 500,
10 | timingFunction: "ease-out",
11 | });
12 | animation.bottom(0).step();
13 |
14 | this.setData({
15 | animationData: animation.export(),
16 | });
17 | }, 3000);
18 | },
19 | },
20 | });
21 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/scan-tips/scan-tips.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/scan-tips/scan-tips.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 正对与壁画重合并扫描
9 |
10 |
11 |
12 | 请保持手机静止,正对壁画扫描。
13 |
14 |
15 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/scan-tips/scan-tips.wxss:
--------------------------------------------------------------------------------
1 | .scan-container {
2 | display: flex;
3 | justify-content: center;
4 | align-items: center;
5 | position: fixed;
6 | top: 0;
7 | left: 0;
8 | width: 100vw;
9 | height: 100%;
10 | background: rgba(36, 36, 36, 0.8);
11 | text-align: center;
12 | z-index: 4;
13 | }
14 |
15 | .scan-warper {
16 | display: flex;
17 | flex-direction: column;
18 | align-items: center;
19 | position: relative;
20 | width: 58.94vw;
21 | height: 107.73vw;
22 | }
23 |
24 | .scan-warper image {
25 | width: 9.87vw;
26 | height: 10.93vw;
27 | }
28 |
29 | .scan-warper .work {
30 | margin-top: 3.73vw;
31 | width: 50.13vw;
32 | height: 92.8vw;
33 | }
34 |
35 | .top-left {
36 | position: absolute;
37 | top: 0;
38 | left: 0;
39 | }
40 |
41 | .top-right {
42 | position: absolute;
43 | top: 0;
44 | right: 0;
45 | transform: scaleX(-1);
46 | }
47 |
48 | .bottom-left {
49 | position: absolute;
50 | bottom: 0;
51 | left: 0;
52 | transform: scaleY(-1);
53 | }
54 |
55 | .bottom-right {
56 | position: absolute;
57 | bottom: 0;
58 | right: 0;
59 | transform: scaleX(-1) scaleY(-1);
60 | }
61 |
62 | .tips {
63 | position: absolute;
64 | left: 50%;
65 | transform: translateX(-50%);
66 | bottom: 4.8vw;
67 | width: 65.07vw;
68 | height: 13.87vw;
69 | width: 37.33vw;
70 | height: 5.33vw;
71 | font-size: 3.73vw;
72 | font-weight: normal;
73 | color: #ffffff;
74 | line-height: 5.33vw;
75 | }
76 | .tips-container {
77 | display: flex;
78 | flex-direction: row;
79 | align-items: center;
80 | position: fixed;
81 | bottom: -22.93vw;
82 | width: 100vw;
83 | height: 22.93vw;
84 | background: rgba(36, 36, 36, 0.8);
85 | z-index: 6;
86 | }
87 |
88 | .tips-container image {
89 | margin-left: 12.27vw;
90 | width: 6.93vw;
91 | height: 11.2vw;
92 | }
93 |
94 | .tips-container view {
95 | margin-left: 6.93vw;
96 | font-size: 3.73vw;
97 | font-weight: normal;
98 | color: #ffffff;
99 | line-height: 5.33vw;
100 | }
101 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/warning/images/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/components/warning/images/warning.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/warning/warning.js:
--------------------------------------------------------------------------------
1 | Component({
2 | methods: {
3 | closeWarning() {
4 | this.triggerEvent("closeWarning");
5 | },
6 | },
7 | });
8 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/warning/warning.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/warning/warning.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 警告
6 |
7 | 您需要一个安全无阻的空间来感受此增强现实体验。请站在道路两旁的人行道上体验,时刻注意道路上往来的行人以及障碍物。
10 |
11 |
12 |
13 | 知道了
14 |
15 |
16 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/warning/warning.wxss:
--------------------------------------------------------------------------------
1 | .warning-container {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | position: absolute;
6 | top: 0;
7 | left: 0;
8 | width: 100vw;
9 | height: 100%;
10 | background: rgba(36, 36, 36, 0.8);
11 | z-index: 5;
12 | }
13 |
14 | .warning-warper {
15 | margin-top: 96.53vw;
16 | padding: 0 10vw;
17 | }
18 |
19 | .warning-title-warper {
20 | text-align: left;
21 | }
22 |
23 | .warning-title-warper image {
24 | vertical-align: middle;
25 | width: 6.4vw;
26 | height: 5.6vw;
27 | }
28 |
29 | .warning-title-warper text {
30 | margin-left: 2.4vw;
31 | width: 9.07vw;
32 | height: 6.4vw;
33 | font-size: 4.53vw;
34 | font-weight: normal;
35 | color: #ffffff;
36 | line-height: 6.4vw;
37 | }
38 |
39 | .warning-warper .warning-content {
40 | margin-top: 10.13vw;
41 | width: 78.4vw;
42 | height: 24.53vw;
43 | font-size: 3.73vw;
44 | font-weight: normal;
45 | color: #ffffff;
46 | line-height: 6.13vw;
47 | letter-spacing: 1px;
48 | text-align: left;
49 | }
50 |
51 | .close {
52 | position: absolute;
53 | bottom: 8.8vw;
54 | width: 65.07vw;
55 | height: 13.87vw;
56 | }
57 |
58 | .close image {
59 | width: 100%;
60 | height: 100%;
61 | }
62 |
63 | .close view {
64 | position: absolute;
65 | top: 50%;
66 | left: 50%;
67 | transform: translate(-50%, -50%);
68 | color: rgba(255, 255, 255, 1);
69 | }
70 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/work-detail/images/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/components/work-detail/images/close.png
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/work-detail/work-detail.js:
--------------------------------------------------------------------------------
1 | Component({
2 | data: {
3 | showDetail: false,
4 | showMoreDetail: false,
5 | animationData: {},
6 | },
7 | lifetimes: {
8 | attached() {
9 | let animation = wx.createAnimation({
10 | duration: 500,
11 | timingFunction: "ease-out",
12 | });
13 | this.animation = animation;
14 | },
15 | },
16 | methods: {
17 | onClickDetail() {
18 | this.setData({
19 | showDetail: true,
20 | });
21 | },
22 | onClickClose() {
23 | this.setData({
24 | showDetail: false,
25 | showMoreDetail: false,
26 | });
27 | },
28 | showMoreDetail() {
29 | this.setData({
30 | showMoreDetail: true,
31 | });
32 | this.animation.height("124.8vw").step();
33 | this.setData({
34 | animationData: this.animation.export(),
35 | });
36 | },
37 | hideMoreDetail() {
38 | this.setData({
39 | showMoreDetail: false,
40 | });
41 | this.animation.height("54.67vw").step();
42 | this.setData({
43 | animationData: this.animation.export(),
44 | });
45 | },
46 | },
47 | });
48 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/work-detail/work-detail.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
4 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/work-detail/work-detail.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 作品
4 | 详情
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | 太 阳
13 |
14 |
15 | “太阳”的作者是一对白俄罗斯夫妇,Key
17 | Detail和他的妻子Yu-BABA。该项目是立邦漆“为爱上色”公益活动。这幅壁画究竟有何含义? 在Key
18 | Detail提供的作品介绍中提到,他将女孩设计为太阳的模样,女孩身着传统川剧服饰,鲜艳饱和的色彩,代表成都人民热情好客的性格特点。女孩身边围绕的凤凰,代表动物与人的和平相处。同时,他也想把凤凰在中国文化中吉祥的美好寓意传递给成都人民。
19 | 此外,凤凰在西方文化中被称为“Phoenix”,除了被翻译为凤凰之外,还有一个名字叫做长生鸟,这样就能把长寿的祝愿带给这里的居民。
20 |
21 |
22 | “太阳”的作者是一对白俄罗斯夫妇,Key
23 | Detail和他的妻子Yu-BABA。该项目是立邦漆“为爱上色”公益活动。这幅壁画究竟有何含义?
24 | 查看全文
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/components/work-detail/work-detail.wxss:
--------------------------------------------------------------------------------
1 | .detail-btn {
2 | display: flex;
3 | flex-direction: column;
4 | justify-content: center;
5 | align-items: center;
6 | position: absolute;
7 | top: 30.13vw;
8 | left: 6.67vw;
9 | width: 10.13vw;
10 | height: 10.13vw;
11 | background: rgba(255, 238, 228, 0.41);
12 | box-shadow: 0vw 0.53vw 1.87vw 0vw rgba(58, 40, 40, 0.25);
13 | border-radius: 2.13vw;
14 | backdrop-filter: blur(15px);
15 | z-index: 2;
16 | font-size: 2.93vw;
17 | text-shadow: 0px 1px 2px rgba(58, 40, 40, 0.25);
18 | line-height: 3.2vw;
19 | box-sizing: border-box;
20 | color: #ffffff;
21 | }
22 |
23 | .detail-warper {
24 | position: absolute;
25 | width: 100%;
26 | height: 100%;
27 | background: rgba(36, 36, 36, 0.78);
28 | backdrop-filter: blur(50px);
29 | z-index: 10;
30 | }
31 |
32 | .close-btn {
33 | display: flex;
34 | justify-content: center;
35 | align-items: center;
36 | position: absolute;
37 | top: 30.13vw;
38 | right: 6.67vw;
39 | width: 8.53vw;
40 | height: 8.53vw;
41 | background-color: rgba(255, 238, 228, 0.41);
42 | border-radius: 50%;
43 | line-height: 8.53vw;
44 | z-index: 2;
45 | }
46 |
47 | .close-btn .close-image {
48 | width: 4.27vw;
49 | }
50 |
51 | .detail-warper .work {
52 | position: absolute;
53 | width: 78.13vw;
54 | top: 34.4vw;
55 | left: 50%;
56 | transform: translateX(-50%);
57 | }
58 |
59 | .introduction {
60 | display: flex;
61 | flex-direction: column;
62 | align-items: center;
63 | position: absolute;
64 | bottom: 0px;
65 | width: 100vw;
66 | height: 54.67vw;
67 | background: rgba(255, 255, 255, 0.72);
68 | box-shadow: 0vw 0.53vw 9.87vw 0vw #2e5064;
69 | border-radius: 6.67vw 6.67vw 0vw 0vw;
70 | backdrop-filter: blur(27px);
71 | }
72 |
73 | .title {
74 | margin-top: 5.6vw;
75 | height: 9.6vw;
76 | font-size: 6.67vw;
77 | font-weight: bold;
78 | color: #313435;
79 | line-height: 9.6vw;
80 | }
81 |
82 | .breakline {
83 | margin-top: 3vw;
84 | width: 80vw;
85 | height: 1px;
86 | background-color: #c0c0c0;
87 | }
88 |
89 | .introduction-detail {
90 | margin-top: 4.8vw;
91 | width: 80vw;
92 | height: 25.33vw;
93 | font-weight: normal;
94 | color: #464b50;
95 | line-height: 6vw;
96 | font-size: 4vw;
97 | color: #464b50;
98 | text-align: left;
99 | }
100 |
101 | .more-detail {
102 | width: 16vw;
103 | height: 4.53vw;
104 | font-size: 3.2vw;
105 | font-weight: normal;
106 | color: #912c07;
107 | line-height: 4.53vw;
108 | }
109 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/pages/index/index.js:
--------------------------------------------------------------------------------
1 | function getPrivate() {
2 | if (wx.requirePrivacyAuthorize) {
3 | return new Promise((resolve, reject) => {
4 | wx.requirePrivacyAuthorize({
5 | success: (res) => {
6 | console.log("用户同意了隐私协议");
7 | resolve(res);
8 | },
9 | fail: (res) => {
10 | reject(res);
11 | console.log("用户拒绝了隐私协议");
12 | },
13 | });
14 | });
15 | } else {
16 | return Promise.resolve();
17 | }
18 | }
19 |
20 | Page({
21 | data: {
22 | showVideo: false,
23 | showChooseBtn: false,
24 | // 胶囊按钮高度
25 | menuButtonHeight: "32px",
26 | // 胶囊按钮位置
27 | capsuleTop: "48px",
28 | },
29 |
30 | onLoad() {
31 | wx.loadFontFace({
32 | family: "PangMenZhengDao",
33 | source:
34 | 'url("https://kivicube-resource.kivisense.com/projects/solar-divine-bird-mp/fonts/PangMenZhengDaoBiaoTiTi.ttf")',
35 | fail(e) {
36 | wx.showToast({
37 | title: "字体文件加载失败",
38 | icon: "none",
39 | duration: 1000,
40 | });
41 | console.error(e);
42 | },
43 | });
44 | //设置左上角按钮的位置和高度
45 | const { top: capsuleTop, height: capsuleHeight } =
46 | wx.getMenuButtonBoundingClientRect();
47 |
48 | this.setData({
49 | menuButtonHeight: capsuleHeight + "px",
50 | capsuleTop: capsuleTop + "px",
51 | });
52 | },
53 |
54 | videoPlay() {
55 | this.setData({
56 | showVideo: true,
57 | });
58 | },
59 |
60 | async showChooseBtn() {
61 | try {
62 | await getPrivate();
63 | this.setData({
64 | showChooseBtn: true,
65 | });
66 | } catch (error) {
67 | console.log(error);
68 | }
69 | },
70 | hideChooseBtn() {
71 | this.setData({
72 | showChooseBtn: false,
73 | });
74 | },
75 |
76 | //分享小程序到微信聊天界面
77 | onShareAppMessage() {
78 | return {
79 | title: "扫描线下“The Sun”壁画查看AR效果",
80 | path: "/pages/index/index",
81 | imageUrl: "/asset/share.jpg",
82 | };
83 | },
84 | //分享小程序到朋友圈
85 | onShareTimeline() {
86 | return {
87 | title: "扫描线下“The Sun”壁画查看AR效果",
88 | path: "/pages/index/index",
89 | imageUrl: "/asset/share.jpg",
90 | };
91 | },
92 | });
93 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "disableScroll": true,
3 | "navigationStyle": "custom",
4 | "usingComponents": {
5 | "private-modal": "../../components/private-modal/private-modal",
6 | "copyright": "/components/copyright/copyright"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
26 | AR实境动态壁画
27 |
28 |
29 | 成都市武侯区得胜社区
30 |
31 |
32 |
33 | 即刻体验
34 |
35 |
36 |
37 |
38 | 我在线上
39 |
40 |
41 |
42 | 我在线下
43 |
44 |
45 |
46 | 免费制作同款AR
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | position: absolute;
6 | width: 100%;
7 | height: 100%;
8 | overflow: hidden;
9 | }
10 |
11 | .bg {
12 | position: absolute;
13 | width: 100%;
14 | height: 100%;
15 | }
16 |
17 | .bg-video {
18 | position: absolute;
19 | top: 0;
20 | left: 0;
21 | width: 100vw;
22 | height: 100%;
23 | }
24 |
25 | .mask {
26 | position: absolute;
27 | top: 0;
28 | left: 0;
29 | width: 100%;
30 | height: 100%;
31 | background: linear-gradient(183deg, rgba(7, 6, 6, 0) 0%, #292323 100%);
32 | opacity: 0.84;
33 | }
34 |
35 | .hide-choose-btn {
36 | position: absolute;
37 | left: 16px;
38 | }
39 |
40 | .title {
41 | margin-top: 101.6vw;
42 | width: 36vw;
43 | height: 17.07vw;
44 | font-size: 8.53vw;
45 | font-family: PangMenZhengDao;
46 | color: #ffffff;
47 | line-height: 9.87vw;
48 | text-shadow: 0px 1px 5px rgba(32, 35, 44, 0.63);
49 | z-index: 2;
50 | text-align: center;
51 | }
52 |
53 | .position {
54 | display: flex;
55 | align-items: center;
56 | margin-top: 7.47vw;
57 | z-index: 2;
58 | }
59 |
60 | .position image {
61 | width: 4.8vw;
62 | height: 5.87vw;
63 | }
64 |
65 | .position-content {
66 | margin-left: 1.86vw;
67 | width: 45vw;
68 | color: rgba(255, 255, 255, 1);
69 | font-weight: normal;
70 | }
71 |
72 | .btn {
73 | display: flex;
74 | justify-content: center;
75 | align-items: center;
76 | width: 66.13vw;
77 | }
78 |
79 | .btn image {
80 | position: absolute;
81 | width: 100%;
82 | height: auto;
83 | }
84 |
85 | .btn view {
86 | color: rgba(255, 255, 255, 1);
87 | font-weight: bold;
88 | z-index: 2;
89 | }
90 |
91 | .exprience {
92 | position: absolute;
93 | bottom: 25vw;
94 | width: 66.13vw;
95 | height: 15.47vw;
96 | }
97 |
98 | .btn-warper {
99 | position: absolute;
100 | bottom: 10vw;
101 | z-index: 2;
102 | }
103 |
104 | .online {
105 | position: relative;
106 | width: 52.27vw;
107 | height: 12.53vw;
108 | }
109 |
110 | .offline {
111 | position: relative;
112 | margin-top: 5.07vw;
113 | width: 52.27vw;
114 | height: 12.53vw;
115 | }
116 |
117 | .produce {
118 | position: absolute;
119 | bottom: 15vw;
120 | height: 4.53vw;
121 | font-size: 3.2vw;
122 | font-weight: bold;
123 | color: #ffffff;
124 | line-height: 4.53vw;
125 | z-index: 2;
126 | }
127 |
128 | .produce view {
129 | height: 4.53vw;
130 | font-size: 3.2vw;
131 | font-weight: bold;
132 | color: #ffffff;
133 | line-height: 4.53vw;
134 | }
135 |
136 | .produce .underline {
137 | width: 100%;
138 | height: 1px;
139 | background-color: #ffffff;
140 | }
141 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/pages/webview/webview.js:
--------------------------------------------------------------------------------
1 | Page({
2 | //分享小程序到微信聊天界面
3 | onShareAppMessage() {
4 | return {
5 | title: "扫描线下“The Sun”壁画查看AR效果",
6 | path: "/pages/index/index",
7 | imageUrl: "/asset/share.jpg",
8 | };
9 | },
10 | //分享小程序到朋友圈
11 | onShareTimeline() {
12 | return {
13 | title: "扫描线下“The Sun”壁画查看AR效果",
14 | path: "/pages/index/index",
15 | imageUrl: "/asset/share.jpg",
16 | };
17 | },
18 | });
19 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/pages/webview/webview.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/solar-divine-bird-mp/pages/webview/webview.wxml:
--------------------------------------------------------------------------------
1 |
4 | 点击打开
5 |
6 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/pages/webview/webview.wxss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/pages/webview/webview.wxss
--------------------------------------------------------------------------------
/solar-divine-bird-mp/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件",
3 | "packOptions": {
4 | "ignore": [],
5 | "include": []
6 | },
7 | "setting": {
8 | "urlCheck": true,
9 | "es6": true,
10 | "enhance": true,
11 | "postcss": true,
12 | "preloadBackgroundData": false,
13 | "minified": true,
14 | "newFeature": false,
15 | "coverView": true,
16 | "nodeModules": true,
17 | "autoAudits": false,
18 | "showShadowRootInWxmlPanel": true,
19 | "scopeDataCheck": false,
20 | "uglifyFileName": false,
21 | "checkInvalidKey": true,
22 | "checkSiteMap": true,
23 | "uploadWithSourceMap": true,
24 | "compileHotReLoad": false,
25 | "lazyloadPlaceholderEnable": false,
26 | "useMultiFrameRuntime": true,
27 | "useApiHook": true,
28 | "useApiHostProcess": true,
29 | "babelSetting": {
30 | "ignore": [],
31 | "disablePlugins": [],
32 | "outputPath": ""
33 | },
34 | "enableEngineNative": false,
35 | "useIsolateContext": false,
36 | "userConfirmedBundleSwitch": false,
37 | "packNpmManually": false,
38 | "packNpmRelationList": [],
39 | "minifyWXSS": true,
40 | "disableUseStrict": false,
41 | "minifyWXML": true,
42 | "showES6CompileOption": false,
43 | "useCompilerPlugins": false,
44 | "condition": false,
45 | "compileWorklet": false,
46 | "localPlugins": false,
47 | "swc": false,
48 | "disableSWC": true
49 | },
50 | "compileType": "miniprogram",
51 | "libVersion": "2.21.3",
52 | "appid": "wx03800a762308862c",
53 | "projectname": "solar-divine-bird-mp",
54 | "condition": {},
55 | "editorSetting": {
56 | "tabIndent": "insertSpaces",
57 | "tabSize": 2
58 | },
59 | "simulatorPluginLibVersion": {}
60 | }
--------------------------------------------------------------------------------
/solar-divine-bird-mp/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [
4 | {
5 | "action": "allow",
6 | "page": "*"
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/solar-divine-bird-mp/识别图.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/solar-divine-bird-mp/识别图.jpg
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/Kivicube/pages/exprience/exprience.js:
--------------------------------------------------------------------------------
1 | Page({
2 | data: {
3 | //是否显示loading页面,在进入页面时显示,在kivicube-scene场景加载完成后(loadSceneEnd)关闭
4 | showCustomDownload: true,
5 | //判断是否加载kivicube-scene,因为kivicube-scene需要摄像机权限,所以获取摄像机权限后再加载整个kivicube-scene组件
6 | showKiviScene: false,
7 | //是否显示领取红包封面
8 | showRedEnvelopes: false,
9 | //设定kivicube-scene初始化使用的摄像头
10 | cameraPos: "front",
11 | //海报标签的显示
12 | hidePoster: true,
13 | //需要展示的海报的地址,方便保存,base64字符串,生成速度比canvasToTempFilePath快很多
14 | posterUrl: "",
15 | },
16 | async onLoad() {
17 | //获取摄像头权限后,渲染kivicube-scene
18 | const { authSetting } = await wx.getSetting();
19 | if (!authSetting["scope.camera"]) {
20 | try {
21 | await wx.authorize({
22 | scope: "scope.camera",
23 | });
24 | this.setData({
25 | showKiviScene: true,
26 | });
27 | } catch (error) {
28 | wx.showModal({
29 | title: "摄像头权限被拒绝",
30 | content: "AR体验需要您授予摄像头权限",
31 | cancelText: "不授权",
32 | cancelColor: "#999",
33 | confirmText: "去授权",
34 | confirmColor: "#f94218",
35 | success: async (res) => {
36 | if (res.confirm) {
37 | const { authSetting } = await wx.openSetting();
38 | if (authSetting["scope.camera"]) {
39 | this.setData({
40 | showKiviScene: true,
41 | });
42 | } else {
43 | wx.navigateBack();
44 | }
45 | } else if (res.cancel) {
46 | wx.navigateBack();
47 | }
48 | },
49 | });
50 | }
51 | } else {
52 | // 有权限则直接获取
53 | this.setData({
54 | showKiviScene: true,
55 | });
56 | }
57 | },
58 |
59 | onShow() {
60 | //页面常亮
61 | wx.setKeepScreenOn({
62 | keepScreenOn: true,
63 | });
64 | },
65 |
66 | //kivicube-scene组件的bindready事件绑定的函数,通过这个函数获取并保存场景的信息
67 | ready({ detail: view }) {
68 | this.view = view;
69 | },
70 |
71 | //场景加载完成后才关闭loading页面
72 | loadSceneEnd() {
73 | //跳过云识别
74 | this.view.skipCloudar();
75 | this.setData({
76 | showCustomDownload: false,
77 | });
78 | },
79 |
80 | //如果跳过云识别,直接进入这个函数;如果没跳过云识别,在扫描到识别图时进入这个函数
81 | sceneStart() {
82 | //5s后展示领取红包封面的弹窗
83 | setTimeout(() => {
84 | if (!wx.getStorageSync("redEnvelopesShowed")) {
85 | wx.setStorageSync("redEnvelopesShowed", true);
86 | this.setData({
87 | showRedEnvelopes: true,
88 | });
89 | }
90 | }, 5000);
91 | },
92 |
93 | //自定义拍照按钮需要2步操作:1,在kivicube-scene上设置hideTakePhoto;2给自定义的点击按钮绑定方法
94 | generatePhoto() {
95 | wx.showLoading({
96 | title: "拍照中",
97 | mask: true,
98 | });
99 | //自定义拍照
100 | this.view
101 | .takePhoto()
102 | .then(async (photo) => {
103 | //在canvas上生成海报
104 | //获取canvas实例
105 | const canvasInstance = await new Promise((resolve) => {
106 | wx.createSelectorQuery()
107 | .select("#photoCanvas")
108 | .fields({
109 | node: true,
110 | size: true,
111 | })
112 | .exec((res) => {
113 | resolve(res[0]);
114 | });
115 | });
116 |
117 | //因为后面要设置canvas画布的实际大小,所以获取物理像素比
118 | let dpr = wx.getSystemInfoSync().pixelRatio;
119 | //canvas的宽度和高度,在生成海报时大量使用(逻辑像素)
120 | const canvasWidth = canvasInstance.width;
121 | const canvasHeight = canvasInstance.height;
122 |
123 | //获取并存储canvas实例,在生成海报阶段的wx.canvasToTempFilePath使用
124 | const canvas = canvasInstance.node;
125 |
126 | //获取canvas上下文,在生成海报中绘制各种元素时使用
127 | const ctx = canvas.getContext("2d");
128 |
129 | //设置canvas画布的大小(物理像素)
130 | canvas.width = canvasWidth * dpr;
131 | canvas.height = canvasHeight * dpr;
132 |
133 | const vwToPx = (vw) => (canvas.width / 100) * vw;
134 |
135 | const loadImg = (canvas, imgPath) => {
136 | return new Promise((resolve, reject) => {
137 | let img = canvas.createImage();
138 | img.src = imgPath;
139 | img.onload = () => {
140 | resolve(img);
141 | };
142 | img.onerror = () => {
143 | //onerror函数没有参数
144 | reject(new Error("图片加载错误"));
145 | };
146 | });
147 | };
148 |
149 | //canvas绘制过程中出现的数字均为设计图上的内容
150 | //生成海报背景图片
151 | try {
152 | const bgImg = await loadImg(canvas, "/asset/poster-bg.png");
153 | ctx.drawImage(bgImg, 0, 0, canvas.width, canvas.height);
154 | } catch (error) {
155 | throw new Error(error);
156 | }
157 |
158 | //在海报上生成kivicube-scene拍摄出的照片
159 | try {
160 | //kivicube-scene生成照片的宽和高信息,在生成海报时裁切照片时用到
161 | const { width: picWidth, height: picHeight } = await wx.getImageInfo({
162 | src: photo,
163 | });
164 | let img = await loadImg(canvas, photo);
165 | //最终生成在海报上照片的宽高比
166 | let genePhotoRatio = 59.07 / 92.77;
167 | //获取最终生成海报时所需kivi-scene拍摄出照片的总高度和纵向起始位置
168 | let imgTotalHeight = picWidth / genePhotoRatio;
169 | let imgStartY = (picHeight - imgTotalHeight) / 2;
170 | ctx.drawImage(
171 | img,
172 | 0,
173 | imgStartY,
174 | picWidth,
175 | imgTotalHeight,
176 | vwToPx(5.65),
177 | vwToPx(16.77),
178 | vwToPx(88.6),
179 | vwToPx(139.14)
180 | );
181 | } catch (error) {
182 | throw new Error(error);
183 | }
184 |
185 | //生成二维码
186 | try {
187 | let qrcode = await loadImg(canvas, "/asset/qrcode.png");
188 | ctx.drawImage(
189 | qrcode,
190 | vwToPx(68.9),
191 | vwToPx(159.45),
192 | vwToPx(21.04),
193 | vwToPx(21.34)
194 | );
195 | } catch (error) {
196 | throw new Error(error);
197 | }
198 |
199 | //生成kivisense的logo
200 | try {
201 | let logo = await loadImg(canvas, "/asset/logo.png");
202 | ctx.drawImage(
203 | logo,
204 | vwToPx(26.22),
205 | vwToPx(7.32),
206 | vwToPx(46.04),
207 | vwToPx(4.57)
208 | );
209 | } catch (error) {
210 | throw new Error(error);
211 | }
212 |
213 | //生成文本
214 | ctx.fillStyle = "#feeca3";
215 | ctx.font = `normal 700 ${vwToPx(6.1)}px PingFangSC-Semibold`;
216 | ctx.fillText("AR虎娃贺新春", vwToPx(8.23), vwToPx(161.59 + 6.1));
217 | ctx.font = `normal 400 ${vwToPx(4.57)}px PingFangSC`;
218 | ctx.fillText(
219 | "即刻体验,领取红包封面",
220 | vwToPx(8.23),
221 | vwToPx(161.59 + 6.1 + 8.54)
222 | );
223 |
224 | //cnavas转换成能展示的图片
225 | try {
226 | const { tempFilePath } = await wx.canvasToTempFilePath({
227 | x: 0,
228 | y: 0,
229 | width: canvasWidth,
230 | height: canvasHeight,
231 | destWidth: canvas.width,
232 | destHeight: canvas.height,
233 | canvas,
234 | });
235 | //显示海报,隐藏拍照按钮
236 | this.setData({
237 | posterUrl: tempFilePath,
238 | hidePoster: false,
239 | });
240 | } catch (error) {
241 | throw new Error(error);
242 | }
243 |
244 | wx.hideLoading();
245 | })
246 | .catch((e) => {
247 | wx.hideLoading();
248 | wx.showToast({
249 | icon: "none",
250 | title: "照片生成失败,请稍后再试",
251 | duration: 1000,
252 | });
253 | console.error(e);
254 | });
255 | },
256 |
257 | //kivicube-scene的binderror事件绑定的函数,用于判定错误信息,
258 | error(e) {
259 | const { detail } = e;
260 | // 判定是否camera权限问题,是则向用户申请权限。
261 | if (detail && detail.isCameraAuthDenied) {
262 | const page = this;
263 | wx.showModal({
264 | title: "提示",
265 | content: "请给予“摄像头”权限",
266 | success() {
267 | wx.openSetting({
268 | success({ authSetting: { "scope.camera": isGrantedCamera } }) {
269 | if (isGrantedCamera) {
270 | wx.redirectTo({
271 | url: "/" + page.__route__,
272 | });
273 | } else {
274 | wx.showToast({
275 | title: "获取“摄像头”权限失败!",
276 | icon: "none",
277 | });
278 | }
279 | },
280 | });
281 | },
282 | });
283 | }
284 | console.error(detail);
285 | },
286 |
287 | //切换前后置摄像头的逻辑
288 | switchCamera() {
289 | const position = this.data.cameraPos === "front" ? "back" : "front";
290 | this.view.switchCamera(position);
291 | this.setData({
292 | cameraPos: position,
293 | });
294 | },
295 |
296 | //重新拍摄海报的逻辑
297 | rePhoto() {
298 | this.setData({
299 | hidePoster: true,
300 | posterUrl: "",
301 | });
302 | },
303 |
304 | //分享小程序到微信聊天界面
305 | onShareAppMessage() {
306 | return {
307 | title: "AR虎娃贺新春",
308 | path: "/pages/index/index",
309 | imageUrl: "/asset/share.jpg",
310 | };
311 | },
312 | //分享小程序到朋友圈
313 | onShareTimeline() {
314 | return {
315 | title: "AR虎娃贺新春",
316 | path: "/pages/index/index",
317 | imageUrl: "/asset/share.jpg",
318 | };
319 | },
320 |
321 | //领取红包封面
322 | showRedPackage() {
323 | wx.showRedPackage({
324 | url: "https://support.weixin.qq.com/cgi-bin/mmsupport-bin/showredpacket?receiveuri=abcJqTpylEG&check_type=2#wechat_redirect",
325 | success: () => {
326 | this.setData({
327 | showRedEnvelopes: false,
328 | });
329 | },
330 | });
331 | },
332 | });
333 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/Kivicube/pages/exprience/exprience.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationStyle": "custom",
3 | "disableScroll": true,
4 | "usingComponents": {
5 | "kivicube-scene": "plugin://kivicube/kivicube-scene",
6 | "back-button": "/components/back-button/back-button",
7 | "loading": "/components/loading/loading",
8 | "poster": "/components/poster/poster"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/Kivicube/pages/exprience/exprience.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
26 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | 领取红包封面
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/Kivicube/pages/exprience/exprience.wxss:
--------------------------------------------------------------------------------
1 | /* 写在分包里的css样式无法生效,所以样式写在了app.wxss,分包中使用的样式以subpkg开头 */
2 | /* 详情见https://developers.weixin.qq.com/community/develop/doc/0004a84f8149b842802c298a650800 */
3 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/app.js:
--------------------------------------------------------------------------------
1 | App({});
2 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": ["pages/index/index"],
3 | "window": {
4 | "backgroundTextStyle": "light",
5 | "navigationBarBackgroundColor": "#fff",
6 | "navigationBarTitleText": "Weixin",
7 | "navigationBarTextStyle": "black",
8 | "initialRenderingCache": "static"
9 | },
10 | "subpackages": [
11 | {
12 | "root": "Kivicube",
13 | "pages": ["pages/exprience/exprience"],
14 | "plugins": {
15 | "kivicube": {
16 | "version": "2.16.8",
17 | "provider": "wx3bbab3920eabccb2"
18 | }
19 | }
20 | }
21 | ],
22 | "preloadRule": {
23 | "pages/index/index": {
24 | "network": "wifi",
25 | "packages": ["Kivicube"]
26 | }
27 | },
28 | "__usePrivacyCheck__": true,
29 | "style": "v2",
30 | "sitemapLocation": "sitemap.json"
31 | }
32 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/app.wxss:
--------------------------------------------------------------------------------
1 | .gold-text {
2 | color: #feeca3;
3 | }
4 |
5 | /* 写在分包里的css样式无法生效,所以样式写在了app.wxss,分包中使用的样式以subpkg开头 */
6 | /* 详情见https://developers.weixin.qq.com/community/develop/doc/0004a84f8149b842802c298a650800 */
7 | .subpkg-kivi-scene {
8 | display: block;
9 | position: absolute;
10 | width: 100vw;
11 | height: 100%;
12 | }
13 |
14 | .subpkg-custom-photo {
15 | position: absolute;
16 | left: 50%;
17 | bottom: 6.49vw;
18 | transform: translateX(-50%);
19 | width: 45.96vw;
20 | height: 45.96vw;
21 | z-index: 5;
22 | }
23 |
24 | .subpkg-switch-camera {
25 | position: absolute;
26 | right: 8.71vw;
27 | bottom: 23.11vw;
28 | transform: translateX(-50%);
29 | width: 12.71vw;
30 | height: 12.71vw;
31 | z-index: 5;
32 | }
33 |
34 | .subpkg-poster-canvas {
35 | position: absolute;
36 | top: 20vw;
37 | left: -1000vw;
38 | width: 100vw;
39 | height: 188.1vw;
40 | }
41 |
42 | .subpkg-red-envelopes-container {
43 | position: absolute;
44 | width: 100vw;
45 | height: 100%;
46 | background-color: rgba(255, 255, 255, 0.9);
47 | z-index: 6;
48 | }
49 |
50 | @supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {
51 | .subpkg-red-envelopes-container {
52 | background-color: rgba(255, 255, 255, 0.5);
53 | -webkit-backdrop-filter: blur(10px);
54 | backdrop-filter: blur(10px);
55 | }
56 | }
57 |
58 | .subpkg-red-envelopes-warper {
59 | position: absolute;
60 | top: 50%;
61 | left: 50%;
62 | transform: translate(-50%, -50%);
63 | width: 60.53vw;
64 | height: 85.33vw;
65 | animation: zoom 0.2s ease-in 0s 1;
66 | }
67 |
68 | @keyframes zoom {
69 | 0% {
70 | opacity: 0;
71 | transform: translate(-50%, -50%) scale(0);
72 | }
73 |
74 | 50% {
75 | opacity: 1;
76 | }
77 |
78 | 100% {
79 | transform: translate(-50%, -50%) scale(1);
80 | }
81 | }
82 |
83 | .subpkg-red-envelopes-warper .subpkg-red-envelopes-bg {
84 | width: 100%;
85 | height: 100%;
86 | }
87 |
88 | .subpkg-red-envelopes-button {
89 | position: absolute;
90 | bottom: 6.13vw;
91 | left: 50%;
92 | transform: translateX(-50%);
93 | width: 46.67vw;
94 | height: 12.27vw;
95 | }
96 |
97 | .subpkg-red-envelopes-button image {
98 | width: 100%;
99 | height: 100%;
100 | }
101 |
102 | .subpkg-red-envelopes-button text {
103 | position: absolute;
104 | top: 50%;
105 | left: 50%;
106 | height: 4.53vw;
107 | line-height: 4.53vw;
108 | transform: translate(-50%, -50%);
109 | z-index: 100;
110 | font-size: 3.73vw;
111 | }
112 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/2022.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/2022.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/button.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/custom-photo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/custom-photo.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/fish.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/fish.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/home-bg-short.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/home-bg-short.jpg
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/home-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/home-bg.jpg
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/logo.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/poster-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/poster-bg.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/qrcode.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/red-envelopes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/red-envelopes.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/share-red-envelopes-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/share-red-envelopes-button.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/share.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/switch-camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/switch-camera.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/asset/tiger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/asset/tiger.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/back-button/back-button.js:
--------------------------------------------------------------------------------
1 | Component({
2 | data: {
3 | // // 胶囊按钮高度
4 | menuButtonHeight: "32px",
5 | // // 左边返回按钮距屏幕顶部的距离
6 | capsuleTop: "48px",
7 | },
8 |
9 | lifetimes: {
10 | attached() {
11 | //在自定义navigationStyle的情况下自定义返回键的位置需要获取如下信息
12 | const { top, height } = wx.getMenuButtonBoundingClientRect();
13 |
14 | this.setData({
15 | menuButtonHeight: height + "px",
16 | capsuleTop: top + "px",
17 | });
18 | },
19 | },
20 |
21 | methods: {
22 | async goBack() {
23 | try {
24 | await wx.navigateBack();
25 | } catch (error) {
26 | wx.navigateTo({
27 | url: "/pages/index/index",
28 | });
29 | }
30 | },
31 | },
32 | });
33 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/back-button/back-button.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
4 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/back-button/back-button.wxml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/back-button/back-button.wxss:
--------------------------------------------------------------------------------
1 | .back {
2 | position: absolute;
3 | left: 2.67vw;
4 | z-index: 100;
5 | }
6 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/back-button/images/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes-高级api/components/back-button/images/back.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/loading/loading.js:
--------------------------------------------------------------------------------
1 | Component({
2 | options: {
3 | styleIsolation: "apply-shared",
4 | },
5 | });
6 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/loading/loading.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
4 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/loading/loading.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 加载中...
5 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/loading/loading.wxss:
--------------------------------------------------------------------------------
1 | .loading-warper {
2 | position: absolute;
3 | width: 100vw;
4 | height: 100%;
5 | text-align: center;
6 | background: linear-gradient(
7 | 8deg,
8 | #ff3737 0%,
9 | #ee6853 63%,
10 | #dd3c2d 100%,
11 | #dd3c2d 100%
12 | );
13 | z-index: 5;
14 | }
15 |
16 | .loading-tiger {
17 | position: absolute;
18 | top: 50%;
19 | left: 50%;
20 | transform: translate(-50%, -50%);
21 | width: 37.6vw;
22 | height: 37.6vw;
23 | }
24 |
25 | .loading-fish {
26 | position: absolute;
27 | top: 50%;
28 | left: 50%;
29 | width: 60.53vw;
30 | height: 60.8vw;
31 | animation: spin 4s linear 0s infinite;
32 | }
33 |
34 | @keyframes spin {
35 | 0% {
36 | transform: translate(-50%, -50%) rotateZ(0deg);
37 | }
38 |
39 | 100% {
40 | transform: translate(-50%, -50%) rotateZ(360deg);
41 | }
42 | }
43 |
44 | .loading-warper text {
45 | position: absolute;
46 | top: 142.47vw;
47 | transform: translateX(-50%);
48 | width: 18.35vw;
49 | height: 5.96vw;
50 | font-size: 14px;
51 | line-height: 4.53vw;
52 | font-weight: normal;
53 | }
54 |
55 | @media screen and (min-aspect-ratio: 375/668) {
56 | .loading-warper text {
57 | top: 117.33vw;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/poster/poster.js:
--------------------------------------------------------------------------------
1 | // components/poster/poster.js
2 | Component({
3 | options: {
4 | styleIsolation: "apply-shared",
5 | },
6 | properties: {
7 | posterUrl: String,
8 | //自定义组件手动支持hidden
9 | hidden: Boolean,
10 | },
11 |
12 | methods: {
13 | rePhoto() {
14 | this.triggerEvent("rephoto");
15 | },
16 | //将海报保存到本地相册
17 | async savePhoto() {
18 | const { authSetting } = await wx.getSetting();
19 | //保存图片到本地
20 | const savePhotoToAlbum = () => {
21 | wx.saveImageToPhotosAlbum({
22 | filePath: this.data.posterUrl,
23 | success() {
24 | wx.showToast({
25 | icon: "none",
26 | title: "照片已保存到相册",
27 | duration: 1000,
28 | });
29 | },
30 | fail() {
31 | wx.showToast({
32 | icon: "none",
33 | title: "照片保存失败,请稍后再试",
34 | duration: 1000,
35 | });
36 | },
37 | });
38 | };
39 | if (!authSetting["scope.writePhotosAlbum"]) {
40 | try {
41 | await wx.authorize({
42 | scope: "scope.writePhotosAlbum",
43 | });
44 | savePhotoToAlbum();
45 | } catch (error) {
46 | wx.showModal({
47 | title: "相册权限被拒绝",
48 | content: "保存照片需要您授予相册权限",
49 | cancelText: "取消",
50 | cancelColor: "#999",
51 | confirmText: "去授权",
52 | confirmColor: "#f94218",
53 | success: async (res) => {
54 | if (res.confirm) {
55 | const { authSetting } = await wx.openSetting();
56 | if (authSetting["scope.writePhotosAlbum"]) {
57 | savePhotoToAlbum();
58 | } else {
59 | return;
60 | }
61 | } else if (res.cancel) {
62 | return;
63 | }
64 | },
65 | });
66 | }
67 | } else {
68 | // 有权限则直接存
69 | savePhotoToAlbum();
70 | }
71 | },
72 | },
73 | });
74 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/poster/poster.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
4 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/poster/poster.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 重新拍照
6 |
7 |
8 |
9 | 保存照片
10 |
11 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/poster/poster.wxss:
--------------------------------------------------------------------------------
1 | .poster-img {
2 | position: absolute;
3 | top: 27.73vw;
4 | left: 6.27vw;
5 | width: 87.47vw;
6 | height: 164.53vw;
7 | z-index: 10;
8 | }
9 |
10 | .savephoto {
11 | position: absolute;
12 | right: 3.73vw;
13 | top: 195.2vw;
14 | width: 45.33vw;
15 | height: 14.93vw;
16 | }
17 |
18 | .savephoto image {
19 | width: 100%;
20 | height: 100%;
21 | vertical-align: middle;
22 | }
23 |
24 | .savephoto text {
25 | position: absolute;
26 | top: 50%;
27 | left: 50%;
28 | transform: translate(-50%, -50%);
29 | font-size: 3.73vw;
30 | line-height: 5.73vw;
31 | }
32 |
33 | .rephoto {
34 | position: absolute;
35 | left: 4vw;
36 | top: 195.2vw;
37 | width: 45.07vw;
38 | height: 14.93vw;
39 | }
40 |
41 | .rephoto image {
42 | width: 100%;
43 | height: 100%;
44 | vertical-align: middle;
45 | }
46 |
47 | .rephoto text {
48 | position: absolute;
49 | top: 50%;
50 | left: 50%;
51 | transform: translate(-50%, -50%);
52 | font-size: 3.73vw;
53 | line-height: 5.73vw;
54 | }
55 |
56 | @media screen and (min-aspect-ratio: 375/668) {
57 | .poster-img {
58 | top: 21.87vw;
59 | left: 17.33vw;
60 | width: 66.93vw;
61 | height: 125.6vw;
62 | }
63 |
64 | .savephoto {
65 | bottom: 12.8vw;
66 | left: 8.27vw;
67 | width: 41.6vw;
68 | height: 13.6vw;
69 | }
70 |
71 | .rephoto {
72 | bottom: 12.8vw;
73 | right: 6.67vw;
74 | width: 41.6vw;
75 | height: 13.6vw;
76 | }
77 | }
78 |
79 | .poster-warper {
80 | position: absolute;
81 | left: 0;
82 | right: 0;
83 | bottom: 0;
84 | top: 0;
85 | background-color: rgba(255, 255, 255, 0.9);
86 | z-index: 5;
87 | }
88 |
89 | @supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {
90 | .poster-warper {
91 | background-color: rgba(255, 255, 255, 0.5);
92 | -webkit-backdrop-filter: blur(10px);
93 | backdrop-filter: blur(10px);
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/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 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/private-modal/private-modal.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/components/private-modal/private-modal.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 隐私保护指引
4 |
5 | 在使用当前小程序服务之前,请仔细阅读《{{privacyContractName}}》。如你同意《{{privacyContractName}}》,请点击“同意”开始使用。
8 |
9 |
10 |
11 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/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 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/pages/index/index.js:
--------------------------------------------------------------------------------
1 | const { windowWidth, windowHeight } = wx.getSystemInfoSync();
2 |
3 | function getPrivate() {
4 | if (wx.requirePrivacyAuthorize) {
5 | return new Promise((resolve, reject) => {
6 | wx.requirePrivacyAuthorize({
7 | success: (res) => {
8 | console.log("用户同意了隐私协议");
9 | resolve(res);
10 | },
11 | fail: (res) => {
12 | reject(res);
13 | console.log("用户拒绝了隐私协议");
14 | },
15 | });
16 | });
17 | } else {
18 | return Promise.resolve();
19 | }
20 | }
21 |
22 | Page({
23 | data: {
24 | isShortScreen: windowWidth / windowHeight > 375 / 668,
25 | },
26 | async gotoExprience() {
27 | try {
28 | await getPrivate();
29 | wx.navigateTo({
30 | url: '/Kivicube/pages/exprience/exprience',
31 | })
32 | } catch (error) {
33 | console.log(error);
34 | }
35 | },
36 | onShareAppMessage() {
37 | return {
38 | title: "AR虎娃贺新春",
39 | path: "/pages/index/index",
40 | imageUrl: "/asset/share.png",
41 | };
42 | },
43 | onShareTimeline() {
44 | return {
45 | title: "AR虎娃贺新春",
46 | path: "/pages/index/index",
47 | imageUrl: "/asset/share.png",
48 | };
49 | },
50 | });
51 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationStyle": "custom",
3 | "disableScroll": true,
4 | "usingComponents": {
5 | "private-modal": "../../components/private-modal/private-modal"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 开启虎年AR
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | .new-year {
2 | position: absolute;
3 | top: 165.33vw;
4 | left: 12.27vw;
5 | width: 75.47vw;
6 | height: 23.2vw;
7 | }
8 |
9 | .btn-warper {
10 | position: absolute;
11 | top: 193.6vw;
12 | left: 19.2vw;
13 | width: 62.13vw;
14 | height: 20.27vw;
15 | }
16 |
17 | .btn-content {
18 | position: absolute;
19 | top: 50%;
20 | left: 50%;
21 | transform: translate(-50%, -50%);
22 | font-size: 5.6vw;
23 | color: #feeca3;
24 | }
25 |
26 | .bg-container {
27 | position: absolute;
28 | width: 100vw;
29 | height: 100%;
30 | overflow: hidden;
31 | background-size: 100% auto;
32 | }
33 |
34 | .bg-container image {
35 | position: absolute;
36 | width: 100vw;
37 | height: 100%;
38 | }
39 |
40 | @media screen and (min-aspect-ratio: 375/668) {
41 | .new-year {
42 | top: 127.73vw;
43 | left: 16.53vw;
44 | width: 66.93vw;
45 | height: 20vw;
46 | }
47 |
48 | .btn-warper {
49 | top: 149.33vw;
50 | left: 22.67vw;
51 | width: 54.67vw;
52 | height: 17.87vw;
53 | }
54 |
55 | .btn-content {
56 | font-size: 4.94vw;
57 | }
58 | }
59 |
60 | .btn-bg {
61 | width: 100%;
62 | height: 100%;
63 | }
64 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件",
3 | "packOptions": {
4 | "ignore": [],
5 | "include": []
6 | },
7 | "setting": {
8 | "urlCheck": false,
9 | "es6": true,
10 | "enhance": true,
11 | "postcss": true,
12 | "preloadBackgroundData": false,
13 | "minified": true,
14 | "newFeature": false,
15 | "coverView": true,
16 | "nodeModules": true,
17 | "autoAudits": false,
18 | "showShadowRootInWxmlPanel": true,
19 | "scopeDataCheck": false,
20 | "uglifyFileName": false,
21 | "checkInvalidKey": true,
22 | "checkSiteMap": true,
23 | "uploadWithSourceMap": true,
24 | "compileHotReLoad": false,
25 | "lazyloadPlaceholderEnable": false,
26 | "useMultiFrameRuntime": true,
27 | "useApiHook": true,
28 | "useApiHostProcess": true,
29 | "babelSetting": {
30 | "ignore": [],
31 | "disablePlugins": [],
32 | "outputPath": ""
33 | },
34 | "enableEngineNative": false,
35 | "useIsolateContext": false,
36 | "userConfirmedBundleSwitch": false,
37 | "packNpmManually": false,
38 | "packNpmRelationList": [],
39 | "minifyWXSS": true,
40 | "disableUseStrict": false,
41 | "minifyWXML": true,
42 | "showES6CompileOption": false,
43 | "useCompilerPlugins": false,
44 | "condition": false
45 | },
46 | "compileType": "miniprogram",
47 | "libVersion": "2.21.4",
48 | "appid": "wx03800a762308862c",
49 | "projectname": "tiger-year-red-envelopes",
50 | "cloudfunctionTemplateRoot": "",
51 | "condition": {
52 | "miniprogram": {
53 | "list": [
54 | {
55 | "name": "",
56 | "pathName": "Kivicube/pages/exprience/exprience",
57 | "query": "",
58 | "scene": null
59 | }
60 | ]
61 | }
62 | },
63 | "editorSetting": {
64 | "tabIndent": "insertSpaces",
65 | "tabSize": 2
66 | }
67 | }
--------------------------------------------------------------------------------
/tiger-year-red-envelopes-高级api/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [{
4 | "action": "allow",
5 | "page": "*"
6 | }]
7 | }
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/Kivicube/pages/exprience/exprience.js:
--------------------------------------------------------------------------------
1 | Page({
2 | data: {
3 | //是否显示loading页面,在进入页面时显示,在kivicube-scene场景加载完成后(loadSceneEnd)关闭
4 | showLoading: true,
5 | //判断是否加载kivicube-scene,因为kivicube-scene需要摄像机权限,所以获取摄像机权限后再加载整个kivicube-scene组件
6 | showKiviScene: false,
7 | //是否显示领取红包封面
8 | showRedEnvelopes: false,
9 | //是否隐藏拍照按钮
10 | hideTakePhoto: false,
11 | //是否隐藏海报
12 | hidePoster: true,
13 | //需要展示的海报的地址,方便保存
14 | posterUrl: "",
15 | },
16 |
17 | async onLoad() {
18 | //获取摄像头权限后,渲染kivicube-scene
19 | const { authSetting } = await wx.getSetting();
20 | if (!authSetting["scope.camera"]) {
21 | try {
22 | await wx.authorize({
23 | scope: "scope.camera",
24 | });
25 | this.setData({
26 | showKiviScene: true,
27 | });
28 | } catch (error) {
29 | wx.showModal({
30 | title: "摄像头权限被拒绝",
31 | content: "AR体验需要您授予摄像头权限",
32 | cancelText: "取消",
33 | cancelColor: "#999",
34 | confirmText: "去授权",
35 | confirmColor: "#f94218",
36 | success: async (res) => {
37 | if (res.confirm) {
38 | const { authSetting } = await wx.openSetting();
39 | if (authSetting["scope.camera"]) {
40 | this.setData({
41 | showKiviScene: true,
42 | });
43 | } else {
44 | wx.navigateBack();
45 | }
46 | } else if (res.cancel) {
47 | wx.navigateBack();
48 | }
49 | },
50 | });
51 | }
52 | } else {
53 | // 有权限则直接获取
54 | this.setData({
55 | showKiviScene: true,
56 | });
57 | }
58 | },
59 |
60 | onShow() {
61 | //在拍摄页面时保持页面常亮
62 | wx.setKeepScreenOn({
63 | keepScreenOn: true,
64 | });
65 | },
66 |
67 | //若在红包封面还没有弹出时退出了页面,则清除展示红包封面的定时器
68 | onUnload() {
69 | clearTimeout(this.showRedEnvelopesTimer);
70 | },
71 |
72 | //场景加载完成后才关闭loading页面
73 | loadSceneEnd() {
74 | this.setData({
75 | showLoading: false,
76 | });
77 | },
78 |
79 | //如果跳过云识别,直接进入这个函数;如果没跳过云识别,在扫描到识别图时进入这个函数
80 | sceneStart() {
81 | const isRedEnvelopesShowed = wx.getStorageSync("redEnvelopesShowed");
82 | if (!isRedEnvelopesShowed) {
83 | //5s后展示领取红包封面的弹窗
84 | this.showRedEnvelopesTimer = setTimeout(() => {
85 | this.setData({
86 | showRedEnvelopes: true,
87 | });
88 | wx.setStorageSync("redEnvelopesShowed", true);
89 | }, 5000);
90 | }
91 | },
92 |
93 | //生成海报的方法
94 | //未使用高级api无法自定义拍照按钮
95 | async generatePhoto({ detail: photoPath }) {
96 | wx.showLoading({
97 | title: "拍照中",
98 | });
99 |
100 | //在canvas上生成海报
101 | //获取canvas实例
102 | const canvasInstance = await new Promise((resolve) => {
103 | wx.createSelectorQuery()
104 | .select("#photoCanvas")
105 | .fields({
106 | node: true,
107 | size: true,
108 | })
109 | .exec((res) => {
110 | resolve(res[0]);
111 | });
112 | });
113 |
114 | //因为后面要设置canvas画布的实际大小,所以获取物理像素比
115 | let dpr = wx.getSystemInfoSync().pixelRatio;
116 | //canvas的宽度和高度,在生成海报时大量使用(逻辑像素)
117 | const canvasWidth = canvasInstance.width;
118 | const canvasHeight = canvasInstance.height;
119 |
120 | //获取并存储canvas实例,在生成海报阶段的wx.canvasToTempFilePath使用
121 | const canvas = canvasInstance.node;
122 |
123 | //获取canvas上下文,在生成海报中绘制各种元素时使用
124 | const ctx = canvas.getContext("2d");
125 |
126 | //设置canvas画布的大小(物理像素)
127 | canvas.width = canvasWidth * dpr;
128 | canvas.height = canvasHeight * dpr;
129 |
130 | const vwToPx = (vw) => (canvas.width / 100) * vw;
131 |
132 | const loadImg = (canvas, imgPath) => {
133 | return new Promise((resolve, reject) => {
134 | let img = canvas.createImage();
135 | img.src = imgPath;
136 | img.onload = () => {
137 | resolve(img);
138 | };
139 | img.onerror = () => {
140 | //onerror函数没有参数
141 | reject(new Error("图片加载错误"));
142 | };
143 | });
144 | };
145 |
146 | const handleImageGeneratingError = () => {
147 | wx.hideLoading();
148 | wx.showToast({
149 | icon: "none",
150 | title: "照片生成失败,请稍后再试",
151 | duration: 1000,
152 | });
153 | };
154 |
155 | //canvas绘制过程中出现的数字均为设计图上的内容
156 | //生成海报背景图片
157 | try {
158 | const bgImg = await loadImg(canvas, "/asset/poster-bg.png");
159 | ctx.drawImage(bgImg, 0, 0, canvas.width, canvas.height);
160 | } catch (error) {
161 | handleImageGeneratingError();
162 | }
163 |
164 | //在海报上生成kivicube-scene拍摄出的照片
165 | try {
166 | //kivicube-scene生成照片的宽和高信息,在生成海报时裁切照片时用到
167 | const { width: picWidth, height: picHeight } = await wx.getImageInfo({
168 | src: photoPath,
169 | });
170 | let img = await loadImg(canvas, photoPath);
171 | //最终生成在海报上照片的宽高比
172 | let genePhotoRatio = 59.07 / 92.77;
173 | //获取最终生成海报时所需kivi-scene拍摄出照片的总高度和纵向起始位置
174 | let imgTotalHeight = picWidth / genePhotoRatio;
175 | let imgStartY = (picHeight - imgTotalHeight) / 2;
176 | ctx.drawImage(
177 | img,
178 | 0,
179 | imgStartY,
180 | picWidth,
181 | imgTotalHeight,
182 | vwToPx(5.65),
183 | vwToPx(16.77),
184 | vwToPx(88.6),
185 | vwToPx(139.14)
186 | );
187 | } catch (error) {
188 | handleImageGeneratingError();
189 | }
190 |
191 | //生成二维码
192 | try {
193 | let qrcode = await loadImg(canvas, "/asset/qrcode.png");
194 | ctx.drawImage(
195 | qrcode,
196 | vwToPx(68.9),
197 | vwToPx(159.45),
198 | vwToPx(21.04),
199 | vwToPx(21.34)
200 | );
201 | } catch (error) {
202 | handleImageGeneratingError();
203 | }
204 |
205 | //生成kivisense的logo
206 | try {
207 | let logo = await loadImg(canvas, "/asset/logo.png");
208 | ctx.drawImage(
209 | logo,
210 | vwToPx(26.22),
211 | vwToPx(7.32),
212 | vwToPx(46.04),
213 | vwToPx(4.57)
214 | );
215 | } catch (error) {
216 | handleImageGeneratingError();
217 | }
218 |
219 | //生成文本
220 | ctx.fillStyle = "#feeca3";
221 | ctx.font = `normal 700 ${vwToPx(6.1)}px PingFangSC-Semibold`;
222 | ctx.fillText("AR虎娃贺新春", vwToPx(8.23), vwToPx(161.59 + 6.1));
223 | ctx.font = `normal 400 ${vwToPx(4.57)}px PingFangSC`;
224 | ctx.fillText(
225 | "即刻体验,领取红包封面",
226 | vwToPx(8.23),
227 | vwToPx(161.59 + 6.1 + 8.54)
228 | );
229 |
230 | //cnavas转换成能展示的图片
231 | try {
232 | const { tempFilePath } = await wx.canvasToTempFilePath({
233 | x: 0,
234 | y: 0,
235 | width: canvasWidth,
236 | height: canvasHeight,
237 | destWidth: canvas.width,
238 | destHeight: canvas.height,
239 | canvas,
240 | });
241 |
242 | //显示海报,隐藏拍照按钮
243 | this.setData({
244 | posterUrl: tempFilePath,
245 | hidePoster: false,
246 | hideTakePhoto: true,
247 | });
248 | } catch (error) {
249 | handleImageGeneratingError();
250 | }
251 |
252 | wx.hideLoading();
253 | },
254 |
255 | rePhoto() {
256 | this.setData({
257 | hidePoster: true,
258 | hideTakePhoto: false,
259 | });
260 | },
261 |
262 | //获取保存图片权限后,保存图片
263 | async savePhoto() {
264 | const { authSetting } = await wx.getSetting();
265 | //保存图片到本地
266 | const savePhotoToAlbum = () => {
267 | wx.saveImageToPhotosAlbum({
268 | filePath: this.data.posterUrl,
269 | success() {
270 | wx.showToast({
271 | icon: "none",
272 | title: "照片已保存到相册",
273 | duration: 1000,
274 | });
275 | },
276 | fail() {
277 | wx.showToast({
278 | icon: "none",
279 | title: "照片保存失败,请稍后再试",
280 | duration: 1000,
281 | });
282 | },
283 | });
284 | };
285 | if (!authSetting["scope.writePhotosAlbum"]) {
286 | try {
287 | await wx.authorize({
288 | scope: "scope.writePhotosAlbum",
289 | });
290 | savePhotoToAlbum();
291 | } catch (error) {
292 | wx.showModal({
293 | title: "相册权限被拒绝",
294 | content: "保存照片需要您授予相册权限",
295 | cancelText: "取消",
296 | cancelColor: "#999",
297 | confirmText: "去授权",
298 | confirmColor: "#f94218",
299 | success: async (res) => {
300 | if (res.confirm) {
301 | const { authSetting } = await wx.openSetting();
302 | if (authSetting["scope.writePhotosAlbum"]) {
303 | savePhotoToAlbum();
304 | } else {
305 | return;
306 | }
307 | } else if (res.cancel) {
308 | return;
309 | }
310 | },
311 | });
312 | }
313 | } else {
314 | // 有权限则直接存
315 | savePhotoToAlbum();
316 | }
317 | },
318 |
319 | //kivicube-scene的binderror事件绑定的函数,用于判定错误信息,
320 | error(e) {
321 | const { detail } = e;
322 | // 判定是否camera权限问题,是则向用户申请权限。
323 | if (detail && detail.isCameraAuthDenied) {
324 | const page = this;
325 | wx.showModal({
326 | title: "提示",
327 | content: "请给予“摄像头”权限",
328 | success() {
329 | wx.openSetting({
330 | success({ authSetting: { "scope.camera": isGrantedCamera } }) {
331 | if (isGrantedCamera) {
332 | wx.redirectTo({
333 | url: "/" + page.__route__,
334 | });
335 | } else {
336 | wx.showToast({
337 | title: "获取“摄像头”权限失败!",
338 | icon: "none",
339 | });
340 | }
341 | },
342 | });
343 | },
344 | });
345 | }
346 | },
347 |
348 | //分享小程序到微信聊天界面
349 | onShareAppMessage() {
350 | return {
351 | title: "AR虎娃贺新春",
352 | path: "/pages/index/index",
353 | imageUrl: "/asset/share.jpg",
354 | };
355 | },
356 | //分享小程序到朋友圈
357 | onShareTimeline() {
358 | return {
359 | title: "AR虎娃贺新春",
360 | path: "/pages/index/index",
361 | imageUrl: "/asset/share.jpg",
362 | };
363 | },
364 |
365 | //领取红包封面
366 | showRedPackage() {
367 | wx.showRedPackage({
368 | url: "https://support.weixin.qq.com/cgi-bin/mmsupport-bin/showredpacket?receiveuri=abcJqTpylEG&check_type=2#wechat_redirect",
369 | success: () => {
370 | this.setData({
371 | showRedEnvelopes: false,
372 | });
373 | },
374 | });
375 | },
376 | });
377 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/Kivicube/pages/exprience/exprience.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationStyle": "custom",
3 | "disableScroll": true,
4 | "usingComponents": {
5 | "kivicube-scene": "plugin://kivicube/kivicube-scene",
6 | "back-button": "/components/back-button/back-button"
7 | }
8 | }
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/Kivicube/pages/exprience/exprience.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 加载中...
7 |
8 |
9 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | 领取红包封面
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | 重新拍照
42 |
43 |
44 |
45 | 保存照片
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/Kivicube/pages/exprience/exprience.wxss:
--------------------------------------------------------------------------------
1 | /* 写在分包里的css样式无法生效,所以样式写在了app.wxss,分包中使用的样式以subpkg开头 */
2 | /* 详情见https://developers.weixin.qq.com/community/develop/doc/0004a84f8149b842802c298a650800 */
3 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/app.js:
--------------------------------------------------------------------------------
1 | App({});
2 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": ["pages/index/index"],
3 | "subpackages": [
4 | {
5 | "root": "Kivicube",
6 | "pages": ["pages/exprience/exprience"],
7 | "plugins": {
8 | "kivicube": {
9 | "version": "2.16.8",
10 | "provider": "wx3bbab3920eabccb2"
11 | }
12 | }
13 | }
14 | ],
15 | "preloadRule": {
16 | "pages/index/index": {
17 | "network": "wifi",
18 | "packages": ["Kivicube"]
19 | }
20 | },
21 | "__usePrivacyCheck__": true,
22 | "style": "v2",
23 | "sitemapLocation": "sitemap.json",
24 | "lazyCodeLoading": "requiredComponents"
25 | }
26 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/app.wxss:
--------------------------------------------------------------------------------
1 | .gold-text {
2 | color: #feeca3;
3 | }
4 |
5 | /* 写在分包里的css样式无法生效,所以样式写在了app.wxss,分包中使用的样式以subpkg开头 */
6 | /* 详情见https://developers.weixin.qq.com/community/develop/doc/0004a84f8149b842802c298a650800 */
7 |
8 | .subpkg-loading-warper {
9 | position: absolute;
10 | width: 100vw;
11 | height: 100%;
12 | text-align: center;
13 | background: linear-gradient(
14 | 8deg,
15 | #ff3737 0%,
16 | #ee6853 63%,
17 | #dd3c2d 100%,
18 | #dd3c2d 100%
19 | );
20 | z-index: 5;
21 | }
22 |
23 | .subpkg-loading-tiger {
24 | position: absolute;
25 | top: 50%;
26 | left: 50%;
27 | transform: translate(-50%, -50%);
28 | width: 37.6vw;
29 | height: 37.6vw;
30 | }
31 |
32 | .subpkg-loading-fish {
33 | position: absolute;
34 | top: 50%;
35 | left: 50%;
36 | width: 60vw;
37 | height: 60vw;
38 | animation: spin 4s linear 0s infinite;
39 | }
40 |
41 | @keyframes spin {
42 | 0% {
43 | transform: translate(-50%, -50%) rotateZ(0deg);
44 | }
45 |
46 | 100% {
47 | transform: translate(-50%, -50%) rotateZ(360deg);
48 | }
49 | }
50 |
51 | .subpkg-loading-text {
52 | position: absolute;
53 | top: 142.47vw;
54 | transform: translateX(-50%);
55 | width: 18.35vw;
56 | height: 5.96vw;
57 | font-size: 14px;
58 | line-height: 4.53vw;
59 | font-weight: normal;
60 | }
61 |
62 | @media screen and (min-aspect-ratio: 375/668) {
63 | .subpkg-loading-text {
64 | top: 117.33vw;
65 | }
66 | }
67 |
68 | .subpkg-kivi-scene {
69 | display: block;
70 | position: absolute;
71 | width: 100vw;
72 | height: 100%;
73 | }
74 |
75 | .subpkg-red-envelopes-container {
76 | position: absolute;
77 | width: 100vw;
78 | height: 100%;
79 | backdrop-filter: blur(10px);
80 | background-color: rgba(255, 255, 255, 0.5);
81 | z-index: 6;
82 | }
83 |
84 | .subpkg-red-envelopes-warper {
85 | position: absolute;
86 | top: 50%;
87 | left: 50%;
88 | transform: translate(-50%, -50%);
89 | width: 60.53vw;
90 | height: 85.33vw;
91 | animation: zoom 0.2s ease-in 0s 1;
92 | }
93 |
94 | @keyframes zoom {
95 | 0% {
96 | opacity: 0;
97 | transform: translate(-50%, -50%) scale(0);
98 | }
99 |
100 | 50% {
101 | opacity: 1;
102 | }
103 |
104 | 100% {
105 | transform: translate(-50%, -50%) scale(1);
106 | }
107 | }
108 |
109 | .subpkg-red-envelopes-warper .subpkg-red-envelopes-bg {
110 | width: 100%;
111 | height: 100%;
112 | }
113 |
114 | .subpkg-red-envelopes-button {
115 | position: absolute;
116 | bottom: 6.13vw;
117 | left: 50%;
118 | transform: translateX(-50%);
119 | width: 46.67vw;
120 | height: 12.27vw;
121 | text-align: center;
122 | }
123 |
124 | .subpkg-red-envelopes-button image {
125 | width: 100%;
126 | height: 100%;
127 | }
128 |
129 | .subpkg-red-envelopes-button text {
130 | position: absolute;
131 | top: 50%;
132 | left: 50%;
133 | height: 4.53vw;
134 | width: 100%;
135 | line-height: 4.53vw;
136 | transform: translate(-50%, -50%);
137 | z-index: 100;
138 | font-size: 3.73vw;
139 | }
140 |
141 | .subpkg-poster-img {
142 | position: absolute;
143 | top: 27.73vw;
144 | left: 6.27vw;
145 | width: 87.47vw;
146 | height: 164.53vw;
147 | z-index: 10;
148 | }
149 |
150 | .subpkg-savephoto {
151 | position: absolute;
152 | right: 3.73vw;
153 | top: 195.2vw;
154 | width: 45.33vw;
155 | height: 14.93vw;
156 | }
157 |
158 | .subpkg-savephoto image {
159 | width: 100%;
160 | height: 100%;
161 | vertical-align: middle;
162 | }
163 |
164 | .subpkg-savephoto text {
165 | position: absolute;
166 | top: 50%;
167 | left: 50%;
168 | transform: translate(-50%, -50%);
169 | font-size: 3.73vw;
170 | line-height: 5.73vw;
171 | }
172 |
173 | .subpkg-rephoto {
174 | position: absolute;
175 | left: 4vw;
176 | top: 195.2vw;
177 | width: 45.07vw;
178 | height: 14.93vw;
179 | }
180 |
181 | .subpkg-rephoto image {
182 | width: 100%;
183 | height: 100%;
184 | vertical-align: middle;
185 | }
186 |
187 | .subpkg-rephoto text {
188 | position: absolute;
189 | top: 50%;
190 | left: 50%;
191 | transform: translate(-50%, -50%);
192 | font-size: 3.73vw;
193 | line-height: 5.73vw;
194 | }
195 |
196 | @media screen and (min-aspect-ratio: 375/668) {
197 | .subpkg-poster-img {
198 | top: 21.87vw;
199 | left: 17.33vw;
200 | width: 66.93vw;
201 | height: 125.6vw;
202 | }
203 |
204 | .subpkg-savephoto {
205 | bottom: 12.8vw;
206 | left: 8.27vw;
207 | width: 41.6vw;
208 | height: 13.6vw;
209 | }
210 |
211 | .subpkg-rephoto {
212 | bottom: 12.8vw;
213 | right: 6.67vw;
214 | width: 41.6vw;
215 | height: 13.6vw;
216 | }
217 | }
218 |
219 | .subpkg-poster-canvas {
220 | position: absolute;
221 | top: 20vw;
222 | left: -1000vw;
223 | width: 100vw;
224 | height: 188.1vw;
225 | }
226 |
227 | .subpkg-poster-warper {
228 | position: absolute;
229 | backdrop-filter: blur(10px);
230 | left: 0;
231 | right: 0;
232 | bottom: 0;
233 | top: 0;
234 | background-color: rgba(255, 255, 255, 0.5);
235 | z-index: 10000;
236 | }
237 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/2022.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/2022.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/button.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/fish.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/fish.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/home-bg-short.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/home-bg-short.jpg
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/home-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/home-bg.jpg
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/logo.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/poster-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/poster-bg.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/qrcode.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/red-envelopes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/red-envelopes.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/share-red-envelopes-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/share-red-envelopes-button.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/share.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/asset/tiger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/asset/tiger.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/components/back-button/back-button.js:
--------------------------------------------------------------------------------
1 | Component({
2 | data: {
3 | // 胶囊按钮高度
4 | menuButtonHeight: "32px",
5 | // 左边返回按钮距屏幕顶部的距离
6 | capsuleTop: "48px",
7 | },
8 | lifetimes: {
9 | attached() {
10 | const { top, height } = wx.getMenuButtonBoundingClientRect();
11 | this.setData({
12 | // 胶囊按钮高度
13 | menuButtonHeight: height + "px",
14 | //返回按钮的位置
15 | capsuleTop: top + "px",
16 | });
17 | },
18 | },
19 | methods: {
20 | async goBack() {
21 | try {
22 | await wx.navigateBack();
23 | } catch (error) {
24 | wx.navigateTo({
25 | url: "/pages/index/index",
26 | });
27 | }
28 | },
29 | },
30 | });
31 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/components/back-button/back-button.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/components/back-button/back-button.wxml:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/components/back-button/back-button.wxss:
--------------------------------------------------------------------------------
1 | .back {
2 | position: absolute;
3 | left: 2.67vw;
4 | z-index: 100;
5 | }
6 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/components/back-button/images/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kivisense/wechat-kivicube-plugin-cases/6b7f11d86a59afb6d2dee23f1f2dc897b77af024/tiger-year-red-envelopes/components/back-button/images/back.png
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/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 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/components/private-modal/private-modal.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/components/private-modal/private-modal.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 隐私保护指引
4 |
5 | 在使用当前小程序服务之前,请仔细阅读《{{privacyContractName}}》。如你同意《{{privacyContractName}}》,请点击“同意”开始使用。
8 |
9 |
10 |
11 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/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 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/pages/index/index.js:
--------------------------------------------------------------------------------
1 | const { windowWidth, windowHeight } = wx.getSystemInfoSync();
2 |
3 | function getPrivate() {
4 | if (wx.requirePrivacyAuthorize) {
5 | return new Promise((resolve, reject) => {
6 | wx.requirePrivacyAuthorize({
7 | success: (res) => {
8 | console.log("用户同意了隐私协议");
9 | resolve(res);
10 | },
11 | fail: (res) => {
12 | reject(res);
13 | console.log("用户拒绝了隐私协议");
14 | },
15 | });
16 | });
17 | } else {
18 | return Promise.resolve();
19 | }
20 | }
21 |
22 | Page({
23 | data: {
24 | isShortScreen: windowWidth / windowHeight > 375 / 668,
25 | },
26 | async gotoExprience() {
27 | try {
28 | await getPrivate();
29 | wx.navigateTo({
30 | url: '/Kivicube/pages/exprience/exprience',
31 | })
32 | } catch (error) {
33 | console.log(error);
34 | }
35 | },
36 | onShareAppMessage() {
37 | return {
38 | title: "AR虎娃贺新春",
39 | path: "/pages/index/index",
40 | imageUrl: "/asset/share.png",
41 | };
42 | },
43 | onShareTimeline() {
44 | return {
45 | title: "AR虎娃贺新春",
46 | path: "/pages/index/index",
47 | imageUrl: "/asset/share.png",
48 | };
49 | },
50 | });
51 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationStyle": "custom",
3 | "disableScroll": true,
4 | "usingComponents": {
5 | "private-modal": "../../components/private-modal/private-modal"
6 | }
7 | }
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 开启虎年AR
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | .new-year {
2 | position: absolute;
3 | top: 165.33vw;
4 | left: 12.27vw;
5 | width: 75.47vw;
6 | height: 23.2vw;
7 | }
8 |
9 | .btn-warper {
10 | position: absolute;
11 | top: 193.6vw;
12 | left: 19.2vw;
13 | width: 62.13vw;
14 | height: 20.27vw;
15 | }
16 |
17 | .btn-content {
18 | position: absolute;
19 | top: 50%;
20 | left: 50%;
21 | transform: translate(-50%, -50%);
22 | font-size: 5.6vw;
23 | color: #feeca3;
24 | }
25 |
26 | .bg-container {
27 | position: absolute;
28 | width: 100vw;
29 | height: 100%;
30 | overflow: hidden;
31 | background-size: 100% auto;
32 | }
33 |
34 | .bg-container image {
35 | position: absolute;
36 | width: 100vw;
37 | height: 100%;
38 | }
39 |
40 | @media screen and (min-aspect-ratio: 375/668) {
41 | .new-year {
42 | top: 127.73vw;
43 | left: 16.53vw;
44 | width: 66.93vw;
45 | height: 20vw;
46 | }
47 |
48 | .btn-warper {
49 | top: 149.33vw;
50 | left: 22.67vw;
51 | width: 54.67vw;
52 | height: 17.87vw;
53 | }
54 |
55 | .btn-content {
56 | font-size: 4.94vw;
57 | }
58 | }
59 |
60 | .btn-bg {
61 | width: 100%;
62 | height: 100%;
63 | }
64 |
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件",
3 | "setting": {
4 | "urlCheck": false,
5 | "es6": true,
6 | "enhance": true,
7 | "postcss": true,
8 | "preloadBackgroundData": false,
9 | "minified": true,
10 | "newFeature": false,
11 | "coverView": true,
12 | "nodeModules": true,
13 | "autoAudits": false,
14 | "showShadowRootInWxmlPanel": true,
15 | "scopeDataCheck": false,
16 | "uglifyFileName": false,
17 | "checkInvalidKey": true,
18 | "checkSiteMap": true,
19 | "uploadWithSourceMap": true,
20 | "compileHotReLoad": false,
21 | "lazyloadPlaceholderEnable": false,
22 | "useMultiFrameRuntime": true,
23 | "babelSetting": {
24 | "ignore": [],
25 | "disablePlugins": [],
26 | "outputPath": ""
27 | },
28 | "enableEngineNative": false,
29 | "useIsolateContext": false,
30 | "userConfirmedBundleSwitch": false,
31 | "packNpmManually": false,
32 | "packNpmRelationList": [],
33 | "minifyWXSS": true,
34 | "disableUseStrict": false,
35 | "minifyWXML": true,
36 | "showES6CompileOption": false,
37 | "useCompilerPlugins": false,
38 | "condition": false,
39 | "ignoreUploadUnusedFiles": true
40 | },
41 | "compileType": "miniprogram",
42 | "cloudfunctionTemplateRoot": "",
43 | "condition": {
44 | "miniprogram": {
45 | "list": [
46 | {
47 | "name": "",
48 | "pathName": "Kivicube/pages/exprience/exprience",
49 | "query": "",
50 | "scene": null
51 | }
52 | ]
53 | }
54 | },
55 | "editorSetting": {
56 | "tabIndent": "insertSpaces",
57 | "tabSize": 2
58 | },
59 | "libVersion": "2.21.3",
60 | "packOptions": {
61 | "ignore": [],
62 | "include": []
63 | },
64 | "appid": "wx03800a762308862c"
65 | }
--------------------------------------------------------------------------------
/tiger-year-red-envelopes/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [{
4 | "action": "allow",
5 | "page": "*"
6 | }]
7 | }
--------------------------------------------------------------------------------