程式碼倉庫地址:
https://github.com/openglobus/openglobus
原創。@秋意正寒
1 簡介
OpenGlobus
是一個設計用於顯示可互動性三維地圖、影像瓦片、向量資料、標註、三維物件的 JavaScript 庫。它所用的技術是純 WebGL
,完全開源免費。
它的目標是:讓三維地圖要素更快、更好看,使用者友好度拉滿並且在有關專案中容易編碼實現。
筆者注:
OpenGlobus
的起名,頗有三維界的OpenLayers
的意味
2 HelloGlobus
很容易能通過 npm scripts
中的 build
命令打包到一個生產模式的 umd 包,包括兩個檔案,一個 js 檔案,一個 css 檔案,寫這篇文章時,庫版本是 0.8.5
,所以上最簡單的示例程式碼:
<link rel="stylesheet" href="og-0.8.5.css">
<script src="og-0.8.5.js"></script>
<div id="viewport"></div>
<script>
const globus = new og.Globe({
target: 'viewport'
})
</script>
在控制檯,鍵入 og
可輸出全域性物件。
出圖大概是這樣的效果:
觀察控制檯的網路請求,不難發現在不新增任何圖層、高程資料的時候,它不會發生任何網路圖層的請求,也就是說,這個夜光圖和背景完全是內建在程式碼中的靜態資源。
3 在 Vite 中與 vue3 整合
經測試,Globe
物件暫不支援直接傳入 HTMLDivElement
,只能傳遞一個 id 字串,所以繫結 DOM ref 的方法行不通。
習慣性把屬性作為 vue 元件的 props 的開發者請注意,下列寫法雖然可以正確出現地球,但是這樣會增加監聽負載,一旦將來 globe 上的東西越來越多,WebGL 的幀率將不能保證:
<template>
<div id="viewport"></div>
</template>
<script setup>
import * as og from '@openglobus/og' // 發文時,還沒有型別定義庫 `*.d.ts`,所以暫時只能整體匯入,而不能用解構語法
import { onMounted, defineProps, ref } from 'vue'
import '/node_modules/@openglobus/og/css/og.css'
let globe = ref()
onMounted(() => {
globe = new og.Globe({
target: 'viewport'
})
})
defineProps([
'globe'
])
</script>
所以,我建議改成這樣:
<template>
<div id="viewport"></div>
</template>
<script setup>
import * as og from '@openglobus/og' // 發文時,還沒有型別定義庫 `*.d.ts`,所以暫時只能整體匯入,而不能用解構語法
import { onMounted } from 'vue'
import '/node_modules/@openglobus/og/css/og.css'
let globe = null
onMounted(() => {
globe = new og.Globe({
target: 'viewport'
})
})
</script>
4 在 Vite 中與 react 整合
這個就簡單了:
import React, { useEffect } from 'react'
import * as og from '@openglobus/og' // 發文時,還沒有型別定義庫 `*.d.ts`,所以暫時只能整體匯入,而不能用解構語法
import '/node_modules/@openglobus/og/css/og.css'
function App() {
useEffect(() => {
const globe = new og.Globe({
target: 'viewport'
})
}, [])
return <div id="viewport"></div>
}
export default App
5 示例程式碼
官網(www.openglobus.org)提供了一些示例程式碼,足夠學習使用,只要知道入口物件是 Globe
類即可。
6 API風格
不僅庫的名字類似 OpenLayers
,它還在很多 API 命名上“暫時”接近 ol。拿建立 XYZ 圖層來說:
const osm = new og.layer.XYZ("OpenStreetMap", {
isBaseLayer: true, // 是否是底圖
url: "//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", // url
visibility: true, // 可見性
attribution: 'Data @ OpenStreetMap contributors, ODbL' // 宣告之類的字串
});
和 OpenLayers
的比較:
const xyzSource = new ol.source.XYZ({
url: `https://{a-c}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=Your API key from http://www.thunderforest.com/docs/apikeys/ here`,
})
以及 Vector 圖層:
const markerLayer = new og.layer.Vector("Markers", {
clampToGround: true
})
在 ol 也有類似的 API 名稱。
更有趣的是,當前的示例內碼表面和 ol 6.5
的示例內碼表面極為相似:
og | ol |
---|---|
更別提 API 幫助文件了,我懷疑是用的同一個母模板。
7 目前已完成的功能(截至發文時)
基本資料載入功能
- GeoJson 資料載入
- 靜態圖片載入(並支援拖拽調整其四個角的位置)
- 地形服務載入(Mapbox的地形服務、GeoServer的Bil格式地形服務等),支援垂直誇大
- GeoServer WMS 載入
- Canvas瓦片載入(Canvas作為一層直接貼到地球表面)
- 廣告牌載入(類似於精靈?),支援貼地
- 視訊紋理
- 基本向量圖形繪製(polylines、marker、circle、ray等),marker支援互動式拖拽移動
介面定製與互動功能
- 支援自定義控制元件(類繼承形式實現,且暫時只能用原生 DOM)
- 支援 Popup(彈窗),彈窗樣式比較醜,雖然支援背面剔除,但是它的更新座標的機制感覺和 Cesium 自定義氣泡差不多... 都是監聽事件改變 DOM 的座標
- 支援圖層切換控制元件(儘管現在還很醜)
- 支援滑鼠滑過(mousemove)、左鍵單擊(lclick)等基本事件,也支援禁用事件
- 支援相機飛行動畫
渲染器及渲染效果相關功能
- 提供時鐘(儒略日期、UTC等均支援)
- 內建簡單的數學庫
- 圖層透明度設定
- 支援簡易太陽光
- 支援假性半透明顏色覆蓋
複雜的需求肯定達不到(例如將視訊完整地貼合複雜模型等),畢竟才釋出不久。
8 提供原生 WebGL 介面
在 GeoTexture2d
例子中,就出現了與底層 WebGL 幾乎完全一致的程式碼,例如 fbo、program、uniforms、attributes 等,也支援自定義的著色器程式碼,意味著應該是有底層的能力的。
9 展望未來
它建立於 2018 年,但是在 GitHub 上是今年 3 月才活躍起來的,官網列舉此庫的特點如下:
圖層支援
- WMS、WMTS
- 標籤和廣告牌
- 向量圖層:線與面型別
- 靜態覆蓋圖層:支援靜態圖片、視訊、WebGL FBO
- 自定義 canvas 瓦片圖層
- GeoJSON圖層
- 其他
預設控制元件
- 縮放按鈕
- 經緯度座標提示
- 圖層切換
- 太陽位置控制元件
- 指北針
- 互動式導航(即滑鼠鍵盤控制)
引擎的效能表現
- 純 WebGL 實現渲染器
- 支援多地球例項
- 單 WebGlProgram(不太確定)
- 內建時鐘,即時渲染
- 支援事件:draw、click、mouseenter等
- 支援圖層、物件的拾取
- LOD控制
- 舒適的互動體驗
- 無依賴!
三維視覺化
- 支援多種高程資料來源
- 柔和的燈光
- 自定義天空盒
- 圖層外觀支援自定義:光引數、高度調整、透明度、可見範圍等
- 軸對齊的廣告牌和標籤
- 即將支援:3dTiles、大氣散射效果、glTF模型
若再迭代十幾個版本,那是非常值得期待的,畢竟它的 API 更接近 GIS 風格。
但是,現在國內的需求更接近區域性展示而不是全球範圍展示,能不能被國內的piao客們青睞,還要再等等。