geojson-3d-renderer:从原理到实践,打造高性能3D地理可视化库

geojson-3d-renderer: 3D GeoJSON 可视化

geojson-3d-renderer 是我制作的一个功能强大的 3D GeoJSON 可视化库,兼容 Three.js、Vue.js + Three.js 和 TresJS 环境。提供 Vue 组件、钩子和工具函数,用于在 3D 空间中渲染 GeoJSON 数据,并支持自定义材质。

演示示例

中文文档

Github

  • 🗺️ 基于墨卡托投影的 3D GeoJSON 可视化
  • 🎨 可自定义材质的几何体生成(形状和线条)
  • ⚡ Vue 3 Composition API 支持
  • 📦 支持 Tree-shaking,轻量级
  • 🔧 TypeScript 支持

用法

安装

bash 复制代码
npm install geojson-3d-renderer
# 或
yarn add geojson-3d-renderer
# 或
pnpm add geojson-3d-renderer

Vue 组件

需要在 Vue.js、Three.js 和 TresJS 环境中使用

vue 复制代码
<template>
  <TresCanvas>
    <TresPerspectiveCamera :position="[0, 0, 50]" />
    <OrbitControls />
    <GeoJson
      url="https://geo.datav.aliyun.com/areas_v3/bound/100000_full_city.json"
      :mercator-center="[104.0, 37.5]"
      :options="{
        mercatorScale: 30,
        extrudeDepth: 1,
        lineOffset: 0.01,
      }"
    />
  </TresCanvas>
</template>

<script setup>
import { TresCanvas, TresPerspectiveCamera } from '@tresjs/core'
import { OrbitControls } from '@tresjs/cientos'
import { GeoJson } from 'geojson-3d-renderer'
</script>

Composition API

需要在 Vue.js、Three.js 环境中使用

vue 复制代码
<template>
  <TresCanvas>
    <TresPerspectiveCamera :position="[0, 0, 50]" />
    <OrbitControls />
    <TresGroup>
      <TresMesh v-if="shapeGeometry" :geometry="shapeGeometry">
        <TresMeshBasicMaterial color="#409EFF" />
      </TresMesh>
      <TresLineSegments v-if="lineGeometry" :geometry="lineGeometry">
        <TresLineBasicMaterial color="#000000" />
      </TresLineSegments>
    </TresGroup>
  </TresCanvas>
</template>

<script setup>
import {
  TresCanvas,
  TresPerspectiveCamera,
  TresGroup,
  TresMesh,
  TresLineSegments,
} from '@tresjs/core'
import { OrbitControls } from '@tresjs/cientos'
import { useGeojson } from 'geojson-3d-renderer'

const { mergedShapeGeometry: shapeGeometry, mergedLineGeometry: lineGeometry } = useGeojson(
  'https://geo.datav.aliyun.com/areas_v3/bound/100000_full_city.json',
  [104.0, 37.5],
  {
    mercatorScale: 30,
    extrudeDepth: 1,
    lineOffset: 0.01,
  }
)
</script>

工具函数 (Utility Function)

需要在 Three.js 环境中使用

ts 复制代码
import { genGeojsonGeometry } from 'geojson-3d-renderer/utils'

const { mergedShapeGeometry, mergedLineGeometry } = await genGeojsonGeometry(
  'https://geo.datav.aliyun.com/areas_v3/bound/100000_full_city.json',
  [104.0, 37.5],
  {
    mercatorScale: 30,
    extrudeDepth: 1,
    lineOffset: 0.01,
  }
)

原理解析

整体架构设计

genGeojsonGeometry.ts 是整个库的核心模块,负责将 GeoJSON 数据转换为 Three.js 可渲染的几何体。其整体架构设计遵循了职责分离原则:

text 复制代码
// 模块职责划分
genGeojsonGeometry()
├── 数据加载 (d3.json)
├── 投影转换 (d3.geoMercator)
├── 几何体生成
│   ├── 填充几何体 (ExtrudeGeometry)
│   └── 线段几何体 (BufferGeometry)
└── 几何体合并 (BufferGeometryUtils)

下面主要介绍几何体的生成与合并

Three.js 几何体构建

填充几何体生成

填充几何体使用 Three.js 的 ExtrudeGeometry 实现:

ts 复制代码
const createGeometryFromPolygon = (polygon: number[][], projection: GeoProjection) => {
  const shape = new Shape()
  let firstPoint = true

  polygon.forEach((coord) => {
    const [x, y] = projection(coord as [number, number]) || [0, 0]
    if (firstPoint) {
      shape.moveTo(x, -y)  // 注意:Y 坐标取反,适应 Three.js 坐标系
      firstPoint = false
    } else {
      shape.lineTo(x, -y)
    }
  })

  const extrudeSettings = {
    depth: mergedOptions.extrudeDepth,  // 挤出深度
    bevelEnabled: false,               // 禁用斜面
  }

  return new ExtrudeGeometry(shape, extrudeSettings)
}

线段几何体生成

线段几何体使用 Three.js 的 BufferGeometry 实现:

ts 复制代码
const createLineSegmentsFromPolygon = (polygon: number[][], projection: GeoProjection) => {
  const n = polygon.length
  if (n < 2) return new BufferGeometry()
  
  // 使用 TypedArray 优化性能
  const vertexCount = n * 2
  const positions = new Float32Array(vertexCount * 3)
  let ptr = 0
  
  for (let i = 0; i < n; i++) {
    const a = polygon[i] as [number, number]
    const b = polygon[(i + 1) % n] as [number, number]
    const [ax, ay] = projection(a) || [0, 0]
    const [bx, by] = projection(b) || [0, 0]
    
    // 线段起点
    positions[ptr++] = ax
    positions[ptr++] = -ay
    positions[ptr++] = lineZPosition  // Z 轴偏移

    // 线段终点  
    positions[ptr++] = bx
    positions[ptr++] = -by
    positions[ptr++] = lineZPosition
  }
  
  const lineGeometry = new BufferGeometry()
  lineGeometry.setAttribute('position', new Float32BufferAttribute(positions, 3))
  return lineGeometry
}

几何体合并优化

为了提高渲染性能,库使用 BufferGeometryUtils.mergeGeometries 进行几何体合并:

ts 复制代码
if (mergedOptions.needShapeGeometry) {
  mergedShapeGeometry = BufferGeometryUtils.mergeGeometries(shapeGeometryList)
  mergedShapeGeometry.computeBoundingSphere()
}

if (mergedOptions.needLineGeometry) {
  mergedLineGeometry = BufferGeometryUtils.mergeGeometries(lineGeometryList)
  mergedLineGeometry.computeBoundingSphere()
}

结束啦

这就是我做的一个将geojson渲染为3d的包啦

如果你有更好的方法或者建议,欢迎在下面留言,或者在 GitHub 提 issues

掰掰啦~~~

相关推荐
酒鼎9 小时前
学习笔记(12-02)事件循环 - 实战案例 —⭐
前端·javascript
Bigger9 小时前
第一章:我是如何剖析 Claude Code 整体架构与启动流程的
前端·aigc·claude
竹林8189 小时前
从“连接失败”到丝滑登录:我用 ethers.js v6 搞定 MetaMask 钱包连接的全过程
前端·javascript
oi..9 小时前
《Web 安全入门|XSS 漏洞原理、CSP 策略与 HttpOnly 防护实践》
前端·网络·测试工具·安全·web安全·xss
UXbot9 小时前
2026年AI全链路产品开发工具对比:5款从创意到上线一站式平台深度解析
前端·ui·kotlin·软件构建·swift·原型模式
一拳不是超人10 小时前
前端工程师也要懂的服务器部署知识:从 Nginx 到 CI/CD
服务器·前端
AlkaidSTART10 小时前
TanStack Query 技术指南:异步状态管理核心实践
前端·react.js
三原10 小时前
超级好用的三原后台管理v1.0.0发布🎉(Vue3 + Ant Design Vue + Java Spring Boot )附源码
java·vue.js·开源
之歆10 小时前
RBAC权限模型设计与实现深度解析
vue.js
种花家的强总10 小时前
前端项目开发/维护中降低成本的方式之一:降低耦合度
前端