准备添加three场景
调试ios授权
This commit is contained in:
parent
15a990124c
commit
fb1d34bcf4
@ -75,7 +75,6 @@
|
|||||||
<use x="170" y="25" xlink:href="#single" class="leaf l-36" id="leaf36"></use>
|
<use x="170" y="25" xlink:href="#single" class="leaf l-36" id="leaf36"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>精彩即将为您呈现...</p>
|
<p>精彩即将为您呈现...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
playsinline
|
playsinline
|
||||||
webkit-playsinline
|
webkit-playsinline
|
||||||
x5-playsinline
|
x5-playsinline
|
||||||
|
muted
|
||||||
ref="myVideo"
|
ref="myVideo"
|
||||||
></video>
|
></video>
|
||||||
|
|
||||||
@ -39,6 +40,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- canvas -->
|
||||||
|
<canvas class="canvas" ref="canvas"></canvas>
|
||||||
|
|
||||||
<!-- hand -->
|
<!-- hand -->
|
||||||
<div
|
<div
|
||||||
class="hand-dialog"
|
class="hand-dialog"
|
||||||
@ -63,6 +67,7 @@ import {
|
|||||||
MediaStreamErrorEnum,
|
MediaStreamErrorEnum,
|
||||||
EventEnum,
|
EventEnum,
|
||||||
} from "@handtracking.io/yoha";
|
} from "@handtracking.io/yoha";
|
||||||
|
import * as THREE from "three";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "handTrack",
|
name: "handTrack",
|
||||||
@ -76,31 +81,34 @@ export default {
|
|||||||
videoRealSize: {},
|
videoRealSize: {},
|
||||||
handStatus: "未检测到手",
|
handStatus: "未检测到手",
|
||||||
handStep: 1,
|
handStep: 1,
|
||||||
|
meshAdded: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.video = this.$refs.myVideo;
|
this.video = this.$refs.myVideo;
|
||||||
|
this.canvas = this.$refs.canvas;
|
||||||
|
|
||||||
|
this.initTHREELayer();
|
||||||
this.checkUserDeviceSuitable();
|
this.checkUserDeviceSuitable();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 检测用户手机是否兼容
|
// 检测用户手机是否兼容
|
||||||
// > 14 safria ok || > 14.3 ios webview ok
|
// > 14.3 ios ok
|
||||||
checkUserDeviceSuitable() {
|
checkUserDeviceSuitable() {
|
||||||
if (
|
if (
|
||||||
window.deviceInfo.system === "IOS" &&
|
window.deviceInfo.system === "IOS"
|
||||||
window.deviceInfo.app === "WX"
|
// && window.deviceInfo.app === "WX"
|
||||||
) {
|
) {
|
||||||
let iosV = this.getIOSVersion();
|
let iosV = this.getIOSVersion();
|
||||||
if (
|
if (
|
||||||
!this.versionStringCompare(iosV, "14.3") &&
|
!this.versionStringCompare(iosV, "14.3")
|
||||||
this.versionStringCompare(iosV, "14.0")
|
// && this.versionStringCompare(iosV, "14.0")
|
||||||
) {
|
) {
|
||||||
this.$Utils.showTips({
|
// this.$Utils.showTips({
|
||||||
message: "请点击右上角 ...</br>在浏览器打开",
|
// message: "请点击右上角 ...</br>在浏览器打开",
|
||||||
autoClose: false,
|
// autoClose: false,
|
||||||
});
|
// });
|
||||||
} else if (!this.versionStringCompare(iosV, "14.0")) {
|
// } else if (!this.versionStringCompare(iosV, "14.0")) {
|
||||||
this.$Utils.showTips({
|
this.$Utils.showTips({
|
||||||
message:
|
message:
|
||||||
"😭 很抱歉</br>⚠️ 当前系统版本过低</br>无法体验该Demo",
|
"😭 很抱歉</br>⚠️ 当前系统版本过低</br>无法体验该Demo",
|
||||||
@ -162,11 +170,16 @@ export default {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return global.navigator.mediaDevices
|
return navigator.mediaDevices
|
||||||
.getUserMedia(constraints)
|
.getUserMedia(constraints)
|
||||||
.then((stream) => {
|
.then((stream) => {
|
||||||
if (stream) {
|
if (stream) {
|
||||||
stopStreamTracks(stream);
|
const tracks = stream.getTracks();
|
||||||
|
tracks.forEach(function (track) {
|
||||||
|
track.stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
// stopStreamTracks(stream);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return Promise.reject(new Error("EmptyStreamError"));
|
return Promise.reject(new Error("EmptyStreamError"));
|
||||||
@ -178,21 +191,26 @@ export default {
|
|||||||
return Promise.reject(errMsg);
|
return Promise.reject(errMsg);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 开始获取权限
|
// IOS 用户获取授权
|
||||||
requestPermission() {
|
requestPermission() {
|
||||||
return this.getDevicePermission({ video: true, audio: true })
|
return (
|
||||||
.catch(() =>
|
this.getDevicePermission({ video: true })
|
||||||
this.getDevicePermission({ video: false, audio: true })
|
// .catch(() =>
|
||||||
)
|
// this.getDevicePermission({ video: false, audio: true })
|
||||||
.catch(() =>
|
// )
|
||||||
this.getDevicePermission({ video: true, audio: false })
|
// .catch(() =>
|
||||||
)
|
// this.getDevicePermission({ video: true, audio: true })
|
||||||
.catch(() => true);
|
// )
|
||||||
|
.catch(() => true)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
// 获取摄像头设备id
|
// 获取摄像头设备id
|
||||||
async getBackCameraDeviceId() {
|
async getBackCameraDeviceId() {
|
||||||
|
await this.requestPermission();
|
||||||
let source = new Array();
|
let source = new Array();
|
||||||
|
console.log("start get camera devices");
|
||||||
let devices = await navigator.mediaDevices.enumerateDevices();
|
let devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
|
console.log("devices array:", devices);
|
||||||
if (devices.length > 0) {
|
if (devices.length > 0) {
|
||||||
devices.forEach(function (device) {
|
devices.forEach(function (device) {
|
||||||
if (device.kind == "videoinput") {
|
if (device.kind == "videoinput") {
|
||||||
@ -200,6 +218,7 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
console.log("devices source:", source);
|
||||||
return source[source.length - 1].deviceId;
|
return source[source.length - 1].deviceId;
|
||||||
},
|
},
|
||||||
// 初始化 video
|
// 初始化 video
|
||||||
@ -222,8 +241,6 @@ export default {
|
|||||||
// },
|
// },
|
||||||
};
|
};
|
||||||
|
|
||||||
this.video.play();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.stream = await navigator.mediaDevices.getUserMedia(
|
this.stream = await navigator.mediaDevices.getUserMedia(
|
||||||
constraints
|
constraints
|
||||||
@ -243,12 +260,12 @@ export default {
|
|||||||
const videoTracks = stream.getVideoTracks();
|
const videoTracks = stream.getVideoTracks();
|
||||||
this.stream = stream; // make variable available to browser console
|
this.stream = stream; // make variable available to browser console
|
||||||
let streamSize = this.GetStreamDimensions(stream);
|
let streamSize = this.GetStreamDimensions(stream);
|
||||||
let handledSize = this.ScaleResolutionToHeight(
|
// let handledSize = this.ScaleResolutionToHeight(
|
||||||
streamSize,
|
// streamSize,
|
||||||
window.innerHeight
|
// window.innerHeight
|
||||||
);
|
// );
|
||||||
|
|
||||||
this.videoRealSize = handledSize;
|
// this.videoRealSize = handledSize;
|
||||||
|
|
||||||
console.log("Got stream with constraints:", constraints);
|
console.log("Got stream with constraints:", constraints);
|
||||||
console.log(`Using video device: ${videoTracks[0].label}`);
|
console.log(`Using video device: ${videoTracks[0].label}`);
|
||||||
@ -256,13 +273,15 @@ export default {
|
|||||||
console.log("Got stream size:", streamSize);
|
console.log("Got stream size:", streamSize);
|
||||||
console.log(
|
console.log(
|
||||||
"Got streamHandled size:",
|
"Got streamHandled size:",
|
||||||
window.innerHeight,
|
window.innerHeight
|
||||||
handledSize
|
// handledSize
|
||||||
);
|
);
|
||||||
|
|
||||||
this.responseVideo(handledSize);
|
// this.responseVideoAndCanvas(handledSize);
|
||||||
this.video.srcObject = stream;
|
this.video.srcObject = stream;
|
||||||
|
|
||||||
|
// this.video.play();
|
||||||
|
|
||||||
// 开始识别
|
// 开始识别
|
||||||
this.startDraw();
|
this.startDraw();
|
||||||
},
|
},
|
||||||
@ -271,9 +290,14 @@ export default {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
},
|
},
|
||||||
// 视频设置
|
// 视频设置
|
||||||
responseVideo(size) {
|
responseVideoAndCanvas(size) {
|
||||||
this.video.width = size.width;
|
this.video.width = size.width;
|
||||||
this.video.height = size.height;
|
this.video.height = size.height;
|
||||||
|
|
||||||
|
// init canvcas
|
||||||
|
this.ctx = this.canvas.getContext("2d");
|
||||||
|
this.canvas.width = size.width;
|
||||||
|
this.canvas.height = size.height;
|
||||||
},
|
},
|
||||||
// 获得stream大小
|
// 获得stream大小
|
||||||
GetStreamDimensions(stream) {
|
GetStreamDimensions(stream) {
|
||||||
@ -327,6 +351,7 @@ export default {
|
|||||||
this.progress = Math.round(progress * 100);
|
this.progress = Math.round(progress * 100);
|
||||||
this.progressText = `${this.progress}%`;
|
this.progressText = `${this.progress}%`;
|
||||||
});
|
});
|
||||||
|
console.log("engine model loaded");
|
||||||
|
|
||||||
this.progressText = "引擎准备中…";
|
this.progressText = "引擎准备中…";
|
||||||
this.engine.Configure({
|
this.engine.Configure({
|
||||||
@ -358,16 +383,25 @@ export default {
|
|||||||
autoAlpha: 1,
|
autoAlpha: 1,
|
||||||
delay: 0.5,
|
delay: 0.5,
|
||||||
});
|
});
|
||||||
|
// 识别引擎启动
|
||||||
|
this.engineStart();
|
||||||
|
},
|
||||||
|
// 识别引擎启动
|
||||||
|
engineStart() {
|
||||||
this.engine.Start((e) => {
|
this.engine.Start((e) => {
|
||||||
|
let cursorPos;
|
||||||
if (e.coordinates) {
|
if (e.coordinates) {
|
||||||
const cursorPos = this.ExponentialCoordinateAverage(
|
cursorPos = this.ExponentialCoordinateAverage(
|
||||||
this.ComputeCursorPositionFromCoordinates(e.coordinates)
|
this.ComputeCursorPositionFromCoordinates(e.coordinates)
|
||||||
);
|
);
|
||||||
console.log(cursorPos);
|
console.log(cursorPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// console.log(e.type);
|
||||||
|
|
||||||
if (e.type === EventEnum.RESULT) {
|
if (e.type === EventEnum.RESULT) {
|
||||||
|
this.drawPoint(cursorPos[0], cursorPos[1]);
|
||||||
|
this.Render();
|
||||||
if (e.poses.fist) {
|
if (e.poses.fist) {
|
||||||
this.handStatus = "握拳";
|
this.handStatus = "握拳";
|
||||||
if (this.handStep == 1) {
|
if (this.handStep == 1) {
|
||||||
@ -376,7 +410,6 @@ export default {
|
|||||||
// document.getElementById("status").innerText = "握拳";
|
// document.getElementById("status").innerText = "握拳";
|
||||||
} else if (e.poses.pinch) {
|
} else if (e.poses.pinch) {
|
||||||
this.handStatus = "捏合";
|
this.handStatus = "捏合";
|
||||||
// document.getElementById("status").innerText = "捏合";
|
|
||||||
} else {
|
} else {
|
||||||
this.handStatus = "张开";
|
this.handStatus = "张开";
|
||||||
if (this.handStep == 2) {
|
if (this.handStep == 2) {
|
||||||
@ -445,6 +478,54 @@ export default {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// init THREELayer
|
||||||
|
initTHREELayer() {
|
||||||
|
this.camera_ = new THREE.OrthographicCamera(
|
||||||
|
0,
|
||||||
|
this.videoRealSize.width,
|
||||||
|
0,
|
||||||
|
this.videoRealSize.height,
|
||||||
|
0,
|
||||||
|
1000
|
||||||
|
);
|
||||||
|
this.renderer_ = new THREE.WebGLRenderer({
|
||||||
|
alpha: true,
|
||||||
|
powerPreference: "high-performance",
|
||||||
|
failIfMajorPerformanceCaveat: false,
|
||||||
|
antialias: true,
|
||||||
|
});
|
||||||
|
this.renderer_.domElement = this.canvas;
|
||||||
|
this.renderer_.debug.checkShaderErrors = false;
|
||||||
|
this.renderer_.setSize(
|
||||||
|
this.videoRealSize.width,
|
||||||
|
this.videoRealSize.height
|
||||||
|
);
|
||||||
|
this.renderer_.setPixelRatio(window.devicePixelRatio);
|
||||||
|
this.renderer_.setClearColor(0x000000, 0.0);
|
||||||
|
this.renderer_.autoClear = true;
|
||||||
|
this.scene_ = new THREE.Scene();
|
||||||
|
},
|
||||||
|
// draw pointer
|
||||||
|
drawPoint(x, y) {
|
||||||
|
if (!this.meshAdded) {
|
||||||
|
this.geo_ = new THREE.RingGeometry(0, 8, 30);
|
||||||
|
this.mat_ = new THREE.MeshBasicMaterial({
|
||||||
|
color: "red",
|
||||||
|
side: THREE.DoubleSide,
|
||||||
|
});
|
||||||
|
this.mesh_ = new THREE.Mesh(this.geo_, this.mat_);
|
||||||
|
this.scene_.add(this.mesh_);
|
||||||
|
this.meshAdded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mesh_.position.x = x * this.videoRealSize.width;
|
||||||
|
this.mesh_.position.y = y * this.videoRealSize.height;
|
||||||
|
this.mesh_.position.z = 0;
|
||||||
|
},
|
||||||
|
// THREE canvas render
|
||||||
|
Render() {
|
||||||
|
this.renderer_.render(this.scene_, this.camera_);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@ -459,8 +540,8 @@ export default {
|
|||||||
align-content: center;
|
align-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
.video {
|
.video {
|
||||||
.paLayout(50%,50%,auto,100%,0);
|
// .paLayout(50%,50%,auto,100%,0);
|
||||||
transform: translate(-50%, -50%);
|
// transform: translate(-50%, -50%);
|
||||||
// transform: scaleX(-1);
|
// transform: scaleX(-1);
|
||||||
// width: 750px;
|
// width: 750px;
|
||||||
display: none;
|
display: none;
|
||||||
@ -521,6 +602,12 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.canvas {
|
||||||
|
.paLayout(50%,50%,auto,100%,100);
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
pointer-events: none;
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
.btn {
|
.btn {
|
||||||
.paCenterBottom(50%,280px,80px,2);
|
.paCenterBottom(50%,280px,80px,2);
|
||||||
background-color: rgba(255, 255, 255, 0.85);
|
background-color: rgba(255, 255, 255, 0.85);
|
||||||
@ -534,7 +621,7 @@ export default {
|
|||||||
.paCenter(50%,80%,40px,12);
|
.paCenter(50%,80%,40px,12);
|
||||||
margin-top: -20px;
|
margin-top: -20px;
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
border-radius: 20px;
|
border-radius: 25px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
.bar {
|
.bar {
|
||||||
.prLayout(100%,100%);
|
.prLayout(100%,100%);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user