基於 HTML5 WebGL 構建智能城市 3D 場景

前言

隨着城市規模的擴大,傳統的方式很難完全地展現城市的全貌,但隨着 3D 技術的應用,出現了 3D 城市羣的方式以動態,交互式地把城市全貌呈現出來。配合智能城市系統,經過 Web 可視化的方式,使得城市管理者能夠更及時地瞭解交通狀況,城市消防,電力管理等方面的運行狀況,作出處理。html

本 demo 使用 HT for Web 產品輕量化 HTML5/WebGL 建模的方案,傳統的 智慧樓宇/樓宇自動化/樓宇安防/智慧園區 常會採用 BIM(建築信息模型 Building information modeling)軟件,如 Autodesk 的 Revit 或 Bentley 這類建築和工程軟件,但這些 BIM 建模模型的數據每每過於龐大臃腫,絕大部分細節信息對樓宇自控意義不大,反而影響拖累了行業 Web SCADA 或 Web 組態監控的趨勢,因此咱們採用以 Hightopo 的 HT for Web 產品輕量化 HTML5/WebGL 建模的方案,實現快速建模、運行時輕量化到甚至手機終端瀏覽器便可 3D 可視化運維的良好效果。node

demo 地址:智慧城市
json

預覽圖:瀏覽器

代碼實現

加載 3d 場景bash

新建一個 3d 場景,並加入到頁面中。運維

const g3d = new ht.graph3d.Graph3dView();
const dm3d = g3d.dm();
g3d.addToDOM();
複製代碼

addToDOM 函數默認將場景加載到 body 中並填充窗口。ide

接下來反序列化城市場景 json,並在反序列化函數的回調中設置了場景的視角,中心位置,天空盒,並得到各圖元信息,調用 startAnim 函數:函數

g3d.deserialize('scenes/ny.json', () => {
  g3d.setEye([1132.8386351821287, 1916.836416970022, 1479.5345608290288]);
  g3d.setCenter([519.9741236104874, 273.4741921410557, -319.58669041297884]);
  g3d.setSkyBox(dm3d.getDataByTag('skyBox'));
   
  // 獲取擴散效果的圖元
  scaleList.push(
      dm3d.getDataByTag('scaleBlue'),
      dm3d.getDataByTag('scaleRed')
  );
  ···
   
  // 開始動畫
  startAnim();
});複製代碼

動畫實現動畫

加載後的城市場景以下圖所示:ui

咱們能夠看到場景中有藍黃水波紋效果,道路,消防通道的流動效果,上下浮動的效果和旋轉的 logo 和衛星。

動畫的實現均經過 ht.Default.startAnim 實現的,先來了解一下:

ht.Default.startAnim({
  // 動畫幀數
  frames: 12,
  // 動畫幀間隔毫秒數
  interval: 10,
  // 動畫緩動函數,默認採用 ht.Default.animEasing
  easing: function(t){ return t * t; },
  // 動畫結束後調用的函數
  finishFunc: function(){ console.log('Done!') },
  // action 函數必須提供,實現動畫過程當中的屬性變化
  action: function(v, t){
    // 此例子展現將節點 node 從位置 p1 動畫到位置 p2
    node.setPosition(
        p1.x + (p2.x - p1.x) * v,
        p1.y + (p2.y - p1.y) * v
    );
  }
});複製代碼

以上爲 Frame-Based 方式動畫, 這種方式用戶經過指定 frames 動畫幀數,以及 interval 動畫幀間隔參數控制動畫效果。

ht的動畫手冊能夠參照:動畫手冊

下面依次介紹各個效果的實現。

1. 波紋效果

預覽圖:

代碼:

function waveScale(obj, dlt, max, min) {
  obj.forEach(node => {
    // 擴散半徑增長
    let s = node.getScaleX() + dlt;
    // 擴散半徑大於最大值的時候, 重置爲最小值
    if (s >= max) s = min;
    // 設置 x,y,z 方向的縮放值
    node.setScale3d(s, s, s);
  });
}
function startAnim() {
  ht.Default.startAnim({
    frames: Infinity,
    interval: 20,
    action: () => {
    // 擴散藍和擴散紅
      waveScale(scaleList, dltScale, maxScale, minScale);
    }
  });
}複製代碼

2. 旋轉效果

預覽圖:

代碼:

function rotateAction(obj, dlt) {
  // 獲取圖元旋轉弧度值,沒有就置零
  let rotation = obj.getRotation() || 0;
  // 每幀弧度增長
  obj.setRotation(rotation + dlt);
}
function startAnim() {
  ht.Default.startAnim({
    frames: Infinity,
    interval: 20,
    action: () => {
      // 衛星轉動
      rotateAction(star, dltRoattion);
    }
  });
}複製代碼

3. 流動效果

預覽圖:

流動效果是很是常見的效果,實現的過程也較爲簡單,只須要動態地去改變 uv 貼圖的偏移值便可。在本例中,經過對模型六面的貼圖的 U 方向實施動態增減實現了多個流動效果:

function uvFlow(obj, dlt) {
  // 改變貼圖 uv 座標實現流動效果
  let offset = obj.s('all.uv.offset') || [0, 0];
  obj.s('all.uv.offset', [offset[0] + dlt, offset[1]]);
}
function startAnim() {
  ht.Default.startAnim({
    frames: Infinity,
    interval: 20,
    action: () => {
      // 小路流動效果
      uvFlow(roadSmall, dltRoadSmall);
    }
  });
}複製代碼

4. 浮動效果

預覽圖:

代碼:

function blockFloat(obj, dis, dlt) {
  obj.forEach(node => {
    let startE = node.a('startE');
    if (startE == null)
    // 得到圖元在 y(高度)方向上的值
      node.a('startE', startE = node.getElevation());
    let float = node.a('float') || 0;
    // 設置 status 爲方向
    let status = node.a('status') || 1;
    node.setElevation(startE + dis * float);
    if (float > 1 || float < 0)
    // 超出閥值則改變方向
      node.a('status', status = -status);
    float += dlt * status;
    // 從新設置圖元高度
    node.a('float', float);
  });
}
function startAnim() {
  ht.Default.startAnim({
    frames: Infinity,
    interval: 20,
    action: () => {
      // 消防標誌浮動效果
      blockFloat(fireFloatList, fireFloadDis, fireFloatDlt)
    }
  });
}複製代碼

這樣,一個基本的效果就實現了。

HT 的 3D 城市羣方案不只能夠在大屏上有良好的效果,在移動端也有着不錯的體驗,這使得城市管理者無論什麼時候何地都能獲取到實時的監控信息,這裏放兩張在移動端瀏覽器上的預覽圖給你們體驗一下:

HT包含了數百個工業互聯網 2D 3D 可視化應用案例,點擊這裏體驗把玩:http://www.hightopo.com/demos/index.html

相關文章
相關標籤/搜索