You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

A-Frame:如何让动态生成实体响应用户位置(移动端)

实现AR文本实体的位置响应交互

需求说明

在iPhone Chrome浏览器中,基于现有AR.js + A-Frame代码,实现以下功能:

  • 动态生成的文本实体绑定指定经纬度位置
  • 用户走近文本时,文本自动放大;远离时缩小
  • 用户可通过相机控制绕文本移动

实现方案与修改代码

核心修改点

  • 新增经纬度输入面板,支持手动设置文本实体的GPS位置
  • 添加实时距离计算逻辑,根据用户与文本的距离动态调整缩放比例
  • 启用相机look-controls,支持用户绕文本旋转视角
  • 开启文本look-at属性,让文本始终面向用户

完整代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
    <script src="https://unpkg.com/aframe-look-at-component@0.8.0/dist/aframe-look-at-component.min.js"></script>
    <script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar-nft.js"></script>
    <script src="https://unpkg.com/aframe-text-geometry-component@^0.5.0/dist/aframe-text-geometry-component.min.js"></script>

    <style>
      body {
        margin: 0;
        padding: 0;
      }
      a-scene {
        width: 100vw;
        height: 100vh;
      }
      .lat-lng-input {
        position: fixed;
        top: 20px;
        left: 20px;
        z-index: 999;
        display: flex;
        gap: 10px;
      }
      .lat-lng-input input {
        padding: 8px;
        border: 1px solid #ccc;
        border-radius: 4px;
      }
      .lat-lng-input button {
        padding: 8px 16px;
        background: #007bff;
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
      }
    </style>
  </head>
  
  <body style="margin: 0; overflow: hidden;">
    <!-- 经纬度输入面板 -->
    <div class="lat-lng-input">
      <input type="text" id="latitude" placeholder="输入纬度" />
      <input type="text" id="longitude" placeholder="输入经度" />
      <button onclick="setEntityLocation()">设置位置</button>
    </div>

    <a-scene
      vr-mode-ui="enabled: false"
      embedded
      arjs="sourceType: webcam; debugUIEnabled: false;"
    >
      <a-assets>
        <img src="WMNH2OF.jpeg" id="chrome" crossorigin="anonymous" />
        <a-asset-item
          id="helvetikerBoldFont"
          src="https://rawgit.com/mrdoob/three.js/dev/examples/fonts/helvetiker_bold.typeface.json"
        ></a-asset-item>
      </a-assets>
      <!-- 启用视角控制 + GPS位置追踪 -->
      <a-camera gps-camera rotation-reader look-controls position="0 1.6 0"></a-camera>
    </a-scene>

    <script>
      let delay = 0;
      let lyrics = [
        "Go shorty",
        "Go shorty",
        "Go shorty",
        "Go shorty",
        "Go shorty",
        "Go shorty"
      ];
      // 存储所有生成的文本实体
      const textEntities = [];
      // 默认经纬度
      let targetLat = 0;
      let targetLng = 0;

      function randomRGB() {
        let r = Math.floor(Math.random() * 256);
        let g = Math.floor(Math.random() * 256);
        let b = Math.floor(Math.random() * 256);
        return `rgb(${r},${g},${b})`;
      }

      function createEntity(transcript) {
        let sceneEl = document.querySelector("a-scene");
        let entityEl2 = document.createElement("a-entity");

        // 绑定GPS位置
        entityEl2.setAttribute("gps-entity-place", `latitude: ${targetLat}; longitude: ${targetLng}`); 
        entityEl2.setAttribute("scale", "1 1 1");
        entityEl2.setAttribute(
          "text-geometry",
          `value: ${transcript}; font: #helvetikerBoldFont; bevelEnabled: true; bevelSize: 0.03; bevelThickness: 0.03; curveSegments: 15;`
        );
        entityEl2.setAttribute(
          "material",
          `metalness:0.9; roughness: 0.05; sphericalEnvMap: #chrome; color: ${randomRGB()}`
        );
        // 文本始终面向相机
        entityEl2.setAttribute("look-at", "[gps-camera]");
        // 循环颜色动画
        entityEl2.setAttribute(
          "animation__color",
          `property: material.color; to: ${randomRGB()}; dur: 2000; easing: linear; loop: true`
        );
        
        sceneEl.appendChild(entityEl2);
        textEntities.push(entityEl2);
      }

      // 实时更新文本缩放
      function updateTextScale() {
        const cameraEl = document.querySelector("[gps-camera]");
        if (!cameraEl.object3D) return;
        
        textEntities.forEach(entity => {
          if (!entity.object3D) return;
          // 计算相机与文本的距离
          const distance = cameraEl.object3D.position.distanceTo(entity.object3D.position);
          // 距离越近缩放越大(可调整比例)
          const scaleFactor = Math.min(5, 10 / distance);
          entity.setAttribute("scale", `${scaleFactor} ${scaleFactor} ${scaleFactor}`);
        });
        
        requestAnimationFrame(updateTextScale);
      }

      // 设置实体经纬度
      function setEntityLocation() {
        const latInput = document.getElementById("latitude");
        const lngInput = document.getElementById("longitude");
        targetLat = parseFloat(latInput.value) || 0;
        targetLng = parseFloat(lngInput.value) || 0;
        // 更新现有实体位置
        textEntities.forEach(entity => {
          entity.setAttribute("gps-entity-place", `latitude: ${targetLat}; longitude: ${targetLng}`);
        });
      }

      function rap() {
        for (let i = 0; i < lyrics.length; i++) {
          setTimeout(function () {
            createEntity(lyrics[i]);
          }, (delay += 2000));
        }
        // 启动距离监听
        setTimeout(() => updateTextScale(), 3000);
      }

      rap();
    </script>
  </body>
</html>

功能说明

  1. 经纬度设置:页面顶部的输入面板支持手动输入目标经纬度,点击按钮后所有文本实体将绑定到该GPS位置
  2. 距离响应缩放:通过requestAnimationFrame实时计算用户与文本的距离,动态调整文本大小,距离越近文本越大
  3. 视角控制:启用look-controls后,用户可拖动屏幕绕文本实体旋转视角,实现环绕查看
  4. 文本朝向:look-at组件确保文本始终面向用户,提升AR交互的直观性

内容的提问来源于stack exchange,提问作者hayden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 01:35:28