• 作者:老汪软件技巧
  • 发表时间:2024-08-28 10:03
  • 浏览量:

⛳️ 前言

在我们日常需求中,除了需要对影像进行可视化展示外,大多数场景下还需要对影像进行调整、注释、分割等操作。Cornerstone3DTools库则支持大多数需要的交互功能。CornerstoneTools支持的工具类型主要分为以下4类:

针对以上4大类型,我们分为上中下3篇文章来展开介绍。上篇则主要对基础交互类工具和同步器工具进行介绍,围绕常用工具的种类、状态及如何注册使用等知识点展开。

效果演示

点击查看完整代码,欢迎star

交互工具工具组

工具

我们来看一下官网对于工具的定义,工具是至少实现了BaseTool接口的未实例化类。这样看来,一个工具其实就是一个类。我们除了可以使用官网中提供的这些工具之外,我们也可以根据它的定义去自定义一些我们需要的一些工具,关于自定义工具后面会详细说明,在这里我们主要是去介绍它内置的一些工具。如果我们想要使用一个工具的话,首先我们要使用库的顶级addTool函数来添加未实例化的工具,另外需要添加到工具组中。

工具组

以一种简单的方式去定义一个视图/一组工具的表现行为,具有相同工具组的视图将共享工具的配置项、模式等

常用工具

关于交互类工具,CornerstoneTools主要提供了以下功能, 标志为常用工具

 PanTool, // 平移工具
 TrackballRotateTool, // 3D旋转工具
 DragProbeTool, // 探针工具
 WindowLevelTool, // 窗宽窗距调整工具
WindowLevelRegionTool, // 窗宽窗距调整工具2
 ZoomTool, // 平移工具
 StackScrollTool, // 鼠标点击及拖动切换层级
 PlanarRotateTool, // 2D旋转工具
 StackScrollMouseWheelTool, // 鼠标滚动切换层级工具
VolumeRotateMouseWheelTool,
MIPJumpToClickTool,

工具状态

在了解完有哪些工具后,我们再来了解一下工具的状态有哪些?

关于操作类工具,我们用到的主要是Active 和 Disabled 两个状态,其他两种状态将在中篇注释工具中演示。

使用流程

在了解完基础的概念后,我们来看一下如何在代码中注册并激活工具。

注册工具

// 第一步:向全局状态中添加工具类
addTool(StackScrollMouseWheelTool);
// 第二步:向工具组中添加工具名
const toolGroup = ToolGroupManager.createToolGroup(groupId);
toolGroup.addTool(StackScrollMouseWheelTool.toolName);
// 第三步:将工具组与视图绑定(注意!!:同一时间,一个viewport只能绑定一个ToolGroup)
toolGroup.addViewport(viewportId1, renderingEngineId);
// 第四步:禁用鼠标上下文菜单(如果需要定义右键功能的话)
['element1', 'element2', 'element3'].forEach(id => {
  const dom = document.querySelector(`#${id}`);
  dom.oncontextmenu = () => false;
})

激活工具

关于工具的四种状态,都可以通过setToolxxxx()函数进行设置,以下为设置工具状态为激活状态

// 01 - 获取工具组
const toolGroup = ToolGroupManager.getToolGroup(groupId);
// 02 - 激活工具组的某个工具,并应该与左键【通过设置 mouseButton 属性,设置当前激活的工具是绑定与哪个按键/鼠标键的】
toolGroup.setToolActive(PanTool.toolName, {
   bindings: [{mouseButton: cstEnums.MouseBindings.Primary}],
});

切换工具

通过上面两步就完成了工具的注册与激活,此时就可以直接使用当前激活的工具。但是一个视图中可能有多个工具需要切换,那在切换的时候需要注意以下事项:

const toolGroup = ToolGroupManager.getToolGroup(groupId);
// 第一步:获取当前左键已激活的工具
const activePrimaryToolName = toolGroup.getActivePrimaryMouseButtonTool();
// 第二步:避免重复激活某个工具
if (activePrimaryToolName === toolName) {
  ElMessage({
    message: '当前工具处已于激活状态,点击左键尝试操作',
    type: 'warning',
  })
  return;
}
// 第三步:禁用掉已激活的工具
if (activePrimaryToolName) {
  toolGroup.setToolDisabled(activePrimaryToolName);
}
// 第四步:启用当前选中的工具
toolGroup.setToolActive(toolName, {
  bindings: [{mouseButton: cstEnums.MouseBindings.Primary}],
});

至此,就完成了一套工具的注册、激活、切换的流程,一般我们可以将需要注册的工具作为一个数组或配置项,遍历循环注册添加即可。

同步器介绍

我们在使用工具时,可能会遇到在视图A调整缩放或调整窗宽窗位时,在视图B中也要同步响应的需求。这时就需要用到了同步器工具。同步器接受一个源视图、一个目标视图,监听的事件及事件发生在源视图后执行的回调事件。我们使用同步器的目的就是要在多个视图之间进行交互同步,Cornerstone支持自定义同步器,同时也内置了一些常用同步器,本文主要介绍一下内置同步器的使用。

内置同步器

使用流程注册同步器

在cornerstoneTool中内置了以上4种功能的同步器,我们可以直接引入后创建使用

// 第一步:从同步器对象中声明已定义的同步器
const {
  createCameraPositionSynchronizer,
  createVOISynchronizer,
  createZoomPanSynchronizer,
  createImageSliceSynchronizer,
} = synchronizers;
// 第二步:创建需要的同步器实例
createCameraPositionSynchronizer(cameraSynchronizerId); 
createVOISynchronizer(voiSynchronizerId, {
  syncInvertState: false,
});
createZoomPanSynchronizer(zoomSynchronizerId);
createImageSliceSynchronizer(imageSliceSynchronizerId);

添加视图

在创建完同步器后,只需要为同步器添加视图即可实现同步

const synchronizer = SynchronizerManager.getSynchronizer(cameraSynchronizerId);
synchronizer.add({
  renderingEngineId,
  viewportId: viewportId,
});

synchronizer.addSource({
  renderingEngineId,
  viewportId: viewportId,
});

synchronizer.addTarget({
  renderingEngineId,
  viewportId: viewportId,
});

切换视图

如果想要添加同步视图,使用 add() 函数,但是如果想要删除同步视图,相同参数下使用 remove() 函数

if (toggle) {
  synchronizer.add({
    renderingEngineId,
    viewportId: event.target.value,
  });
} else {
  synchronizer.remove({
    renderingEngineId,
    viewportId: event.target.value,
  });
}

结束语

至此,我们就介绍完了关于交互工具和同步器的一些基础使用。通过介绍工具的种类、状态和如何去使用一个工具、如何去使用一个同步器等相关内容,完成了上述Demo中的全部功能点的实现。涵盖了日常需求中影像缩放、移动等交互操作、多视图同步等需求场景。文中涉及到的代码已全部更新至 github,欢迎评论交流