添加 手势识别demo完成
This commit is contained in:
parent
a8cca89108
commit
56107508f9
@ -18,10 +18,10 @@ module.exports = {
|
|||||||
// 环境对象
|
// 环境对象
|
||||||
name: 'szxgl测试环境', // 环境名称
|
name: 'szxgl测试环境', // 环境名称
|
||||||
script: 'npm run build:dev', // 打包命令
|
script: 'npm run build:dev', // 打包命令
|
||||||
host: '120.25.121.117', // 服务器地址
|
host: '39.108.110.167', // 服务器地址
|
||||||
port: 22, // 服务器端口号
|
port: 22, // 服务器端口号
|
||||||
username: 'front', // 服务器登录用户名
|
username: 'front', // 服务器登录用户名
|
||||||
password: 'Szxgl#3210', // 服务器登录密码
|
password: 'XfhdFront', // 服务器登录密码
|
||||||
distPath: 'dist', // 本地打包生成目录
|
distPath: 'dist', // 本地打包生成目录
|
||||||
webDir: '/mnt/cdn/scl/webglToy',
|
webDir: '/mnt/cdn/scl/webglToy',
|
||||||
// webDir: "/mnt/services/tomcat-8090-test/webapps/test/front", // test替换自己实际项目目录 服务器部署路径(不可为空或'/')
|
// webDir: "/mnt/services/tomcat-8090-test/webapps/test/front", // test替换自己实际项目目录 服务器部署路径(不可为空或'/')
|
||||||
|
|||||||
@ -47,6 +47,7 @@
|
|||||||
"@babel/core": "^7.13.14",
|
"@babel/core": "^7.13.14",
|
||||||
"@babel/plugin-transform-runtime": "^7.13.10",
|
"@babel/plugin-transform-runtime": "^7.13.10",
|
||||||
"@babel/preset-env": "^7.13.12",
|
"@babel/preset-env": "^7.13.12",
|
||||||
|
"@handtracking.io/yoha": "^0.0.7",
|
||||||
"@nutui/nutui": "^2.2.15",
|
"@nutui/nutui": "^2.2.15",
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/cli-plugin-babel": "~4.5.0",
|
||||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||||
@ -56,10 +57,14 @@
|
|||||||
"axios": "^0.20.0",
|
"axios": "^0.20.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
|
"coi-serviceworker": "^0.1.6",
|
||||||
|
"copy-webpack-plugin": "^4.4.1",
|
||||||
"deploy-cli-service": "^1.2.0",
|
"deploy-cli-service": "^1.2.0",
|
||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
"eslint-plugin-vue": "^6.2.2",
|
"eslint-plugin-vue": "^6.2.2",
|
||||||
"glslify": "^7.1.1",
|
"glslify": "^7.1.1",
|
||||||
|
"handtrackjs": "^0.1.5",
|
||||||
|
"meshline": "^2.0.3",
|
||||||
"qrcode": "^1.4.4",
|
"qrcode": "^1.4.4",
|
||||||
"stats.js": "^0.17.0",
|
"stats.js": "^0.17.0",
|
||||||
"style-resources-loader": "^1.3.2",
|
"style-resources-loader": "^1.3.2",
|
||||||
@ -95,4 +100,4 @@
|
|||||||
"not dead",
|
"not dead",
|
||||||
"not ie <= 8"
|
"not ie <= 8"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ module.exports = {
|
|||||||
'postcss-zindex': false
|
'postcss-zindex': false
|
||||||
},
|
},
|
||||||
"postcss-px2rem-exclude": {
|
"postcss-px2rem-exclude": {
|
||||||
remUnit: 37.5,//转换为rem的基准px
|
remUnit: 75,//转换为rem的基准px
|
||||||
remPrecision: 8, //转换精度,小数点后保留位数
|
remPrecision: 8, //转换精度,小数点后保留位数
|
||||||
// exclude: /node_modules|folder_name/i
|
// exclude: /node_modules|folder_name/i
|
||||||
},
|
},
|
||||||
|
|||||||
BIN
src/assets/images/overlay.png
Normal file
BIN
src/assets/images/overlay.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 367 KiB |
@ -110,7 +110,7 @@ export default {
|
|||||||
|
|
||||||
this.controller = this.renderer.xr.getController(0);
|
this.controller = this.renderer.xr.getController(0);
|
||||||
this.controller.addEventListener("select", () => {
|
this.controller.addEventListener("select", () => {
|
||||||
let moved = new Date().getTime() - that.startTime > 500;
|
let moved = new Date().getTime() - that.startTime > 165;
|
||||||
if (!moved) {
|
if (!moved) {
|
||||||
this.addPumpkin();
|
this.addPumpkin();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,34 +7,24 @@
|
|||||||
* @FilePath: /xfhd-vue-scaffold/src/page/index/Home/Index.vue
|
* @FilePath: /xfhd-vue-scaffold/src/page/index/Home/Index.vue
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="color">
|
<div class="color">
|
||||||
<AR></AR>
|
<AR></AR>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
// @ is an alias to /src
|
// @ is an alias to /src
|
||||||
import AR from "@/components/ar/index.vue";
|
import AR from "@/components/ar/index.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ar",
|
name: "ar",
|
||||||
components: { AR },
|
components: { AR },
|
||||||
mounted() {},
|
mounted() {},
|
||||||
methods: {
|
methods: {},
|
||||||
showTips() {
|
|
||||||
this.$weui.topTips("正在努力开发中……敬请期待", {
|
|
||||||
duration: 1500,
|
|
||||||
className: "custom-classname",
|
|
||||||
callback: function () {
|
|
||||||
// console.log('close');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.color {
|
.color {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -7,34 +7,24 @@
|
|||||||
* @FilePath: /xfhd-vue-scaffold/src/page/index/Home/Index.vue
|
* @FilePath: /xfhd-vue-scaffold/src/page/index/Home/Index.vue
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="color">
|
<div class="color">
|
||||||
<AR></AR>
|
<AR></AR>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
// @ is an alias to /src
|
// @ is an alias to /src
|
||||||
import AR from "@/components/ar/hit.vue";
|
import AR from "@/components/ar/hit.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "arHit",
|
name: "arHit",
|
||||||
components: { AR },
|
components: { AR },
|
||||||
mounted() {},
|
mounted() {},
|
||||||
methods: {
|
methods: {},
|
||||||
showTips() {
|
|
||||||
this.$weui.topTips("正在努力开发中……敬请期待", {
|
|
||||||
duration: 1500,
|
|
||||||
className: "custom-classname",
|
|
||||||
callback: function () {
|
|
||||||
// console.log('close');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.color {
|
.color {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -1,13 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<!-- 需要缓存的 -->
|
<!-- 需要缓存的 -->
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<router-view v-if="$route.meta.keepAlive" />
|
<router-view v-if="$route.meta.keepAlive" />
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
<!-- 不需要缓存的 -->
|
<!-- 不需要缓存的 -->
|
||||||
<router-view v-if="!$route.meta.keepAlive" />
|
<router-view v-if="!$route.meta.keepAlive" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
#app {
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
237
src/page/index/Camera/index.vue
Normal file
237
src/page/index/Camera/index.vue
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: your name
|
||||||
|
* @Date: 2020-08-28 15:20:15
|
||||||
|
* @LastEditTime: 2020-10-10 17:19:06
|
||||||
|
* @LastEditors: Please set LastEditors
|
||||||
|
* @Description: In User Settings Edit
|
||||||
|
* @FilePath: /xfhd-vue-scaffold/src/page/index/Home/Index.vue
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div class="camera">
|
||||||
|
<div class="video-con">
|
||||||
|
<div class="kuang" ref="kuang"></div>
|
||||||
|
<video
|
||||||
|
id="gum-local"
|
||||||
|
class="video"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
autoplay
|
||||||
|
playsinline
|
||||||
|
ref="myVideo"
|
||||||
|
></video>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 获取权限 -->
|
||||||
|
<button
|
||||||
|
id="showVideo"
|
||||||
|
class="btn"
|
||||||
|
ref="showVideoBtn"
|
||||||
|
@click="initVideo($event)"
|
||||||
|
>
|
||||||
|
开启摄像头
|
||||||
|
</button>
|
||||||
|
<button class="btn2" ref="takePhotoBtn" @click="takePhoto($event)">
|
||||||
|
拍照
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<img ref="photo" class="photo" :src="imgsrc" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
// @ is an alias to /src
|
||||||
|
import gsap from "gsap";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Index",
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
imgsrc: "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initCanvas();
|
||||||
|
// this.requestPermission().then((res) => {
|
||||||
|
// if (res === true) {
|
||||||
|
// // 权限获取成功
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取设备权限
|
||||||
|
getDevicePermission(constraints) {
|
||||||
|
if (navigator.mediaDevices.getUserMedia === undefined) {
|
||||||
|
navigator.mediaDevices.getUserMedia = function (constraints) {
|
||||||
|
var getUserMedia =
|
||||||
|
navigator.getUserMedia ||
|
||||||
|
navigator.webkitGetUserMedia ||
|
||||||
|
navigator.mozGetUserMedia ||
|
||||||
|
navigator.msGetUserMedia ||
|
||||||
|
navigator.oGetUserMedia;
|
||||||
|
if (!getUserMedia) {
|
||||||
|
return Promise.reject(
|
||||||
|
new Error(
|
||||||
|
"getUserMedia is not implemented in this browser"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
getUserMedia.call(
|
||||||
|
navigator,
|
||||||
|
constraints,
|
||||||
|
resolve,
|
||||||
|
reject
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return global.navigator.mediaDevices
|
||||||
|
.getUserMedia(constraints)
|
||||||
|
.then((stream) => {
|
||||||
|
if (stream) {
|
||||||
|
stopStreamTracks(stream);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error("EmptyStreamError"));
|
||||||
|
})
|
||||||
|
.catch((errMsg) => {
|
||||||
|
if (errMsg && "NotAllowedError" === errMsg.name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Promise.reject(errMsg);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 开始获取权限
|
||||||
|
requestPermission() {
|
||||||
|
return this.getDevicePermission({ video: true, audio: true })
|
||||||
|
.catch(() =>
|
||||||
|
this.getDevicePermission({ video: false, audio: true })
|
||||||
|
)
|
||||||
|
.catch(() =>
|
||||||
|
this.getDevicePermission({ video: true, audio: false })
|
||||||
|
)
|
||||||
|
.catch(() => true);
|
||||||
|
},
|
||||||
|
// 初始化 video
|
||||||
|
async initVideo(e) {
|
||||||
|
const constraints = {
|
||||||
|
video: {
|
||||||
|
facingMode: "user",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.stream = await navigator.mediaDevices.getUserMedia(
|
||||||
|
constraints
|
||||||
|
);
|
||||||
|
this.handleSuccess(this.stream, constraints);
|
||||||
|
e.target.disabled = true;
|
||||||
|
} catch (e) {
|
||||||
|
this.handleError(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSuccess(stream, constraints) {
|
||||||
|
this.video = this.$refs.myVideo;
|
||||||
|
const videoTracks = stream.getVideoTracks();
|
||||||
|
gsap.to(this.$refs.kuang, { autoAlpha: 1 });
|
||||||
|
gsap.to(this.$refs.showVideoBtn, { autoAlpha: 0 });
|
||||||
|
gsap.to(this.$refs.takePhotoBtn, { autoAlpha: 1 });
|
||||||
|
console.log("Got stream with constraints:", constraints);
|
||||||
|
console.log(`Using video device: ${videoTracks[0].label}`);
|
||||||
|
window.stream = stream; // make variable available to browser console
|
||||||
|
this.video.srcObject = stream;
|
||||||
|
},
|
||||||
|
handleError(error) {
|
||||||
|
console.error(error);
|
||||||
|
},
|
||||||
|
initCanvas() {
|
||||||
|
this.canvas = document.createElement("canvas");
|
||||||
|
this.ctx = this.canvas.getContext("2d");
|
||||||
|
this.canvas.width = 650 * 1.2;
|
||||||
|
this.canvas.height = 900 * 1.2;
|
||||||
|
},
|
||||||
|
async takePhoto() {
|
||||||
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
// this.ctx.fillStyle = "#fff";
|
||||||
|
// this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
this.ctx.drawImage(
|
||||||
|
this.$refs.myVideo,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
650,
|
||||||
|
900,
|
||||||
|
650 * 0.14,
|
||||||
|
900 * 0.1,
|
||||||
|
650,
|
||||||
|
900
|
||||||
|
);
|
||||||
|
let img = await this.loadImage(
|
||||||
|
require("@/assets/images/overlay.png")
|
||||||
|
);
|
||||||
|
this.ctx.drawImage(img, 0, 0, 650 * 1.2, 900 * 1.2);
|
||||||
|
|
||||||
|
this.imgsrc = this.canvas.toDataURL("image/jpeg");
|
||||||
|
|
||||||
|
gsap.to(this.$refs.photo, { autoAlpha: 1 });
|
||||||
|
},
|
||||||
|
loadImage(src) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let img = new Image();
|
||||||
|
img.onload = (res) => {
|
||||||
|
resolve(img);
|
||||||
|
};
|
||||||
|
img.onerror = (res) => {
|
||||||
|
reject(img);
|
||||||
|
};
|
||||||
|
img.src = src;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped lang="less">
|
||||||
|
.camera {
|
||||||
|
// min-height: 100vh;
|
||||||
|
padding: 100px 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
.kuang {
|
||||||
|
visibility: hidden;
|
||||||
|
.paLayout(-12.5%,-10%,120%,120%,1);
|
||||||
|
.bg-norepeat("overlay","png");
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.video-con {
|
||||||
|
.prLayout(650px,900px);
|
||||||
|
// border: 1px solid #fff;
|
||||||
|
.video {
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
// width: 700px;
|
||||||
|
// height: 700px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.btn,
|
||||||
|
.btn2 {
|
||||||
|
margin: 50px;
|
||||||
|
background-color: #fff;
|
||||||
|
.prLayout(200px,50px);
|
||||||
|
line-height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.btn2 {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
.photo {
|
||||||
|
visibility: hidden;
|
||||||
|
.prLayout(750px,1000px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -7,34 +7,24 @@
|
|||||||
* @FilePath: /xfhd-vue-scaffold/src/page/index/Home/Index.vue
|
* @FilePath: /xfhd-vue-scaffold/src/page/index/Home/Index.vue
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="color">
|
<div class="color">
|
||||||
<Color></Color>
|
<Color></Color>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
// @ is an alias to /src
|
// @ is an alias to /src
|
||||||
import Color from "@/components/color/index.vue";
|
import Color from "@/components/color/index.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Index",
|
name: "Index",
|
||||||
components: { Color },
|
components: { Color },
|
||||||
mounted() {},
|
mounted() {},
|
||||||
methods: {
|
methods: {},
|
||||||
showTips() {
|
|
||||||
this.$weui.topTips("正在努力开发中……敬请期待", {
|
|
||||||
duration: 1500,
|
|
||||||
className: "custom-classname",
|
|
||||||
callback: function () {
|
|
||||||
// console.log('close');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.color {
|
.color {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
405
src/page/index/HandTrack/index.vue
Normal file
405
src/page/index/HandTrack/index.vue
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
<template>
|
||||||
|
<div class="hand-track">
|
||||||
|
<video
|
||||||
|
id="gum-local"
|
||||||
|
class="video"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
autoplay
|
||||||
|
playsinline
|
||||||
|
webkit-playsinline
|
||||||
|
x5-playsinline
|
||||||
|
ref="myVideo"
|
||||||
|
></video>
|
||||||
|
|
||||||
|
<!-- 获取权限 -->
|
||||||
|
<button
|
||||||
|
id="showVideo"
|
||||||
|
class="btn"
|
||||||
|
ref="showVideoBtn"
|
||||||
|
@click="initVideo($event)"
|
||||||
|
>
|
||||||
|
开启摄像头
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- info -->
|
||||||
|
<div class="info-dialog">
|
||||||
|
<div class="progress" ref="progress">
|
||||||
|
当前进度: {{ progressText }}..
|
||||||
|
</div>
|
||||||
|
<div class="status">
|
||||||
|
当前手势: <span>{{ handStatus }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- unsuit-dialog -->
|
||||||
|
<div class="unsuit-dialog" ref="unsuit">请在浏览器中打开</div>
|
||||||
|
<div class="unsuit-dialog" ref="unsuit2">您的系统版本过低</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
// @ is an alias to /src
|
||||||
|
import gsap from "gsap";
|
||||||
|
import {
|
||||||
|
IEngine,
|
||||||
|
Load,
|
||||||
|
IHandTrackingApi,
|
||||||
|
MediaStreamErrorEnum,
|
||||||
|
EventEnum,
|
||||||
|
} from "@handtracking.io/yoha";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "handTrack",
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
progressText: "0%", //进度文字
|
||||||
|
BORDER_PADDING_FACTOR: 0.01, //边界阀值
|
||||||
|
VIDEO_WIDTH_FACTOR: 0.8, //宽度阀值
|
||||||
|
videoRealSize: {},
|
||||||
|
handStatus: "未检测到手",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.video = this.$refs.myVideo;
|
||||||
|
|
||||||
|
this.checkUserDeviceSuitable();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 检测用户手机是否兼容
|
||||||
|
checkUserDeviceSuitable() {
|
||||||
|
if (
|
||||||
|
window.deviceInfo.system === "IOS" &&
|
||||||
|
window.deviceInfo.app === "WX"
|
||||||
|
) {
|
||||||
|
let iosV = this.getIOSVersion();
|
||||||
|
console.log(
|
||||||
|
!this.versionStringCompare(iosV, 14.5),
|
||||||
|
this.versionStringCompare(iosV, 11)
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
!this.versionStringCompare(iosV, 14.5) &&
|
||||||
|
this.versionStringCompare(iosV, 11)
|
||||||
|
) {
|
||||||
|
gsap.to(this.$refs.unsuit, { autoAlpha: 1 });
|
||||||
|
} else if (!this.versionStringCompare(iosV, 11)) {
|
||||||
|
gsap.to(this.$refs.unsuit2, { autoAlpha: 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 版本号比较
|
||||||
|
versionStringCompare(preVersion = "", lastVersion = "") {
|
||||||
|
var sources = preVersion.split(".");
|
||||||
|
var dests = lastVersion.split(".");
|
||||||
|
var maxL = Math.max(sources.length, dests.length);
|
||||||
|
var result = 0;
|
||||||
|
for (let i = 0; i < maxL; i++) {
|
||||||
|
let preValue = sources.length > i ? sources[i] : 0;
|
||||||
|
let preNum = isNaN(Number(preValue))
|
||||||
|
? preValue.charCodeAt()
|
||||||
|
: Number(preValue);
|
||||||
|
let lastValue = dests.length > i ? dests[i] : 0;
|
||||||
|
let lastNum = isNaN(Number(lastValue))
|
||||||
|
? lastValue.charCodeAt()
|
||||||
|
: Number(lastValue);
|
||||||
|
if (preNum < lastNum) {
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
} else if (preNum > lastNum) {
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
// 获取设备权限
|
||||||
|
getDevicePermission(constraints) {
|
||||||
|
if (navigator.mediaDevices.getUserMedia === undefined) {
|
||||||
|
navigator.mediaDevices.getUserMedia = function (constraints) {
|
||||||
|
var getUserMedia =
|
||||||
|
navigator.getUserMedia ||
|
||||||
|
navigator.webkitGetUserMedia ||
|
||||||
|
navigator.mozGetUserMedia ||
|
||||||
|
navigator.msGetUserMedia ||
|
||||||
|
navigator.oGetUserMedia;
|
||||||
|
if (!getUserMedia) {
|
||||||
|
return Promise.reject(
|
||||||
|
new Error(
|
||||||
|
"getUserMedia is not implemented in this browser"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
getUserMedia.call(
|
||||||
|
navigator,
|
||||||
|
constraints,
|
||||||
|
resolve,
|
||||||
|
reject
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return global.navigator.mediaDevices
|
||||||
|
.getUserMedia(constraints)
|
||||||
|
.then((stream) => {
|
||||||
|
if (stream) {
|
||||||
|
stopStreamTracks(stream);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error("EmptyStreamError"));
|
||||||
|
})
|
||||||
|
.catch((errMsg) => {
|
||||||
|
if (errMsg && "NotAllowedError" === errMsg.name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Promise.reject(errMsg);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 开始获取权限
|
||||||
|
requestPermission() {
|
||||||
|
return this.getDevicePermission({ video: true, audio: true })
|
||||||
|
.catch(() =>
|
||||||
|
this.getDevicePermission({ video: false, audio: true })
|
||||||
|
)
|
||||||
|
.catch(() =>
|
||||||
|
this.getDevicePermission({ video: true, audio: false })
|
||||||
|
)
|
||||||
|
.catch(() => true);
|
||||||
|
},
|
||||||
|
// 获取摄像头设备id
|
||||||
|
async getBackCameraDeviceId() {
|
||||||
|
let source = new Array();
|
||||||
|
let devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
|
if (devices.length > 0) {
|
||||||
|
devices.forEach(function (device) {
|
||||||
|
if (device.kind == "videoinput") {
|
||||||
|
source.push(device);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return source[source.length - 1].deviceId;
|
||||||
|
},
|
||||||
|
// 初始化 video
|
||||||
|
async initVideo(e) {
|
||||||
|
const constraints = {
|
||||||
|
video: {
|
||||||
|
deviceId: { exact: await this.getBackCameraDeviceId() },
|
||||||
|
facingMode: "environment",
|
||||||
|
},
|
||||||
|
// video: {
|
||||||
|
// facingMode: { exact: "environment" },
|
||||||
|
// width: { min: 375, ideal: 375, max: 750 },
|
||||||
|
// height: { min: 590, ideal: 590, max: 1624 },
|
||||||
|
// },
|
||||||
|
};
|
||||||
|
|
||||||
|
this.video.play();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.stream = await navigator.mediaDevices.getUserMedia(
|
||||||
|
constraints
|
||||||
|
);
|
||||||
|
|
||||||
|
gsap.to(e.target, { autoAlpha: 0 });
|
||||||
|
e.target.disabled = true;
|
||||||
|
|
||||||
|
// 处理成功回调
|
||||||
|
this.handleSuccess(this.stream, constraints);
|
||||||
|
} catch (e) {
|
||||||
|
this.handleError(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 处理stream获取成功
|
||||||
|
async handleSuccess(stream, constraints) {
|
||||||
|
const videoTracks = stream.getVideoTracks();
|
||||||
|
this.stream = stream; // make variable available to browser console
|
||||||
|
let streamSize = this.GetStreamDimensions(stream);
|
||||||
|
let handledSize = this.ScaleResolutionToWidth(
|
||||||
|
streamSize,
|
||||||
|
window.innerWidth
|
||||||
|
);
|
||||||
|
|
||||||
|
this.videoRealSize = handledSize;
|
||||||
|
|
||||||
|
console.log("Got stream with constraints:", constraints);
|
||||||
|
console.log(`Using video device: ${videoTracks[0].label}`);
|
||||||
|
console.log("Got stream size:", streamSize);
|
||||||
|
console.log(
|
||||||
|
"Got streamHandled size:",
|
||||||
|
window.innerWidth,
|
||||||
|
handledSize
|
||||||
|
);
|
||||||
|
|
||||||
|
this.responseVideo(handledSize);
|
||||||
|
this.video.srcObject = stream;
|
||||||
|
|
||||||
|
// 开始识别
|
||||||
|
this.startDraw();
|
||||||
|
},
|
||||||
|
// 处理stream获取错误
|
||||||
|
handleError(error) {
|
||||||
|
console.error(error);
|
||||||
|
},
|
||||||
|
// 视频设置
|
||||||
|
responseVideo(size) {
|
||||||
|
this.video.width = size.width;
|
||||||
|
this.video.height = size.height;
|
||||||
|
},
|
||||||
|
// 获得stream大小
|
||||||
|
GetStreamDimensions(stream) {
|
||||||
|
return {
|
||||||
|
width: stream.getVideoTracks()[0].getSettings().width,
|
||||||
|
height: stream.getVideoTracks()[0].getSettings().height,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// 等比缩放视频
|
||||||
|
ScaleResolutionToWidth(resolution, width) {
|
||||||
|
const cw = resolution.width;
|
||||||
|
const ch = resolution.height;
|
||||||
|
const tw = width;
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: tw,
|
||||||
|
height: ch / (cw / tw),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// 创建手势识别引擎
|
||||||
|
async CreateEngine() {
|
||||||
|
let API = IHandTrackingApi;
|
||||||
|
if (API) {
|
||||||
|
return API.CreateEngine();
|
||||||
|
}
|
||||||
|
API = await Load("./yoha");
|
||||||
|
return API.CreateEngine();
|
||||||
|
},
|
||||||
|
// 开始识别
|
||||||
|
async startDraw() {
|
||||||
|
this.engine = await this.CreateEngine();
|
||||||
|
await this.engine.DownloadModel((progress) => {
|
||||||
|
this.progressText = `${Math.round(progress * 100)}%`;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.progressText = "引擎准备中…";
|
||||||
|
this.engine.Configure({
|
||||||
|
// Webcam video is usually flipped so we want the coordinates to be flipped as well.
|
||||||
|
flipX: false,
|
||||||
|
// Crop away a small area at the border to prevent the user to move out of view
|
||||||
|
// when reaching for border areas on the canvas.
|
||||||
|
padding: this.BORDER_PADDING_FACTOR,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.engine.SetUpCustomTrackSource(this.video);
|
||||||
|
// await this.engine.SetUpCameraTrackSource();
|
||||||
|
|
||||||
|
// ios需要预热
|
||||||
|
if (window.deviceInfo.system === "IOS") {
|
||||||
|
await this.engine.Warmup();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.progressText = "引擎已就绪";
|
||||||
|
gsap.to(this.$refs.progress, {
|
||||||
|
autoAlpha: 0,
|
||||||
|
delay: 0.5,
|
||||||
|
onComplete: () => {
|
||||||
|
this.$refs.progress.style.display = "none";
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
this.engine.Start((e) => {
|
||||||
|
if (e.type === EventEnum.RESULT) {
|
||||||
|
if (e.poses.fist) {
|
||||||
|
this.handStatus = "握拳";
|
||||||
|
// document.getElementById("status").innerText = "握拳";
|
||||||
|
} else if (e.poses.pinch) {
|
||||||
|
this.handStatus = "捏合";
|
||||||
|
// document.getElementById("status").innerText = "捏合";
|
||||||
|
} else {
|
||||||
|
this.handStatus = "张开";
|
||||||
|
// document.getElementById("status").innerText = "张开";
|
||||||
|
}
|
||||||
|
} else if (e.type === EventEnum.LOST) {
|
||||||
|
this.handStatus = "未检测到手";
|
||||||
|
// document.getElementById("status").innerText = "未检测到手";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 获取ios版本号
|
||||||
|
getIOSVersion() {
|
||||||
|
let str = navigator.userAgent.toLowerCase();
|
||||||
|
let ver = str.match(/cpu iphone os (.*?) like mac os/);
|
||||||
|
if (!ver) {
|
||||||
|
console.log("请在Ios系统中打开");
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
"你当前的Ios系统版本为:" + ver[1].replace(/_/g, ".")
|
||||||
|
);
|
||||||
|
return ver[1].replace(/_/g, ".");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped lang="less">
|
||||||
|
.hand-track {
|
||||||
|
.prLayout(100%,100vh);
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
.video {
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
// transform: scaleX(-1);
|
||||||
|
width: 750px;
|
||||||
|
height: auto;
|
||||||
|
// height: 700px;
|
||||||
|
}
|
||||||
|
.info-dialog {
|
||||||
|
.paLayout(0,0, 50%,130px,2);
|
||||||
|
background-color: rgba(255, 255, 255, 0.25);
|
||||||
|
border-radius: 0 0 30px 0;
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 28px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: left;
|
||||||
|
text-indent: 10px;
|
||||||
|
justify-content: center;
|
||||||
|
div {
|
||||||
|
width: 100%;
|
||||||
|
line-height: 40px;
|
||||||
|
color: #fff;
|
||||||
|
span {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #f00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.progress {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
.paCenterBottom(200px,280px,80px,2);
|
||||||
|
background-color: #fff;
|
||||||
|
line-height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
.unsuit-dialog {
|
||||||
|
visibility: hidden;
|
||||||
|
.paCenterBottom(0, 100%,80px,10);
|
||||||
|
position: fixed;
|
||||||
|
background-color: rgba(255, 255, 255, 0.35);
|
||||||
|
color: #fff;
|
||||||
|
line-height: 80px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -7,168 +7,178 @@
|
|||||||
* @FilePath: /xfhd-vue-scaffold/src/page/index/Home/Index.vue
|
* @FilePath: /xfhd-vue-scaffold/src/page/index/Home/Index.vue
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="home">
|
<div class="home">
|
||||||
<Shader></Shader>
|
<Shader></Shader>
|
||||||
<div class="overlay"></div>
|
<div class="overlay"></div>
|
||||||
<div class="page grid js_show dialog">
|
<div class="page grid js_show dialog">
|
||||||
<div class="page__hd">
|
<div class="page__hd">
|
||||||
<h1 class="page__title" style="font-size: 20px">
|
<h1 class="page__title" style="font-size: 20px">
|
||||||
大板栗的玩具屋
|
大板栗的玩具屋
|
||||||
</h1>
|
</h1>
|
||||||
<p class="page__desc" style="font-size: 18px">玩具列表</p>
|
<p class="page__desc" style="font-size: 18px">玩具列表</p>
|
||||||
<p class="page__desc">have fun!</p>
|
<p class="page__desc">have fun!</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="weui-grids" style="margin-top: 100px">
|
<div class="weui-grids" style="margin-top: 100px">
|
||||||
<div
|
<div
|
||||||
style="opacity: 0.5"
|
style="opacity: 0.5"
|
||||||
@click="jump(1)"
|
@click="jump(1)"
|
||||||
class="weui-grid link"
|
class="weui-grid link"
|
||||||
>
|
>
|
||||||
<div class="weui-grid__icon">
|
<div class="weui-grid__icon">
|
||||||
<span class="iconfont"></span>
|
<span class="iconfont"></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="weui-grid__label">Color</p>
|
<p class="weui-grid__label">Color</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style="opacity: 0.5"
|
style="opacity: 0.5"
|
||||||
@click="jump(2)"
|
@click="jump(2)"
|
||||||
class="weui-grid link"
|
class="weui-grid link"
|
||||||
>
|
>
|
||||||
<div class="weui-grid__icon">
|
<div class="weui-grid__icon">
|
||||||
<span class="iconfont"></span>
|
<span class="iconfont"></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="weui-grid__label">AR Paint</p>
|
<p class="weui-grid__label">AR Paint</p>
|
||||||
</div>
|
</div>
|
||||||
<div style="opacity: 0.5" @click="jump(3)" class="weui-grid">
|
<div style="opacity: 0.5" @click="jump(3)" class="weui-grid">
|
||||||
<div class="weui-grid__icon">
|
<div class="weui-grid__icon">
|
||||||
<span class="iconfont"></span>
|
<span class="iconfont"></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="weui-grid__label">AR HIT</p>
|
<p class="weui-grid__label">AR HIT</p>
|
||||||
</div>
|
</div>
|
||||||
<a
|
<div
|
||||||
href="#"
|
style="opacity: 0.5"
|
||||||
class="weui-grid"
|
@click="jump(4)"
|
||||||
style="opacity: 0.5"
|
class="weui-grid link"
|
||||||
@click="showTips"
|
>
|
||||||
>
|
<div class="weui-grid__icon">
|
||||||
<div class="weui-grid__icon">
|
<span class="iconfont"></span>
|
||||||
<span class="iconfont"></span>
|
</div>
|
||||||
</div>
|
<p class="weui-grid__label">摄像机</p>
|
||||||
<p class="weui-grid__label">...</p>
|
</div>
|
||||||
</a>
|
<div class="weui-grid" style="opacity: 0.5" @click="jump(5)">
|
||||||
<a
|
<div class="weui-grid__icon">
|
||||||
href="#"
|
<span class="iconfont"></span>
|
||||||
class="weui-grid"
|
</div>
|
||||||
style="opacity: 0.5"
|
<p class="weui-grid__label">手势检测</p>
|
||||||
@click="showTips"
|
</div>
|
||||||
>
|
<div class="weui-grid" style="opacity: 0.5">
|
||||||
<div class="weui-grid__icon">
|
<div class="weui-grid__icon">
|
||||||
<span class="iconfont"></span>
|
<span class="iconfont"></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="weui-grid__label">预留</p>
|
<p class="weui-grid__label">...</p>
|
||||||
</a>
|
</div>
|
||||||
<a
|
</div>
|
||||||
href="#"
|
</div>
|
||||||
class="weui-grid"
|
</div>
|
||||||
style="opacity: 0.5"
|
|
||||||
@click="showTips"
|
|
||||||
>
|
|
||||||
<div class="weui-grid__icon">
|
|
||||||
<span class="iconfont"></span>
|
|
||||||
</div>
|
|
||||||
<p class="weui-grid__label">...</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
// @ is an alias to /src
|
// @ is an alias to /src
|
||||||
import Shader from "@/components/shader/index.vue";
|
import Shader from "@/components/shader/index.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Index",
|
name: "Index",
|
||||||
components: {
|
components: {
|
||||||
Shader,
|
Shader,
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// this.$weui.toast('即将跳转至项目列表页', {
|
// this.$weui.toast('即将跳转至项目列表页', {
|
||||||
// duration: 3500,
|
// duration: 3500,
|
||||||
// className: "toast-warn",
|
// className: "toast-warn",
|
||||||
// });
|
// });
|
||||||
// setTimeout(() => {
|
// setTimeout(() => {
|
||||||
// location.href = './project-list.html'
|
// location.href = './project-list.html'
|
||||||
// }, 3500);
|
// }, 3500);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 跳转
|
// 跳转
|
||||||
jump(id) {
|
jump(id) {
|
||||||
// 第一个游戏
|
// 第一个游戏
|
||||||
if (id == 1) {
|
if (id == 1) {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: "Color",
|
name: "Color",
|
||||||
params: {},
|
params: {},
|
||||||
});
|
});
|
||||||
} else if (id == 2) {
|
} else if (id == 2) {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: "AR",
|
name: "AR",
|
||||||
params: {},
|
params: {},
|
||||||
});
|
});
|
||||||
} else if (id == 3) {
|
} else if (id == 3) {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: "ARHit",
|
name: "ARHit",
|
||||||
params: {},
|
params: {},
|
||||||
});
|
});
|
||||||
}
|
} else if (id == 4) {
|
||||||
},
|
this.$router.push({
|
||||||
showTips() {
|
name: "Camera",
|
||||||
this.$weui.topTips("正在努力开发中……敬请期待", {
|
params: {},
|
||||||
duration: 1500,
|
});
|
||||||
className: "custom-classname",
|
} else if (id == 5) {
|
||||||
callback: function () {
|
this.$router.push({
|
||||||
// console.log('close');
|
name: "HandTrack",
|
||||||
},
|
});
|
||||||
});
|
}
|
||||||
},
|
},
|
||||||
},
|
showTips() {},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.home {
|
.home {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
.overlay {
|
.overlay {
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
.paLayout(0,0,100%,100%,101);
|
.paLayout(0,0,100%,100%,101);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.link {
|
.link {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.dialog {
|
.dialog {
|
||||||
.paLayout(0,0,100%,50%,102);
|
.paLayout(0,0,100%,50%,102);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
.weui-grids::before,
|
.weui-grids {
|
||||||
.weui-grids::after,
|
display: flex;
|
||||||
.weui-grid:before,
|
flex-direction: row;
|
||||||
.weui-grid:after {
|
justify-content: center;
|
||||||
display: none;
|
flex-wrap: wrap;
|
||||||
}
|
font-size: 30px;
|
||||||
.weui-grid__label {
|
.weui-grid {
|
||||||
color: #fff;
|
display: inline-block;
|
||||||
}
|
width: 33.33%;
|
||||||
.weui-grid__icon {
|
height: 150px;
|
||||||
display: flex;
|
margin-top: 10px;
|
||||||
flex-direction: column;
|
.iconfont {
|
||||||
justify-content: center;
|
font-size: 40px;
|
||||||
align-items: center;
|
}
|
||||||
.iconfont {
|
.weui-grid__label {
|
||||||
font-size: 30px;
|
line-height: 80px;
|
||||||
}
|
text-align: center;
|
||||||
}
|
}
|
||||||
.page__hd {
|
}
|
||||||
padding: 40px;
|
}
|
||||||
}
|
.weui-grids::before,
|
||||||
}
|
.weui-grids::after,
|
||||||
|
.weui-grid:before,
|
||||||
|
.weui-grid:after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.weui-grid__label {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.weui-grid__icon {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
.iconfont {
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.page__hd {
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -20,9 +20,9 @@ import {
|
|||||||
} from 'gsap'
|
} from 'gsap'
|
||||||
import '@/assets/css/reset.less'
|
import '@/assets/css/reset.less'
|
||||||
// import imgList from '@/preload/imgList.js' // 预加载资源图
|
// import imgList from '@/preload/imgList.js' // 预加载资源图
|
||||||
import weui from 'weui'
|
// import weui from 'weui'
|
||||||
import '@/assets/css/weui-2.0.1.css';
|
// import '@/assets/css/weui-2.0.1.css';
|
||||||
import '@/assets/css/weui-for-work.css'
|
// import '@/assets/css/weui-for-work.css'
|
||||||
// import VueLazyload from 'vue-lazyload' lazyload 懒加载
|
// import VueLazyload from 'vue-lazyload' lazyload 懒加载
|
||||||
|
|
||||||
// fix swiper6 with vue-awesome-swiper bug
|
// fix swiper6 with vue-awesome-swiper bug
|
||||||
@ -40,7 +40,7 @@ Vue.config.productionTip = false
|
|||||||
// 挂载工具集
|
// 挂载工具集
|
||||||
Vue.prototype.$Utils = utils;
|
Vue.prototype.$Utils = utils;
|
||||||
// 引入 weui
|
// 引入 weui
|
||||||
Vue.prototype.$weui = weui
|
// Vue.prototype.$weui = weui
|
||||||
|
|
||||||
// init xgl plugins
|
// init xgl plugins
|
||||||
utils.initial({
|
utils.initial({
|
||||||
|
|||||||
@ -12,6 +12,9 @@ import Home from '../Home/index.vue'
|
|||||||
import Color from '../Color/index.vue'
|
import Color from '../Color/index.vue'
|
||||||
import AR from '../AR/index.vue'
|
import AR from '../AR/index.vue'
|
||||||
import ARHit from '../ARHit/index.vue'
|
import ARHit from '../ARHit/index.vue'
|
||||||
|
import Camera from '../Camera/index.vue'
|
||||||
|
import HandTrack from '../HandTrack/index.vue'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
@ -62,6 +65,26 @@ const routes = [
|
|||||||
keepAlive: false, // 是否保持活跃
|
keepAlive: false, // 是否保持活跃
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/camera",
|
||||||
|
name: "Camera",
|
||||||
|
component: Camera,
|
||||||
|
meta: {
|
||||||
|
title: "camera test", // 标题
|
||||||
|
keepAlive: false, // 是否保持活跃
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/track",
|
||||||
|
name: "HandTrack",
|
||||||
|
component: HandTrack,
|
||||||
|
meta: {
|
||||||
|
title: "Hand Track", // 标题
|
||||||
|
keepAlive: false, // 是否保持活跃
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
// {
|
// {
|
||||||
// path: "/example",
|
// path: "/example",
|
||||||
// name: "example",
|
// name: "example",
|
||||||
|
|||||||
15
tsconfig.json
Normal file
15
tsconfig.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "commonjs",
|
||||||
|
"strict": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"experimentalDecorators": true
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"dist"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@ const path = require('path');
|
|||||||
const CompressionPlugin = require('compression-webpack-plugin');
|
const CompressionPlugin = require('compression-webpack-plugin');
|
||||||
const vConsolePlugin = require("vconsole-webpack-plugin");
|
const vConsolePlugin = require("vconsole-webpack-plugin");
|
||||||
const TinyimgPlugin = require("tinyimg-webpack-plugin");
|
const TinyimgPlugin = require("tinyimg-webpack-plugin");
|
||||||
|
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||||
|
|
||||||
function resolve(dir) {
|
function resolve(dir) {
|
||||||
return path.join(__dirname, dir);
|
return path.join(__dirname, dir);
|
||||||
@ -83,7 +84,54 @@ module.exports = {
|
|||||||
logged: true
|
logged: true
|
||||||
})]
|
})]
|
||||||
|
|
||||||
|
// 配置 copy plguins
|
||||||
|
let copyImg = [
|
||||||
|
new CopyWebpackPlugin([
|
||||||
|
// This is required so that yoha can load model files etc.
|
||||||
|
{ from: 'node_modules/@handtracking.io/yoha/', to: 'yoha/' },
|
||||||
|
// Required for github pages...
|
||||||
|
{ from: 'node_modules/coi-serviceworker/coi-serviceworker.min.js', to: './' },
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
config.plugins = [...config.plugins,
|
||||||
|
...pluginsDev,
|
||||||
|
...tinyimg,
|
||||||
|
...copyImg,
|
||||||
|
];
|
||||||
|
|
||||||
config.module.rules.push(
|
config.module.rules.push(
|
||||||
|
// ts加载
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'ts-loader',
|
||||||
|
options: {
|
||||||
|
transpileOnly: true,
|
||||||
|
appendTsSuffixTo: [/\.vue$/],
|
||||||
|
happyPackMode: true // 这个改为true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
//wasm加载
|
||||||
|
{
|
||||||
|
test: /\.wasm$/i,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'file-loader', // 解决wasm加载问题
|
||||||
|
options: {
|
||||||
|
name: './static/wasm/[name].[ext]'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
//模型加载
|
//模型加载
|
||||||
{
|
{
|
||||||
test: /\.(stl|obj|fbx|mtl|glb|gltf)?$/,
|
test: /\.(stl|obj|fbx|mtl|glb|gltf)?$/,
|
||||||
@ -102,11 +150,6 @@ module.exports = {
|
|||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
|
|
||||||
config.plugins = [...config.plugins,
|
|
||||||
...pluginsDev,
|
|
||||||
...tinyimg
|
|
||||||
];
|
|
||||||
|
|
||||||
// 配置gzip压缩
|
// 配置gzip压缩
|
||||||
if (process.env.NODE_ENV === 'production') {
|
if (process.env.NODE_ENV === 'production') {
|
||||||
return {
|
return {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user