如何解决带有 A-Frame/AR JS 的基于 Web 的增强现实 (AR) 中的模态图像弹出窗口
我开发了一个基于网络的 AR 应用程序,其中包含命中测试和对象定位。 应用程序使用摄像头检测表面,并通过点击/触摸事件将 glb 3D 图片放在该表面上。
现在,另一部分是当用户点击 glb 图片时,应该弹出一个带有详细图像的模式弹出窗口。但是 pop 在 VR 模式下有效,但在 AR 模式下无效。
Javascript 来了
<script>
// Define a few custom components useful for AR mode. While these are somewhat reusable,// I recommend checking if there are officially supported alternatives before copying
// these into new projects.
// See also https://github.com/aframevr/aframe/pull/4356
AFRAME.registerComponent('hide-in-ar-mode',{
// Set this object invisible while in AR mode.
init: function () {
this.el.sceneEl.addEventListener('enter-vr',(ev) => {
this.wasVisible = this.el.getAttribute('visible');
if (this.el.sceneEl.is('ar-mode')) {
this.el.setAttribute('visible',false);
}
});
this.el.sceneEl.addEventListener('exit-vr',(ev) => {
if (this.wasVisible) this.el.setAttribute('visible',true);
});
}
});
AFRAME.registerComponent('ar-shadows',{
// Swap an object's material to a transparent shadows-only material while
// in AR mode. Intended for use with a ground plane. The object is also
// set visible while in AR mode,this is useful if it's hidden in other
// modes due to them using a 3D environment.
schema: {
opacity: {default: 0.3}
},init: function () {
this.el.sceneEl.addEventListener('enter-vr',(ev) => {
this.wasVisible = this.el.getAttribute('visible');
if (this.el.sceneEl.is('ar-mode')) {
this.savedMaterial = this.el.object3D.children[0].material;
this.el.object3D.children[0].material = new THREE.ShadowMaterial();
this.el.object3D.children[0].material.opacity = this.data.opacity;
this.el.setAttribute('visible',true);
}
});
this.el.sceneEl.addEventListener('exit-vr',(ev) => {
if (this.savedMaterial) {
this.el.object3D.children[0].material = this.savedMaterial;
this.savedMaterial = null;
}
if (!this.wasVisible) this.el.setAttribute('visible',false);
});
}
});
AFRAME.registerComponent('ar-hit-test',{
init: function () {
this.xrHitTestSource = null;
this.viewerSpace = null;
this.refSpace = null;
this.el.sceneEl.renderer.xr.addEventListener('sessionend',(ev) => {
this.viewerSpace = null;
this.refSpace = null;
this.xrHitTestSource = null;
});
this.el.sceneEl.renderer.xr.addEventListener('sessionstart',(ev) => {
let session = this.el.sceneEl.renderer.xr.getSession();
let element = this.el;
session.addEventListener('select',function () {
let position = element.getAttribute('position');
document.getElementById('dino').setAttribute('position',{
x: (position.x),y: (position.y),z: (position.z)
});
document.getElementById('light').setAttribute('position',{
x: (position.x),y: (position.y + 2.15),z: (position.z)
});
});
session.requestReferenceSpace('viewer').then((space) => {
this.viewerSpace = space;
session.requestHitTestSource({space: this.viewerSpace})
.then((hitTestSource) => {
this.xrHitTestSource = hitTestSource;
});
});
session.requestReferenceSpace('local-floor').then((space) => {
this.refSpace = space;
});
});
},tick: function () {
if (this.el.sceneEl.is('ar-mode')) {
if (!this.viewerSpace) return;
let frame = this.el.sceneEl.frame;
let xrViewerPose = frame.getViewerPose(this.refSpace);
if (this.xrHitTestSource && xrViewerPose) {
let hitTestResults = frame.getHitTestResults(this.xrHitTestSource);
if (hitTestResults.length > 0) {
let pose = hitTestResults[0].getPose(this.refSpace);
let inputMat = new THREE.Matrix4();
inputMat.fromArray(pose.transform.matrix);
let position = new THREE.Vector3();
position.setFromMatrixPosition(inputMat);
this.el.setAttribute('position',position);
}
}
}
}
});
AFRAME.registerComponent('clickhandler',{
init: function() {
},tick: function() {
if (this.el.sceneEl.is('ar-mode')) {
var modal = document.getElementById("myModal");
modal.style.display = "block";
}
}
});
var span = document.getElementById("close");
function close_modal() {
var modal = document.getElementById("myModal");
modal.style.display = "none";
}
HTML 部分在这里
<body>
<div id="myModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<span id="close" onclick="close_modal()">×</span>
<h2>Modal Header</h2>
</div>
<div class="modal-body">
<p>Some text in the Modal Body</p>
<p>Some other text...</p>
</div>
<div class="modal-footer">
<h3>Modal Footer</h3>
</div>
</div>
</div>
<a-scene webxr="requiredFeatures: hit-test,local-floor;" embedded arjs>
<a-assets>
<!-- Model source: https://sketchfab.com/3d-models/spinosaurus-2135501583704537907645bf723685e7
Model author: https://sketchfab.com/VapTor
Model license: CC Attribution -->
<a-asset-item id="spinosaurus"
src="assets/pack.glb"
response-type="arraybuffer"></a-asset-item>
<a-asset-item id="reticle"
src="reticle.gltf"
response-type="arraybuffer"></a-asset-item>
</a-assets>
<a-camera position="0 1.2 0"></a-camera>
<!-- Environment for 2D and VR viewing. It's auto-hidden in AR mode. -->
<!-- <a-entity environment="preset: yavapai; skyType: color; skyColor: #ffe4b5; lighting: none; shadow: none; lightPosition: 0 2.15 0"
hide-in-ar-mode></a-entity> -->
<a-entity id="dino" position="0 0 0" scale="0.01 0.01 0.01">
<a-entity position="0 1.15 0" rotation="0 55 0"
gltf-model="#spinosaurus"
animation-mixer
shadow="cast: true; receive: false"></a-entity>
<!-- This shadow-receiving plane is only visible in AR mode.-->
<a-plane height="30" width="30" rotation="-90 0 0"
shadow="receive: true"
ar-shadows="opacity: 0.2"
visible="false"></a-plane>
</a-entity>
<a-entity light="type: hemisphere; intensity: 1"></a-entity>
<a-light type="directional"
light="castShadow: true;
shadowMapHeight: 1024;
shadowMapWidth: 1024;
shadowCameraLeft: -7;
shadowCameraRight: 5;
shadowCameraBottom: -5;
shadowCameraTop: 5;"
id="light"
target="dino"
position="-2 4 2">
</a-light>
<!-- <a-text value="Hello,World!"></a-text> -->
<a-entity gltf-model="#reticle" scale="0.8 0.8 0.8" ar-hit-test></a-entity>
</a-scene>
<!-- <div id="text">
<h1>A-Frame Spinosaurus for VR/AR</h1>
<p>
Model: <a href="https://sketchfab.com/3d-models/spinosaurus-2135501583704537907645bf723685e7">Spinosaurus</a> by
<a href="https://sketchfab.com/VapTor">Vaptor-Studio</a>.
</p>
<p>
Size: <button id="btn_full">Full</button>
<button id="btn_half">1/2</button>
<button id="btn_quarter">1/4</button>
</p>
<p>
This requires browser support for WebXR's AR mode,for example an
<a href="https://developers.google.com/ar/discover/supported-devices">ARCore-compatible</a>
Android phone with Chrome version 81 or higher.
</p>
<p>
Powered by <a href="https://aframe.io/blog/aframe-v1.0.0/">A-Frame v1.0.0</a>.
</p>
</div>
<script>
function setSize(scale) {
document.getElementById('dino').setAttribute('scale',{x: scale,y: scale,z: scale});
}
document.getElementById('btn_full').onclick = setSize.bind(this,1);
document.getElementById('btn_half').onclick = setSize.bind(this,0.5);
document.getElementById('btn_quarter').onclick = setSize.bind(this,0.25);
</script> -->
<!-- include the Glitch button to show what the webpage is about and
to make it easier for folks to view source and remix -->
<!-- <div class="glitchButton" style="position:fixed;top:20px;right:20px;"></div>
<script src="https://button.glitch.me/button.js"></script> -->
提前致谢。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。