• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

arc3dlab

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

第四篇:一行代码创建地球?今天我们亲手封装第一个 SDK 模块!

📘 专栏说明

本专栏旨在手把手带你从零开始,基于开源三维地球引擎 Cesium 封装一套功能完善、可复用的 WebGIS 增强型 SDK。内容涵盖核心封装思路、关键代码实现、常用 GIS 功能抽象,以及基于该 SDK 构建的 UI 组件库开发。如果你更关注结果而非实现过程,也可直接使用已发布的成果:

🌟 GitHub仓库 📦 NPM 包 ✨ 公众号:经纬码客(欢迎关注)

💡 建议:即便你打算直接使用 SDK,也推荐订阅本专栏 -- 理解设计思路,才能更灵活地扩展属于你自己的专属 GIS 能力!

由于作者需兼顾全职工作,更新主要安排在晚间或节假日,无法保证高频发布,但会持续迭代,直至 SDK 达到实际项目落地标准。届时将完整开源所有源码,供学习与商用(遵循许可证协议)。

大家好,我是 Cesium 酱(也可以叫我“本猿”),一名在 WebGIS 领域摸爬滚打多年的前端开发者。前几期,我们搭好了项目骨架、配好了打包工具、生成了API文档框架。

但说实话——那都只是“工地”。

今天,我们终于要砌第一块砖了!

这块砖的名字叫:Arc3DLab.Viewer。

它的使命很简单:
✅ 默认关闭所有花里胡哨的按钮
✅ 自动适配中国视角
✅ 支持一键开启帧率、Mapbox 控制模式
✅ 隐藏 Cesium Ion 版权信息(合规前提下)
✅ 让你用一行代码就看到地球!

准备好了吗?打开你的编辑器(我用的 VS Code),我们开始敲代码!


🧱 第一步:明确需求 —— 我们想要什么样的 Viewer?

原生 Cesium.Viewer 虽然强大,但默认配置对国内开发者并不友好:

  • 左下和右上角一堆按钮(动画、时间轴、帮助…)
  • 初始视角是全球,但我们要聚焦中国
  • 必须手动设置 Token
  • 想关掉版权信息?得自己找 DOM

于是,我们决定:继承它,改造它,封装它!


✍️ 第二步:定义接口(TypeScript 的优势来了!)

在 src/types/index.ts 中,先定义我们的配置选项:

// src/types/index.ts
import type { Viewer as CesiumViewer } from "cesium"
/**
 * Viewer 类的配置选项
 * @interface Option
 * @extends Cesium.Viewer.ConstructorOptions
 */
export interface Option extends CesiumViewer.ConstructorOptions {
  /** Cesium Ion 默认访问令牌 */
  defaultKey?: string
  /** 是否显示帧率(FPS) */
  fpsShow?: boolean
  /** 是否启用 Mapbox 风格的交互控制(中键缩放 + 右键旋转) */
  mapboxController?: boolean
}

💡 通过 extends Cesium.Viewer.ConstructorOptions,我们保留所有原生配置能力,只新增我们需要的字段。


🛠️ 第三步:创建核心类 —— Viewer.ts

新建文件 src/core/Viewer.ts,开始写我们的增强类:

// src/core/Viewer.ts
import * as Cesium from "cesium"
import { Option } from "../types"
import { BaseLayer } from "./BaseLayer" // 后续会讲,这里先假设有一个默认底图
// 设置默认相机视角为中国区域
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = new Cesium.Rectangle(
  Cesium.Math.toRadians(70),   // 西边界(经度)
  Cesium.Math.toRadians(-15),  // 南边界(纬度)
  Cesium.Math.toRadians(140),  // 东边界
  Cesium.Math.toRadians(80)    // 北边界
)
export class Viewer extends Cesium.Viewer {
  constructor(container: Element | string, public options?: Option) {
    super(container, {
      // —————— 默认关闭所有 UI 控件 ——————
      animation: false,
      fullscreenButton: false,
      geocoder: false,
      homeButton: false,
      infoBox: false,
      sceneModePicker: false,
      timeline: false,
      baseLayerPicker: false,
      navigationHelpButton: false,
      vrButton: false,
      selectionIndicator: false,
      // —————— 性能与渲染优化 ——————
      sceneMode: Cesium.SceneMode.SCENE3D,
      scene3DOnly: true,
      shouldAnimate: true,
      orderIndependentTranslucency: true,
      shadows: false,
      // —————— WebGL 上下文优化 ——————
      contextOptions: {
        webgl: {
          antialias: true,
          alpha: true,
          powerPreference: "high-performance",
          failIfMajorPerformanceCaveat: true,
          preserveDrawingBuffer: false,
        },
        requestWebgl1: false,
      },
      // —————— 使用自定义默认底图(支持离线) ——————
      baseLayer: BaseLayer.DefaultSingleImg,
      // —————— 合并用户传入的配置 ——————
      ...options,
    })
    // 初始化基础配置
    this.initBaseConfig()
  }
  private initBaseConfig() {
    // 1. 设置 Cesium Ion Token(优先使用用户传入的)
    Cesium.Ion.defaultAccessToken = this.options?.defaultKey || "你的默认Token"
    // 2. 开启地形深度检测(地下物体不可见)
    this.scene.globe.depthTestAgainstTerrain = true
    // 3. 时间流速设为正常
    this.clock.multiplier = 1
    // 4. 禁止相机穿地(碰撞检测)
    this.scene.screenSpaceCameraController.enableCollisionDetection = true
    // 5. 隐藏 Cesium 版权信息
    ;(this.cesiumWidget.creditContainer as any).style.display = "none"
    // 6. 高分辨率设备适配
    this.resolutionScale = window.devicePixelRatio
    // 7. Mapbox 交互模式(中键缩放 + 右键旋转)
    if (this.options?.mapboxController) {
      this.scene.screenSpaceCameraController.zoomEventTypes = [
        Cesium.CameraEventType.WHEEL,
        Cesium.CameraEventType.MIDDLE_DRAG,
        Cesium.CameraEventType.PINCH,
      ]
      this.scene.screenSpaceCameraController.tiltEventTypes = [
        Cesium.CameraEventType.RIGHT_DRAG,
        Cesium.CameraEventType.PINCH,
        { eventType: Cesium.CameraEventType.RIGHT_DRAG, modifier: Cesium.KeyboardEventModifier.CTRL },
        { eventType: Cesium.CameraEventType.MIDDLE_DRAG, modifier: Cesium.KeyboardEventModifier.CTRL },
      ]
    }
    // 8. 是否显示帧率
    this.scene.debugShowFramesPerSecond = this.options?.fpsShow || false
  }
}

⚠️ 注意:隐藏版权信息需确保你有合法使用权!本 SDK 仅作技术演示。

⭕这里面细心的小伙伴肯定发现了 BaseLayer.DefaultSingleImg 这个对象,没错这也是我们自定义的底图选项,下一期我们会仔细介绍!


🔌 第四步:导出模块,让别人能用

修改 src/index.ts:

// src/index.ts
export { Viewer } from "./core/Viewer"
// 后续会在这里导出更多模块

然后运行:

npm run build

如果成功,你会在 dist/ 目录看到打包后的文件!


在 demo-html/index.html 中添加:

<div id="map" style="width:100%;height:100vh;"></div>
<script type="module">
  import { Viewer } from '../dist/arc3dlab.esm.js'
  // 一行代码!创建地球
  const viewer = new Viewer('map', {
    fpsShow: true,
    mapboxController: true,
    defaultKey: '你的 Cesium Ion Token'
  })
</script>

- - 刷新页面 - -

🎉 一个干净、聚焦中国、无干扰按钮的三维地球出现了!


🤝 这只是开始!

这个 Viewer 类目前还很简单,但它是我们 SDK 的第一块基石。

后续我们可以自定义:

  • 添加 destroy() 方法做资源清理
  • 封装 flyToChina() 快捷方法
  • 支持自动加载离线底图(关于离线这块,确实不太友好,没办法浏览器安全通病)

而这一切,由你我共同完成。

如果你有想法:

  • “能不能加个自动 Token 管理?”
  • “我希望默认开启抗锯齿!”

欢迎来 GitHub 提 Issue!

你的每一个建议,都可能成为下一行代码。


🌟 项目开源,欢迎Star✨!

GitHub:https://github.com/jianlei-wang/Arc3DLab_SDK

NPM:https://www.npmjs.com/package/arc3dlab

Cesium 酱の百宝箱 · 第 4 篇

代码不多,但每行都有意义。

2026 年伊始,与你共写第一行可用之码。

posted on 2026-01-15 23:19  Arc3DLab  阅读(0)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3