
OHIF 3.9 ViewportActionCornersService 迁移指南从 setComponent 到 addComponent 的多组件角标定位【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers导读本文是 OHIF 3.8 → 3.9 迁移指南系列中的一篇聚焦ViewportActionCornersService的 API 变化。OHIF 在 3.9 中引入了addComponent/addComponents新方法从根本上解决了旧setComponent/setComponents在多个组件同处一个视口角标viewport corner时互相覆盖的难题并通过可选的indexPriority属性提供确定性的排列顺序。读完本文你将掌握新旧 API 的差异、indexPriority的排序规则含左右两侧默认插入位置的差异以及如何把既有代码平滑迁移到新 API并为后续 3.10 定制化viewportActionMenu.*与 3.11ToolbarService的演进打好基础。背景为什么需要改变ViewportActionCornersService是 OHIF 平台层platform/目录提供的服务负责向视口viewport的角落注入自定义组件例如窗宽/窗位菜单、分割覆盖层、方向标签等 UI 元素。在 3.9 之前向角标添加组件使用的是setComponent或setComponents方法。这两个方法的名字本身带有设置语义——其行为更接近整体替换而非增量插入当多个组件被添加到同一个角标位置时后添加的组件本质上会覆盖同位置的已有组件只有非常小心地处理indexPriority属性才能勉强让多个组件共存于同一角落由于排序依赖调用方的细心维护跨扩展extension或跨模式mode叠加角标组件时极易出现组件莫名消失或顺序错乱的问题。从源码结构看这正是 3.9 将 API 从set*改为add*的动机set*隐含覆盖赋值的语义与角标场景增量累积的实际需求相悖。新 APIaddComponent 与 addComponents新方法addComponent单个组件和addComponents批量组件将组件插入视口角标其定位规则如下可选的indexPriority传入时新组件根据该值与角标中已有组件的相对indexPriority进行排序从而得到可预测、可复现的顺序默认插入位置未传indexPriority时——左侧角标如topLeft、bottomLeft的组件追加到末尾右侧角标如topRight、bottomRight的组件插入到开头。这一左追加、右前置的默认策略是为了配合医学影像界面中常见的布局习惯左侧角标通常承载按添加顺序排列的辅助信息右侧角标则希望最新加入的交互组件优先可见。新旧 API 对照维度旧 API3.8 及之前新 API3.9添加单个组件setComponent({ viewportId, id, component, location, indexPriority })addComponent({ viewportId, id, component, location, indexPriority? })批量添加组件setComponents([...])addComponents([...])indexPriority必须小心维护否则组件互相覆盖可选决定角标内的排列顺序默认行为同位置组件互相覆盖左侧追加到末尾、右侧插入到开头多组件共存困难内置支持顺序可预测迁移步骤第一步替换方法名。将setComponent替换为addComponent、将setComponents替换为addComponents其余参数基本保持不变。旧 API 写法viewportActionCornersService.setComponent({ viewportId, id: myComponent, component: MyComponent /, location: viewportActionCornersService.LOCATIONS.topRight, });新 API 写法viewportActionCornersService.addComponent({ viewportId, id: myComponent, component: MyComponent /, location: viewportActionCornersService.LOCATIONS.topRight, indexPriority: 1, // indexPriority 现在可选决定组件在角标内的放置顺序 });第二步审视同角标多组件场景。迁移后请检查所有曾经挤在同一个location的组件在旧 API 下它们可能依赖微妙的调用顺序或indexPriority才得以共存在新 API 下应明确为每个组件指定期望的indexPriority让排序意图显式化。第三步利用默认行为简化代码。如果某个角标内组件之间的相对顺序无关紧要例如同一扩展添加的一组同质按钮可以省略indexPriority让左侧角标自然按添加顺序排列、右侧角标自然按最新优先排列。indexPriority 的排序规则与类型定义新 API 的组件信息类型可从platform/ui-next/src/types/ActionCorners.ts查看其中ActionComponentInfo完整描述了每个角标组件的字段export type ActionComponentInfo { viewportId: string; id: string; component: ReactNode; location: ViewportActionCornersLocations; indexPriority?: number; // 可选决定同角标内的排序 isLocked?: boolean; // 是否锁定 isOpen?: boolean; // 是否默认展开 isVisible?: boolean; // 是否可见 };要点说明indexPriority为可选数值。数值越小优先级越高、越靠前从按相对 indexPriority 排序的语义推断id是组件在角标内的唯一标识location必须来自ViewportActionCornersLocations枚举其完整取值见platform/ui-next/src/components/Viewport/ViewportActionCorners.tsxtopLeft、topRight、bottomLeft、bottomRight、topMiddle、bottomMiddle、leftMiddle、rightMiddle——即除四角外还支持上/下/左/右四条边的中间位置isLocked、isOpen、isVisible等可选标志为角标组件提供更细粒度的行为控制。对应的渲染属性类型ViewportActionCornersProps定义于platform/ui-next/src/types/ViewportActionCornersTypes.ts表明角标组件以cornerComponents的形式按位置分组传入并可通过visibleItemsPerCorner控制每个角落最多显示的条目数。角标渲染机制从服务到 React 组件在新架构下ViewportActionCornersService管理的是哪些组件挂在哪个角落、以什么顺序而真正的 DOM 渲染由 UI 层组件完成。platform/ui-next/src/components/Viewport/ViewportActionCorners.tsx实现了这套渲染骨架ViewportActionCorners.Container维护一个以ViewportActionCornersLocations为键的corners状态通过 Context 提供registerCorner注册接口渲染时对每个位置套用对应的绝对定位 CSS 类例如topLeft使用absolute top-[4px] left-[0px] pl-[4px]Corner子组件TopLeft、TopRight、BottomLeft、BottomRight、TopMiddle、BottomMiddle、LeftMiddle、RightMiddle等负责把各自的 children 注册到对应位置且必须位于Container内部否则会抛出Corner component must be used within a ViewportActionCorners.Container错误。在 cornerstone 扩展侧extensions/cornerstone/src/components/OHIFViewportActionCorners.tsx展示了实际接线方式它基于useViewportHover判断视口是否被悬停或激活isHovered || isActive才渲染角标随后用ViewportActionCorners.Container包裹八个Toolbar插槽每个插槽对应一个工具栏分区如viewportActionMenu.topLeft。与 customizationService 的结合viewportActionMenu 定制从 3.10 开始角标组件的内容可以通过customizationService以viewportActionMenu.location为键进行声明式定制官方 FAQ 文档 add-viewport-icon 给出了完整可运行的示例。关键位置键包括viewportActionMenu.topLeftviewportActionMenu.topRightviewportActionMenu.bottomLeftviewportActionMenu.bottomRight在模式的onModeEnter生命周期钩子中可以用$push增量追加、用$set整体替换function onModeEnter({ servicesManager }) { const { customizationService } servicesManager.services; customizationService.setCustomizations({ viewportActionMenu.topLeft: { // $push 追加到既有条目之后$set 则整体替换 $push: [ { id: modeSwitch, enabled: true, component: getModeSwitchMenu, }, ], }, }); }每个条目的结构为{ id, enabled, component }id唯一标识、enabled控制显隐、component返回一个 React 组件。多个组件在同一角落按数组顺序渲染。若需要为弹出菜单计算正确的对齐方式可使用viewportActionCornersService.getAlignAndSide(location)获取{ align, side }类型定义见platform/ui-next/src/types/ActionCorners.ts中的AlignAndSide再传给DropdownMenuContent的align与side属性。同时参考 3.9 到 3.10 的 CustomizationService 迁移文档3.9 时代viewportActionMenu.windowLevelActionMenu、viewportActionMenu.segmentationOverlay这类定制项通过location: viewportActionCornersService.LOCATIONS.topRight指定位置且可用数值如location: 1表示枚举序数到 3.10 后它们统一演进为viewportActionMenu.*命名空间的定制条目。组件在角标内的渲染顺序即数组顺序这与新 API 中基于indexPriority的可预测排序的设计目标一致。后续演进3.11 中服务被 ToolbarService 取代值得说明的是ViewportActionCornersService的生命周期并未止步于 3.9。在 3.11 中该服务连同ViewportActionCornersProvider、useViewportActionCorners钩子一并被移除角标功能整体并入ToolbarService角标条目以标准工具栏按钮的形式挂载到专用分区如toolbarService.sections.viewportActionMenu.topLeft详见 3.10 到 3.11 的 toolbarService 迁移文档 与 viewport-action-menu 迁移文档。因此建议迁移到 3.9 时注意节奏面向3.9 / 3.10的代码请完成本文所述的setComponent→addComponent替换并善用indexPriority面向3.11 及以后的新代码则建议直接采用ToolbarServiceviewportActionMenu.location分区的方式编写角标 UIOHIFViewportActionCorners.tsxextensions/cornerstone/src/components/OHIFViewportActionCorners.tsx中每个角落渲染一个Toolbar的实现就是这套新模式的直接参考。迁移检查清单全局搜索setComponent/setComponents替换为addComponent/addComponents对同角标多组件显式设置indexPriority以明确顺序无顺序要求时省略indexPriority利用左侧末尾、右侧开头的默认插入行为检查location取值确保来自ViewportActionCornersLocations枚举四角 四边中点若使用定制化方式确认viewportActionMenu.location键名与{ id, enabled, component }结构正确规划未来升级3.11 起改用ToolbarService.sections.viewportActionMenu.location。结语从setComponent到addComponent的变更本质是把覆盖式赋值的角标语义修正为增量插入 显式排序。indexPriority的可选化与默认插入位置的设计让 OHIF 的扩展开发者无需再为同角落多组件的共存问题提心吊胆。掌握这一迁移要点既能顺利完成 3.8 → 3.9 的升级也能平滑衔接 3.10 的声明式定制与 3.11 的ToolbarService架构。【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考