AFrame:重新调整元素的父级,保持其世界位置、旋转

2024-03-07

我正在尝试重新设置元素(实体)的父级,保持其在场景中的位置、旋转(以及如果可能的话,大小,例如比例)。理想情况下,我希望有一个组件(例如“reparent”),当在实体上设置时,将其“移动”到指定的父级,从而将实体的外观保留在场景中。例如,对于下一个 HTML 代码,绿色实体将成为红色实体的子级,但会保持其在场景中的位置和旋转:

  <a-scene id="scene" background="color: grey">
      <a-entity id="red"
        position="-1 3.5 -4" rotation="30 0 0" material="color: red"
        geometry="primitive: cylinder"></a-entity>
        
      <a-entity id="green" reparent="parent: #red"
        position="-3 2 -4" rotation="0 45 0" material="color: green"
        geometry="primitive: box"></a-entity>
  </a-scene>

显然,这可以使用三个级别来完成attach https://threejs.org/docs/#api/en/core/Object3D.attach,但是当我尝试使用它编写一个简单的组件时,它不起作用,显然是由于 HTML 的重新父级调整造成的(我假设是因为 AFrame)。

我已经编写了他的测试组件来显示问题:

AFRAME.registerComponent('reparent', {
  schema: {
    parent: {type: 'selector', default: null},
  },
  init: function () {
    const el = this.el;
    const parent = this.data.parent;

    move = function(evt) {
      parent.object3D.attach(el.object3D);
      console.log(el.object3D.parent.el.id, el.parentElement.id);
//      parent.appendChild(el);
//      console.log(el.object3D.parent.el.id, el.parentElement.id);
    };
    el.sceneEl.addEventListener('loaded', move);
  }
});

运行时,结果是red scene:object3D 的父级已更改,但在 HTML 级别,元素的父级仍然是场景。绿色框按预期显示(在“-3 2 -4”中,世界坐标,并且旋转正确)。

如果我取消注释两行注释,我会得到第二行red red,但是绿色框消失了。换句话说,现在在 HTML 中,元素按照预期重新设置了父级,但不知何故,它的 object3D 不再工作。

知道为什么会失败,或者对这样的组件有其他想法吗?

所有这一切都与 AFrame 1.1.0 相关。


在得到建议后,重用相同的元素(实体)来重新设置父级并不是一个好主意(请参阅更改组件的父级并保持位置 https://stackoverflow.com/questions/52318200/change-parent-of-component-and-keep-position),我探索了将要重新设置父级的实体复制到新父级下的新元素中的想法,然后删除“旧”元素(而不是直接重新设置实体的父级)。诚然,这不是世界上最干净的黑客,但我希望它对我的用例有所帮助。所以,我写了一个组件:

AFRAME.registerComponent('reparent', {
  schema: {
    parent: {type: 'selector', default: null},
  },
  update: function () {
    const el = this.el;
    const parent = this.data.parent;

    if (el.parentElement == parent) {
      // We're already a child of the intended parent, do nothing
      return;
    };
    // Reparent, once object3D is ready
    reparent = function() {
      // Attach the object3D to the new parent, to get position, rotation, scale
      parent.object3D.attach(el.object3D);
      let position = el.object3D.position;
      let rotation = el.object3D.rotation;
      let scale = el.object3D.scale;

      // Create new element, copy the current one on it
      let newEl = document.createElement(el.tagName);
      if (el.hasAttributes()) {
        let attrs = el.attributes;
        for(var i = attrs.length - 1; i >= 0; i--) {
          let attrName = attrs[i].name;
          let attrVal = el.getAttribute(attrName);
          newEl.setAttribute(attrName, attrVal);
        };
      };
      // Listener for location, rotation,... when the new el is laded
      relocate = function() {
        newEl.object3D.location = location;
        newEl.object3D.rotation = rotation;
        newEl.object3D.scale = scale;
      };
      newEl.addEventListener('loaded', relocate, {'once': true});
      // Attach the new element, and remove this one
      parent.appendChild(newEl);
      el.parentElement.removeChild(el);
    };
    if (el.getObject3D('mesh')) {
      reparent();
    } else {
      el.sceneEl.addEventListener('object3dset', reparent, {'once': true});
    };
  }
});

您可以检查它是否适用于以下 HTML 文件:

<!DOCTYPE html>
<html>
  <head>
    <script src="https://aframe.io/releases/1.1.0/aframe.min.js"></script>
    <script src="reparent.js"></script>
  </head>
  <body>
    <a-scene id="scene" background="color: grey">
      <a-entity id="red"
        position="1 2 -4" rotation="30 0 0" material="color: red"
        geometry="primitive: cylinder"></a-entity>
        
      <a-entity id="green" reparent="parent: #red"
        position="-1 0 -4" rotation="0 45 0" material="color: green"
        geometry="primitive: box"></a-entity>

      <a-entity id="wf"
        position="-1 0 -4" rotation="0 45 0" material="wireframe: true"
        geometry="primitive: box"></a-entity>
    </a-scene>
  </body>
</html>

线框实体只是为了显示绿色框如何精确地保持在相同位置,尽管它在红色实体下“重新设置了父级”(探索 DOM 来检查)。如上所述,绿色框实际上是一个新框,是从原始框克隆的,然后被组件删除。

该组件应该在其工作时工作parent属性发生更改,允许在需要时动态重新调整父级。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AFrame:重新调整元素的父级,保持其世界位置、旋转 的相关文章

  • 页面在 Google Adwords 转化跟踪上重定向

    我有一个表单 人们可以在其中提交数据 然后使用 ajax 将数据发送到服务器 我已将其设置为 Google Adwords 中的转化 下面是我使用过的代码 问题是 当用户提交表单时 在收到响应后 它会重定向回我给出的 URL 我不想重定向
  • 如何检测被覆盖的 CSS 属性?

    I can get all css properties for an element with document stylesheets but some of those are not active because those pro
  • 在 onclick 事件上请求麦克风

    有一天 我偶然发现了这个 Javascript 录音机的例子 http webaudiodemos appspot com AudioRecorder index html http webaudiodemos appspot com Au
  • 需要使用 iFrame API 隐藏 YouTube 品牌

    我正在使用 YouTube iFrame API 在我的自定义播放器 javascript 播放器 中加载视频 我需要隐藏 Youtube 品牌 但是在 iOS 设备上 它显示带有以下参数的徽标 playerVars fs 1 autopl
  • Bootstrap 标签栏平滑移动导航按钮

    我有一个用于切换块的普通引导选项卡面板 在导航中切换块时 活动选项卡会突出显示 但现在 当我单击活动选项卡的背景时 它会立即发生变化 是否可以使切换选项卡时背景不会立即改变 而是根据需要哪个选项卡而平滑地左右移动 这可以用以下方法完成吗cs
  • 在 JavaScript 函数中加载图像

    我有获取图像像素颜色的功能 function getImage imgsrc var img img src imgsrc var imageMap new Object img load function var canvas
  • Visual Studio 改变 Ctrl-K-D 的工作方式

    In Visual Studio I m using 2012 is there any way of editing the way that Ctrl K D combinations handles its Auto Formatti
  • Chrome 开发工具命中代码但未命中断点

    我在 chrome 开发工具上启用了断点 并且在一行上有一个断点 我知道 chrome 正在运行 因为我将断点放在具有以下语句的行上 alert why is this not breaking 如果我在本地主机中找到该文件 则断点有效 断
  • 如何在 JavaScript 中将变量的内容写入文件[重复]

    这个问题在这里已经有答案了 可能的重复 firefox 如何启用本地 JavaScript 来读取 写入我的 PC 上的文件 https stackoverflow com questions 2846045 firefox how to
  • 如何调试超时等待异步 Angular 任务?无法在角度页面上找到元素

    编辑 请注意 在 ernst zwingli 的帮助下 我找到了问题的根源 因此 如果您遇到相同的错误 他指出的修复之一可能会帮助您 我的问题是量角器本身的一个已知问题 如果您认为这可能是您 我已经扩展了我的步骤 以在我最初的问题之后查明问
  • 自调用函数未定义

    如果我声明一个函数文字 var x function alert hi console log x returns the function code However var x function alert hi console log
  • Next.js:错误:React.Children.only 期望接收单个 React 元素子元素

    我有一个名为Nav inside components目录及其代码如下所示 import Link from next link const Nav gt return div a Home a a About a div export d
  • Socket IO 服务器到服务器

    服务器是否可以使用 Socket IO 连接到另一个服务器并被视为客户端 并让它加入房间 接收 io sockets in lobby emit 和更多 第一个服务器也在监听连接 消息 嘿 Brad 下面是我的完整 js 应用程序 供参考
  • 嵌套 DIV 的类似斑马的 CSS 样式

    我嵌套了 DIV 元素 但我不知道嵌套的级别 我需要每个都有与其父级不同的背景 创建类似斑马的颜色 我只使用两种背景 深色和白色 效果需要类似于在容器中设置奇数和偶数子级的样式 但在我的例子中 子级是嵌套的 我可以使用每个嵌套元素的规则来做
  • D3 向对象添加超链接?

    我正在尝试制作 D3 图 它将代表我网站的菜单 我尝试按照此处的其他指南添加超链接 但它们都不起作用 每个对象都会有一个不同的 URL 指向 主页 关于 联系方式等 如果添加超链接 我可以拖动对象吗 这意味着如果我按住单击 如果我单击该对象
  • jQuery 中什么函数相当于 .SelectMany()?

    让我解释一下 我们知道 jQuery 中的映射函数充当 Select 如 LINQ 中 tr map function return this children first returns 20 tds 现在的问题是我们如何在 jQuery
  • 使用 ng-if 改变角度方向

    我想通过单击将方向从 rtl 更改为 ltr and in 设置 html
  • 标记(Markdown)+ Mermaid(流程图和图表)

    努力去争取 美人鱼 https github com knsv mermaid https github com knsv mermaid跟 共事 标记 https github com chjj marked https github c
  • 如何使用 javascript 更改文件扩展名

    有谁知道在 Javascript 中更改文件扩展名的简单方法吗 例如 我有一个带有 first docx 的变量 但我需要将其更改为 first html 这将改变字符串包含文件名 let file first docx file file
  • 如何为 jQuery 插件设置私有变量?

    我想创建一个简单的插件 它使用元素的文本作为默认值 或者您可以在调用插件时设置此值 但是 如果我不设置该值 并为多个元素调用插件 则默认值会成倍增加 function fn reText function options var setti

随机推荐