第 2 阶段练习与参考答案

按教程目录完成第 5–7 章后,运行阶段示例并完成以下练习。先观察结果,再阅读参考答案。

练习 1:画出渲染环境中的对象关系

打开浏览器控制台,检查 <code>genericRenderWindow</code> 取得的 Renderer、RenderWindow 和 Interactor。回答:

  1. 哪个对象管理球体与立方体 Actor?
  2. 哪个对象持有活动 Camera?
  3. 哪个对象处理用户输入?
  4. DOM 容器的大小变化后,应调用哪个对象的方法?

参考答案

Renderer 管理 Actor,也持有活动 Camera。Interactor 接收用户输入,并交给交互样式解释。容器尺寸变化后调用 <code>genericRenderWindow.resize()</code>,让具体绘制视图的像素尺寸跟上容器。RenderWindow 负责组织并请求实际渲染。

练习 2:验证容器尺寸与绘制尺寸

先点击“缩窄画布”,确认图像仍正确显示。然后暂时注释掉 <code>ResizeObserver</code> 相关的两行,再刷新并点击同一个按钮。比较两种情况下画布像素大小:

const canvas = document.querySelector("#viewport canvas");
console.log(canvas.width, canvas.height);

参考答案

保留 Observer 时,容器宽度变化会触发 <code>genericRenderWindow.resize()</code>,canvas 的绘制缓冲区尺寸随之更新。去掉 Observer 后,CSS 布局仍会变,但绘制缓冲区尺寸可能保持旧值;画面可能被浏览器缩放或鼠标位置变得不准确。恢复 Observer 后重新运行示例。

练习 3:区分重新取景与重新设置裁剪范围

点击“斜视图”后,分别尝试:

  1. <code>renderer.resetCameraClippingRange()</code>
  2. <code>renderer.resetCamera()</code>

观察相机位置和焦点读数。哪个方法会让视角回到对象整体?

参考答案

<code>resetCameraClippingRange()</code> 更新近、远裁剪范围,通常不会把相机重新对准对象。<code>resetCamera()</code> 根据可见对象边界重新取景,会改变相机位置、焦点或显示尺度,使对象整体进入画面。不要在用户每次拖动后都调用后者,否则会覆盖刚调好的视角。

练习 4:比较两种投影

在透视投影下拖动视角,观察球和立方体的相对大小;切换平行投影后再观察。查阅状态行确认投影方式。回答:切换投影是否改变 Source 生成的数据或 Actor 的位置?

参考答案

不会。切换的是 Camera 的投影规则。球与立方体的数据、Mapper 和 Actor 位置都保持原样。透视投影具有近大远小效果;平行投影不会以同样方式随深度缩小,因此更适合某些需要比较形状与尺寸的视图。

练习 5:追踪交互事件

点击“暂停交互”后尝试拖动画布,再恢复交互并拖动一次。观察状态行中的交互次数。接着把示例里的 <code>interactorStyle.onStartInteractionEvent(…)</code> 暂时误写为 <code>interactor.onStartInteractionEvent(…)</code>,查看浏览器控制台,再改回。

参考答案

暂停时,拖动不会继续修改相机;恢复后,开始一次拖动会使交互计数增加。在本教程固定的 vtk.js 版本中,高层的 <code>onStartInteractionEvent</code> 属于当前交互样式;误写到 Interactor 上会出现方法不存在的运行错误。订阅时必须先确认事件由哪个对象发出。