Skip to content

快速上手 ​

目录 ​

目标 ​

通过一个 30 分钟的简单快速上手教程,带您编写一个静态网页,用于加载端渲染场景,并且具备基础的接口调用和事件监听功能的演示案例。

预先条件 ​

如果您准备使用图观统一 API,基于三维端渲染场景开发,需要具备以下硬件和软件的条件。

硬件 ​

  • 最低硬件要求:8G 内存,无独立显卡笔记本或者台式机。
  • 推荐硬件要求:8G 内存,有独立显卡,NVIDIA GTX 960 及以上的笔记本或者台式机。

软件 ​

  • 操作系统:Windows,MacOS,Linux 均可
  • Microsoft Visual Studio Code
  • 推荐使用Google Chrome 浏览器,版本 88 及以上(2021 年 1 月之后版本),或者 Microsoft Edge 版本 88 及以上、360 浏览器版本 13 及以上
  • 如需查看自己的 Google Chrome 浏览器版本,您可以在浏览器地址栏中输入 chrome://settings/help,或者点击菜单 -> 设置 -> 关于 Chrome

查看浏览器版本

图观场景和代码起始包 ​

开发图观场景,您需要具备一个已经发布的图观场景,和图观统一开发 API SDK。

如果是图观端场景,可以使用在线图观端渲染场景编辑器完成场景的编辑并且发布。发布之后,场景会生成一个全局唯一的 URL(统一资源定位符),通过查看详情可以复制二次开发地址。这个地址是您在进行 TGAPI 开发时需要传入的。

端渲染二次开发地址

如果是图观流场景,需要将打包好的流场景,上传到图观流渲染服务平台。在添加场景后,同样可以获得访问地址和 token。

流渲染场景访问Token

卡通版效果图

写实版效果图

  • 这两个场景的内容和功能没有本质的区别,只是在场景的多边形和材质部分有不同的针对性优化。
  • 点击这里下载代码包
    • 代码包中包括一个 handsonDemo.html 文件和一个 handsonDemoStart.html 文件。
    • handsonDemoStart.html,可以作为您上手编写代码的起点。
    • handsonDemo.html,是这个案例编写完成后的全部代码。
    • html 文件当中引用了在线版本的 TGAPI SDK。

返回本章目录

创建端渲染三维应用程序 ​

引入版本:3.1 起支持

1. 打开 handsonDemoStart.html 页面 ​

查看 handsonDemoStart.html 文件,只有非常少量的 HTML 代码,表示页面的基本head、body节点。head节点中包括后续会用到的基本style样式,在 body 节点中已经有几个后续会使用到的div元素。

HTML
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8" />
    <title>图观统一开发API 快速上手</title>

    <style>
       /* 这里省略部分代码,具体请下载代码文件查看。 */
        </style>
  </head>

  <body>

    
    <div class="app" id="app">
      <div id="container" style="width: 100%; height: 100%"></div>
      
      <div id="loading" class="appLoading">
        <img src="/startGuide/loading.gif" alt="" />
        <div>正在加载场景</div>
      </div>
    </div>

    
    <div class="btns hide">
      <div>添加地标点</div>
      <div>沿路径移动相机</div>
    </div>

    <script>
       /* 程序逻辑主要实现位置 */
        </script>
  </body>
</html>

2. 引入 TGAPI SDK 地址 ​

在head标签的title和style之间插入如下代码。

JavaScript

<script src="https://www.tuguan.net/public/tgapp/TGApp.min.js"></script>

这里使用了在线最新版本的 TGAPI,您也可以选用特定版本的 TGAPI。

3. 添加初始化加载场景代码 ​

在body元素中添加onload属性,并且关联一个新的onBodyLoaded()方法。

HTML
<body onload="onBodyLoaded()">

在body的script标签中创建一个 TGAPP 对象。然后实现onBodyLoaded()方法,在这个方法中首先需要请求一个场景访问 token。

JavaScript
<script>
// 初始化图观App
var appInstance = new TGApp.App();

// 获取场景Token
function onBodyLoaded() {
    // 场景所在服务器
    let server = "www.tuguan.net";
    // 高配版本,写实场景ID:cb205f6b-62e7-45ff-9734-a25883517b6e
    // 低配版本,卡通场景ID:ed402a51-a00a-48f2-8b60-f51963440e82
    // 根据您的硬件配置选取不同的场景,将ID替换到下方的变量中。
    let id = "ed402a51-a00a-48f2-8b60-f51963440e82";
    
    // 定义URL模版
    let sceneUrl = `http://${server}/api/sceneEditor/v1/scenes/${id}/loadAVWS`;
    let tokenUrl = `http://${server}/api/user/v1/visitorScene/${id}`;

    let xhr = new XMLHttpRequest();
    // 设置请求地址和参数
    xhr.open("post", tokenUrl, true);
    // 设置请求头
    xhr.setRequestHeader("Content-Type", "application/json charset=utf-8");
    // 监听readystate状态
    xhr.onreadystatechange = () => {
        if (xhr.readyState == 4 && xhr.status == 200) {
            let result = JSON.parse(xhr.responseText);
            // 请求成功后,初始化地图
            loadScene(sceneUrl, result.accessToken);
        }
    };
    // 发送请求
    xhr.send();
}
</script>

在上面的onBodyLoaded方法中,我们需要在获取完 token 后,继续加载场景,需要实现loadScene方法。在onBodyLoaded方法下面,添加如下代码。

JavaScript
// 初始化加载图观三维场景服务
function loadScene(url, token) {
    appInstance.initService({
        container: document.getElementById("container"),
        mode: "scene",
        url: url,
        token: token
    }, (e) => {
        console.log(e);
        // 隐藏正在加载界面
        document.querySelector('.appLoading').className = 'appLoading hide';
      });
    });
}

特别说明的是,在initService指令的callback回调中,我们隐藏了正在加载的提示。这个提示框通过className选择器找到,然后增加了一个hide的 CSS 样式。

到这里,一个端渲染场景的加载已经基本完成了,可以运行页面进行浏览测试。

为了继续进行后续的功能演示,可以通过addEventListener订阅图观 API 的事件,获得场景服务初始化完成onServiceInit的事件。并且在callback回调函数中,显示出后续需要继续操作的交互按钮。在loadScene方法后面添加如下代码。

实际上,这个操作通过在上方的initService指令的callback回调中编写也可以,这里只是为了举例说明addEventListener的使用。

JavaScript

// 监听场景初始化成功事件
window.appInstance.uniCall('addEventListener', {
    eventName: 'onServiceInit',
    callback: (res) => {
        // 显示交互按钮
        document.querySelector('.btns').className = 'btns';
    }
})

4. 添加地标点 & 弹出标牌 ​

接下来演示如何向场景中添加一个地标点,并且在点击地标点后弹出一个 HTML 的 DIV 标牌。

首先我们在上一步的调用addEventListener事件方法之后,添加点击添加地标点按钮的调用方法,并且实现addLandmark方法。

JavaScript
// 点击添加地标点
document.querySelectorAll('.btns div')[0].onclick = function () {
  addLandmark();
}

// 添加一个地标点
function addLandmark() {
    let jsonData = {
        id: 'pointLayer',      // 图层对象 id,新建时调用者自己传入的唯一标识,用于各种操作的对象识别
        coordType: 0,          // XY 轴坐标类别,0:X 经度,Y 纬度;1:X 米,Y米,相对世界00点
        coordTypeZ: 0,         // Z 轴坐标类别,0:相对 3D 世界 0 海拔;1:相对 3D 世界地表;2:相对 3D 模型表面(单位:米)
        iconName: 'residence', // 内置图标名称,见图观官网统一API开发手册
        label: '',             // 图标标签文本
        tag: 'custominfo',     // 用户自定标签,用户保存用户的扩展数据
        coord: [116.34953788361443, 40.08387756599562], // XY 轴坐标,X:经度;Y:纬度
        coordZ: 65,            // Z 轴高度(单位:米)
        visible: true          // 添加当前图层时默认是显示还是隐藏
    }
  // 开启图层可点击
  window.appInstance.uniCall('addLandmark', jsonData, (res) => {
      window.appInstance.uniCall('pickOverlay', {
          overlayType: 'landmark',
          idLayer: 'pointLayer',
          type: 'click',
          isShowDecorator: false
      })
  })
}

注意,在addLandmark的回调函数中,代码又再一次调用了pickOverlay指令,开启地标点的点击。这样会在用户点击地标点后,触发一个onLandmarkClick事件。这样我们可以继续订阅这个事件,并且通过addOverlayTip指令添加指定地标点对象的标牌。

JavaScript
// 添加图层tip
function addOverlayTip() {
    // 创建HTML里的div标牌
    const landmarkerTipDiv = document.createElement('div');
    landmarkerTipDiv.id = 'landmarkerTip';
    landmarkerTipDiv.innerHTML = "居民楼";
    landmarkerTipDiv.className = "landmarkerTipDiv";
    document.body.appendChild(landmarkerTipDiv);

    // 添加覆盖物的的弹出标牌
    let jsonData = {
        id: 'pointLayer',       // 图层对象 id,新建时调用者自己传入的唯一标识,用于各种操作的对象识别
        url: '',                // Tip 窗口页面地址
        divId: 'landmarkerTip', // 悬浮层DOM元素id
        isShowClose: true,      // 是否显示右上角关闭按钮,默认显示关闭按钮
        size: [300, 150],       // Tip 窗口宽高xy,x:窗口宽;y:窗口高(单位:像素)
        offset: [50, 50],       // Tip 左上角相对 对象中心点 偏移量 xy,x:为正,向右偏移;y:为正,向上偏移(单位:像素)
        overlayType: 'landmark' // 覆盖物类型
    }
    appInstance.uniCall('addOverlayTip', jsonData, (result) => {
        console.log(result);
    })
}

// 注册地标点击事件
window.appInstance.uniCall('addEventListener', {
    eventName: 'onLandmarkClick',
    callback: (res) => {
       addOverlayTip();
    }
})

到这里完成了向场景中添加一个地标点,并且在点击地标点后弹出 HTML 的 DIV 标牌的功能。

5. 添加路径 & 镜头沿路径移动 ​

接下来演示如何向场景中添加一个路径,并且让镜头沿路径游历。

首先我们在上一步的代码之后,继续添加一个添加沿路径移动相机按钮的调用方法,并且实现addPath方法。

JavaScript

// 添加沿路径移动镜头
document.querySelectorAll('.btns div')[1].onclick = function () {
    addPath();
}

// 添加路径图层
function addPath() {
    let jsonData = {
        id: 'path',           // 图层对象 id,新建时调用者自己传入的唯一标识,用于各种操作的对象识别
        name: '路径',          // 图层名称,支持为图层自定义名称
        coordType: 0,         // XY 轴坐标类别,0:X 经度,Y 纬度;1:X 米,Y米,相对世界00点
        coordTypeZ: 0,        // Z 轴坐标类别,0:相对 3D 世界 0 海拔;1:相对 3D 世界地表;2:相对 3D 模型表面(单位:米)
        type: 'Segment06',    // 路线样式类别 Arrow01 Arrow02 Arrow03 Arrow04 Arrow05 Arrow06 Segment01 Segment02 Segment03 Segment04 Segment05 Segment06
        color: '#00ff00',     // 路线颜色,颜色透明(HEX 颜色值)
        colorPass: '#00ff00', // 模型对象 移动经过后的 路径颜色(HEX 颜色值)
        width: 2,             // 路径宽度(单位:米)
        tag: 'custominfo',    // 用户自定标签,用户保存用户的扩展数据
        visible: true,        // 添加当前图层时默认是显示还是隐藏
        points: [             // 定义路径途径点
          {
              "coord": [116.3500030557184, 40.08284427622822],
              "coordZ": 0.3570831396935906
          }, {
              "coord": [116.3500530557184, 40.083374423769506],
              "coordZ": 0.2769105811405785
          }, {
              "coord": [116.35011073784217, 40.084077407712066],
              "coordZ": 0.2769105811404267
          }, {
              "coord": [116.35011073784217, 40.08480525607828],
              "coordZ": 0.2769105811405026
          }, {
              "coord": [116.34898573742421, 40.08480525607828],
              "coordZ": 0.2769105811403509
          }
        ]
  }

  // 添加路径
  appInstance.uniCall('addPath', jsonData, (result) => {
      if (result.result === 1) {
          pathingCamera();
      }
  })
}

虽然上面的代码比较长,实际上只是路径点的数据比较多。这里只有一个图观 API 指令就是addPath,在addPath指令的回调函数里,再次调用让相机沿路径移动的方法,该方法实现的代码如下。

JavaScript
// 路径移动镜头
function pathingCamera() {
    let jsonData = {
        pathId: 'path',    // 路径的id
        loopMode: 'round', //循环模式:none,不循环;round,往返;repeat,从头循环
        reverse: false,    //是否反向移动
        distance: 30,      //镜头距覆盖物距离(单位:米)
        pitch: 5,          //镜头俯仰角(0~89)
        speed: 10          //移动速度 (单位:米/秒)
    }
    // 开启路径移动镜头
    appInstance.uniCall('pathingCamera', jsonData, (result) => {
        console.log(result);
    })
  }

到这里完成了添加路径并且让相机沿路径移动的效果。

6. 三维容器跟随浏览器缩放自适应 ​

虽然图观场景可以自动填充container容器的大小,但是app节点并无法根据浏览器大小自适应。如果想实现这个特性,需要继续在代码最后添加如下内容。

JavaScript
// 地图自适应
function scale() {
    // 可视区域的尺寸
    let visibleWidth = window.innerWidth;
    let visibleHeight = window.innerHeight;
    // 手动配置的面板尺寸
    let manualWidth = 1920;
    let manualHeight = 1080;
    // 计算横向和纵向的缩放系数
    var widthPercentage = (1.0 * visibleWidth) / manualWidth;
    var heightPercentage = (1.0 * visibleHeight) / manualHeight;
    // 取得最小缩放系数
    let scale = Math.min(widthPercentage, heightPercentage);
    document.querySelector('#app').style.transform = `translateX(-50%) translateY(-50%) scale(${scale})`;
}
scale();
// 窗口调整大小时重新计算缩放尺寸
window.onresize = scale;

拖动浏览器大小,内容也会随之缩放,比例始终保持正确。

返回本章目录