第 4 章:第一个可运行程序

学习目标

本章完成一个可旋转、可缩放的球体示例。你将亲自建立 Source → Mapper → Actor → Renderer 的关系,并在运行结果中辨认“改变数据”和“改变外观”的不同效果。完整项目位于示例目录。

4.1 运行环境与目录

示例固定使用 <code>@kitware/vtk.js 37.4.2</code> 和 <code>Vite 7.3.1</code>。Vite 7 要求 Node.js <code>20.19+</code> 或 <code>22.12+</code>。先运行 <code>node --version</code> 检查版本;本机若仍使用 Node 12,需要切换到受支持的 Node 版本。

项目目录如下:

examples/stage-01/
├─ package.json
├─ index.html
└─ src/
   └─ main.js

你可以直接进入示例目录运行:

npm install
npm run dev

打开终端给出的本地地址。也可以运行 <code>npm run build</code> 检查项目能否完成生产构建。这个示例使用浏览器中的 WebGL 绘制,需在支持 WebGL 的浏览器里打开,而不是直接双击 HTML 文件。

4.2 项目依赖

<code>package.json</code> 固定依赖版本,避免教程正文与不同版本的 API 产生偏差:

{
  "name": "vtkjs-tutorial-stage-01",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  },
  "dependencies": {
    "@kitware/vtk.js": "37.4.2"
  },
  "devDependencies": {
    "vite": "7.3.1"
  }
}

<code>index.html</code> 只提供网页入口。我们把 vtk.js 代码放在 <code>src/main.js</code>,由 Vite 的模块系统加载:

<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>vtk.js 第一个程序</title>
  </head>
  <body>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

4.3 完整代码

<code>src/main.js</code> 的内容如下。先整体运行,再按后文逐段分析:

import "@kitware/vtk.js/Rendering/Profiles/Geometry";

import vtkFullScreenRenderWindow
  from "@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow";
import vtkSphereSource
  from "@kitware/vtk.js/Filters/Sources/SphereSource";
import vtkMapper
  from "@kitware/vtk.js/Rendering/Core/Mapper";
import vtkActor
  from "@kitware/vtk.js/Rendering/Core/Actor";

const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
  background: [0.12, 0.14, 0.18],
});

const renderer = fullScreenRenderer.getRenderer();
const renderWindow = fullScreenRenderer.getRenderWindow();

const sphereSource = vtkSphereSource.newInstance({
  radius: 0.7,
  thetaResolution: 32,
  phiResolution: 24,
});

const mapper = vtkMapper.newInstance();
mapper.setInputConnection(sphereSource.getOutputPort());

const actor = vtkActor.newInstance();
actor.setMapper(mapper);
actor.getProperty().setColor(0.95, 0.45, 0.15);

renderer.addActor(actor);
renderer.resetCamera();
renderWindow.render();

运行结果应是深色背景上的橙色球体。默认交互允许用鼠标改变观察方向与距离。若看到页面但没有球体,先打开浏览器开发者工具,检查是否有模块加载或 WebGL 报错。

4.4 逐段理解

加载几何渲染 Profile。 第一条导入语句是副作用导入:它注册本示例需要的几何渲染能力。它并未创建球,也不是一个显示对象。

建立浏览器渲染环境。 <code>vtkFullScreenRenderWindow.newInstance(…)</code> 创建一个方便入门的全屏环境,并提供 Renderer 与 RenderWindow。<code>background</code> 的三个数字是颜色分量,不属于球体数据。该辅助对象还处理画布和默认交互;第 2 阶段会拆解内部对象。

生成数据。 <code>vtkSphereSource</code> 根据半径和两个方向的分辨率产生球面数据。<code>thetaResolution</code>、<code>phiResolution</code> 越低,球面使用的离散面越少,轮廓越容易显出棱角。这些参数作用于 Source 的输出,而不是材质。

连接数据与 Mapper。 <code>sphereSource.getOutputPort()</code> 代表 Source 的输出端口。<code>mapper.setInputConnection(…)</code> 让 Mapper 沿管线取得球面数据。这一行并未把球放进 Renderer。

创建场景对象。 <code>actor.setMapper(mapper)</code> 指定 Actor 的数据映射。<code>actor.getProperty().setColor(…)</code> 设置表面颜色。颜色值在 0 到 1 之间;改变它不会改变 Source 生成的点和多边形。

加入场景并绘制。 <code>renderer.addActor(actor)</code> 使 Actor 可见。<code>resetCamera()</code> 应在添加对象之后调用,这样相机才能根据当前对象重新取景。最后的 <code>renderWindow.render()</code> 请求绘制。

4.5 验证你确实看到了数据与表示的区别

先把 <code>thetaResolution</code> 和 <code>phiResolution</code> 都改为 <code>8</code>。刷新后球体轮廓应更粗糙。再把 <code>setColor</code> 改为另一种颜色。前一项修改改变生成的几何数据,后一项只改变 Actor 的外观。

还可以在 <code>renderWindow.render()</code> 后加入以下观察代码:

console.log(sphereSource.getOutputData().getClassName());

你应看到 <code>vtkPolyData</code>。这说明 Source 输出的是数据对象,而不是 Actor。控制台检查不参与正常绘制,可以观察完后删去。

4.6 常见问题

现象 先检查什么
启动工具提示 Node 版本不支持 使用符合 Vite 7 要求的 Node.js
页面空白且控制台有模块错误 是否执行了 <code>npm install</code>,导入路径与依赖版本是否一致
有背景但没有球体 Source → Mapper、Mapper → Actor、Actor → Renderer 三处连接,以及是否调用 <code>resetCamera()</code>
改颜色却仍显示按数值着色 后续章节的标量可见性与颜色映射设置可能覆盖单一表面颜色
球体变成多面体 检查 Source 的两个分辨率参数

本章示例已经在所列版本下完成构建并在浏览器中验证显示。第 1 阶段的动手题和参考答案集中放在练习文件,以便正文章节专注解释概念与代码。

本章小结

你现在已经把一份由 Source 生成的数据接到了 Mapper,再经 Actor 放入 Renderer 并由 RenderWindow 画出来。下一阶段将拆开全屏辅助对象,进一步学习渲染窗口、相机和交互器。