如何复制要在场景实体中使用的摄影机子帧实体的位置和旋转



我想创建一个控制面板,当用户往下看时,它会出现在用户面前,但随后会将自己锁定到世界空间。

我正在创建一个占位符控制面板,然后将实际控制面板移动到这个位置并旋转,但实际控制面板没有移动到占位符位置,而是停留在位置0 0 0。

但是,如果我在控制台中手动执行该过程,它就会工作。

这就是我正在尝试的:

<!DOCTYPE html>
<html>
<head>
<script src="https://aframe.io/releases/0.4.0/aframe.min.js"></script>
<script>
function createControlPanel() {
var controlPanelPlaceHolder = document.createElement('a-plane');
controlPanelPlaceHolder.setAttribute('id', 'control-panel-place-holder');
document.querySelector('#me').appendChild(controlPanelPlaceHolder);
document.querySelector('#control-panel-place-holder').setAttribute('width', '0.25');
document.querySelector('#control-panel-place-holder').setAttribute('height', '0.15');
document.querySelector('#control-panel-place-holder').setAttribute('position', '0.15 -0.05 -0.3');
document.querySelector('#control-panel-place-holder').setAttribute('rotation', '-45 0 0');
document.querySelector('#control-panel-place-holder').setAttribute('color', 'crimson');

var controlPanel = document.createElement('a-plane');
controlPanel.setAttribute('id', 'control-panel');
controlPanel.setAttribute('width', '0.25');
controlPanel.setAttribute('height', '0.15');
controlPanel.setAttribute('color', 'teal');
document.querySelector('a-scene').appendChild(controlPanel);
document.querySelector('#control-panel-place-holder').object3D.updateMatrixWorld();
document.querySelector('#control-panel').object3D.position.copy(
new THREE.Vector3().setFromMatrixPosition(document.querySelector('#control-panel-place-holder').object3D.matrixWorld)
)
document.querySelector('#control-panel').object3D.quaternion.copy(
document.querySelector('#control-panel-place-holder').object3D.getWorldQuaternion()
)
document.querySelector('#me').removeChild(document.querySelector('#control-panel-place-holder'));
}
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('a-scene').addEventListener('loaded', createControlPanel);
});
</script>
</head>
<body>
<a-scene debug>
<a-entity id='me' camera='userHeight: 1.6' position='10 0 10' rotation='0 45 0' look-controls></a-entity>
</a-scene>
</body>
</html>

我收到错误

Uncaught (in promise) TypeError: Cannot read property 'isPlaying' of null

有没有想过为什么这不起作用?

谢谢。

根据@ngokevin的建议,我已经将代码转移到组件中并进行了重构。

以下解决方案在用户向下看时在用户面前创建一个控制面板和标线。面板保持在适当的位置,这样他们就可以使用标线板进行选择。如果他们抬头看,面板就会消失。

// helper.js
const q = document.querySelector.bind(document)
function setComponentDefaults(component) {
for (attr in component.data)
component.el.setAttribute(attr, component.data[attr])
}
// control-panel-skeleton.js
AFRAME.registerComponent('control-panel-skeleton', {
schema: {
width:  { default: '0.25' },
height: { default: '0.15' }
},
init: function () {
setComponentDefaults(this)
}
})
// control-panel-place-holder.js
AFRAME.registerComponent('control-panel-place-holder', {
schema: {
id:       { default: 'control-panel-place-holder'},
position: { default: '0 -0.05 -0.3' },
rotation: { default: '-45 0 0' },
visible:  { default: 'false' }
},
init: function () {
setComponentDefaults(this)
}
})
// control-panel.js
AFRAME.registerComponent('control-panel', {
schema: {
id:    { default: 'control-panel'},
color: { default: 'teal'}
},
init: function () {
setComponentDefaults(this)
this.el.setAttribute('control-panel-skeleton', '')
const cpHolder = q('#control-panel-place-holder')
this.el.setAttribute('position', cpHolder.object3D.getWorldPosition())
this.el.object3D.setRotationFromQuaternion(cpHolder.object3D.getWorldQuaternion())
q('#reticle').setAttribute('visible', true)
},
remove: () => q('#reticle').setAttribute('visible', false)
})
// control-panel-trigger.js
AFRAME.registerComponent('control-panel-trigger', {
init: function () {
const cp = () => q('#control-panel')
function createIfLookingDown(detail) {
if (detail.newData.x < -25 && !cp()) {
const cp = document.createElement('a-plane')
cp.setAttribute('control-panel', '')
q('a-scene').appendChild(cp)
}
}
function removeIfLookingUp(detail) {
if (detail.newData.x > -20 && cp())
cp().parentNode.removeChild(cp())
}
this.el.addEventListener('componentchanged', (evt) => {
if (evt.detail.name == 'rotation')
createIfLookingDown(evt.detail) || removeIfLookingUp(evt.detail)
})
}
})
// reticle.js
AFRAME.registerComponent('reticle', {
schema: {
id:             { default: 'reticle' },
color:          { default: 'brown' },
cursor:         { default: 'fuse: true' },
position:       { default: '0 0 -0.1' },
'radius-inner': { default: '0.003' },
'radius-outer': { default: '0.0037' },
raycaster:      { default: 'far: 2' },
scale:          { default: '1.7 1.7' },
visible:        { default: 'false' }
},
init: function () {
setComponentDefaults(this)
}
})
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<script src='helper.js'></script>
<script src='aframe-v0.4.0.js'></script>
<script src='control-panel.js'></script>
<script src='control-panel-skeleton.js'></script>
<script src='control-panel-place-holder.js'></script>
<script src='control-panel-trigger.js'></script>
<script src='reticle.js'></script>
</head>
<body>
<a-scene debug>
<a-entity id='me' camera='userHeight: 1.6' position='10 0 10' rotation='0 45 0' look-controls control-panel-trigger>
<a-ring reticle></a-ring>
<a-plane control-panel-place-holder control-panel-skeleton></a-plane>
</a-entity>
<a-plane color='#888'   rotation='-90 0 0' scale='100 100 0'></a-plane>
<a-plane color='yellow' rotation='-90 0 0' scale='1 100 0.2'></a-plane>
<a-plane color='blue'   rotation='-90 0 0' scale='100 1 0.2'></a-plane>
</a-scene>
</body>
</html>

最新更新