
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的排序規(guī)則含左右兩側(cè)默認插入位置的差異以及如何把既有代碼平滑遷移到新 API并為后續(xù) 3.10 定制化viewportActionMenu.*與 3.11ToolbarService的演進打好基礎(chǔ)。背景為什么需要改變ViewportActionCornersService是 OHIF 平臺層platform/目錄提供的服務(wù)負責向視口viewport的角落注入自定義組件例如窗寬/窗位菜單、分割覆蓋層、方向標簽等 UI 元素。在 3.9 之前向角標添加組件使用的是setComponent或setComponents方法。這兩個方法的名字本身帶有設(shè)置語義——其行為更接近整體替換而非增量插入當多個組件被添加到同一個角標位置時后添加的組件本質(zhì)上會覆蓋同位置的已有組件只有非常小心地處理indexPriority屬性才能勉強讓多個組件共存于同一角落由于排序依賴調(diào)用方的細心維護跨擴展extension或跨模式mode疊加角標組件時極易出現(xiàn)組件莫名消失或順序錯亂的問題。從源碼結(jié)構(gòu)看這正是 3.9 將 API 從set*改為add*的動機set*隱含覆蓋賦值的語義與角標場景增量累積的實際需求相悖。新 APIaddComponent 與 addComponents新方法addComponent單個組件和addComponents批量組件將組件插入視口角標其定位規(guī)則如下可選的indexPriority傳入時新組件根據(jù)該值與角標中已有組件的相對indexPriority進行排序從而得到可預(yù)測、可復現(xiàn)的順序默認插入位置未傳indexPriority時——左側(cè)角標如topLeft、bottomLeft的組件追加到末尾右側(cè)角標如topRight、bottomRight的組件插入到開頭。這一左追加、右前置的默認策略是為了配合醫(yī)學影像界面中常見的布局習慣左側(cè)角標通常承載按添加順序排列的輔助信息右側(cè)角標則希望最新加入的交互組件優(yōu)先可見。新舊 API 對照維度舊 API3.8 及之前新 API3.9添加單個組件setComponent({ viewportId, id, component, location, indexPriority })addComponent({ viewportId, id, component, location, indexPriority? })批量添加組件setComponents([...])addComponents([...])indexPriority必須小心維護否則組件互相覆蓋可選決定角標內(nèi)的排列順序默認行為同位置組件互相覆蓋左側(cè)追加到末尾、右側(cè)插入到開頭多組件共存困難內(nèi)置支持順序可預(yù)測遷移步驟第一步替換方法名。將setComponent替換為addComponent、將setComponents替換為addComponents其余參數(shù)基本保持不變。舊 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 現(xiàn)在可選決定組件在角標內(nèi)的放置順序 });第二步審視同角標多組件場景。遷移后請檢查所有曾經(jīng)擠在同一個location的組件在舊 API 下它們可能依賴微妙的調(diào)用順序或indexPriority才得以共存在新 API 下應(yīng)明確為每個組件指定期望的indexPriority讓排序意圖顯式化。第三步利用默認行為簡化代碼。如果某個角標內(nèi)組件之間的相對順序無關(guān)緊要例如同一擴展添加的一組同質(zhì)按鈕可以省略indexPriority讓左側(cè)角標自然按添加順序排列、右側(cè)角標自然按最新優(yōu)先排列。indexPriority 的排序規(guī)則與類型定義新 API 的組件信息類型可從platform/ui-next/src/types/ActionCorners.ts查看其中ActionComponentInfo完整描述了每個角標組件的字段export type ActionComponentInfo { viewportId: string; id: string; component: ReactNode; location: ViewportActionCornersLocations; indexPriority?: number; // 可選決定同角標內(nèi)的排序 isLocked?: boolean; // 是否鎖定 isOpen?: boolean; // 是否默認展開 isVisible?: boolean; // 是否可見 };要點說明indexPriority為可選數(shù)值。數(shù)值越小優(yōu)先級越高、越靠前從按相對 indexPriority 排序的語義推斷id是組件在角標內(nèi)的唯一標識location必須來自ViewportActionCornersLocations枚舉其完整取值見platform/ui-next/src/components/Viewport/ViewportActionCorners.tsxtopLeft、topRight、bottomLeft、bottomRight、topMiddle、bottomMiddle、leftMiddle、rightMiddle——即除四角外還支持上/下/左/右四條邊的中間位置isLocked、isOpen、isVisible等可選標志為角標組件提供更細粒度的行為控制。對應(yīng)的渲染屬性類型ViewportActionCornersProps定義于platform/ui-next/src/types/ViewportActionCornersTypes.ts表明角標組件以cornerComponents的形式按位置分組傳入并可通過visibleItemsPerCorner控制每個角落最多顯示的條目數(shù)。角標渲染機制從服務(wù)到 React 組件在新架構(gòu)下ViewportActionCornersService管理的是哪些組件掛在哪個角落、以什么順序而真正的 DOM 渲染由 UI 層組件完成。platform/ui-next/src/components/Viewport/ViewportActionCorners.tsx實現(xiàn)了這套渲染骨架ViewportActionCorners.Container維護一個以ViewportActionCornersLocations為鍵的corners狀態(tài)通過 Context 提供registerCorner注冊接口渲染時對每個位置套用對應(yīng)的絕對定位 CSS 類例如topLeft使用absolute top-[4px] left-[0px] pl-[4px]Corner子組件TopLeft、TopRight、BottomLeft、BottomRight、TopMiddle、BottomMiddle、LeftMiddle、RightMiddle等負責把各自的 children 注冊到對應(yīng)位置且必須位于Container內(nèi)部否則會拋出Corner component must be used within a ViewportActionCorners.Container錯誤。在 cornerstone 擴展側(cè)extensions/cornerstone/src/components/OHIFViewportActionCorners.tsx展示了實際接線方式它基于useViewportHover判斷視口是否被懸?;蚣せ頸sHovered || isActive才渲染角標隨后用ViewportActionCorners.Container包裹八個Toolbar插槽每個插槽對應(yīng)一個工具欄分區(qū)如viewportActionMenu.topLeft。與 customizationService 的結(jié)合viewportActionMenu 定制從 3.10 開始角標組件的內(nèi)容可以通過customizationService以viewportActionMenu.location為鍵進行聲明式定制官方 FAQ 文檔 add-viewport-icon 給出了完整可運行的示例。關(guān)鍵位置鍵包括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, }, ], }, }); }每個條目的結(jié)構(gòu)為{ id, enabled, component }id唯一標識、enabled控制顯隱、component返回一個 React 組件。多個組件在同一角落按數(shù)組順序渲染。若需要為彈出菜單計算正確的對齊方式可使用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指定位置且可用數(shù)值如location: 1表示枚舉序數(shù)到 3.10 后它們統(tǒng)一演進為viewportActionMenu.*命名空間的定制條目。組件在角標內(nèi)的渲染順序即數(shù)組順序這與新 API 中基于indexPriority的可預(yù)測排序的設(shè)計目標一致。后續(xù)演進3.11 中服務(wù)被 ToolbarService 取代值得說明的是ViewportActionCornersService的生命周期并未止步于 3.9。在 3.11 中該服務(wù)連同ViewportActionCornersProvider、useViewportActionCorners鉤子一并被移除角標功能整體并入ToolbarService角標條目以標準工具欄按鈕的形式掛載到專用分區(qū)如toolbarService.sections.viewportActionMenu.topLeft詳見 3.10 到 3.11 的 toolbarService 遷移文檔 與 viewport-action-menu 遷移文檔。因此建議遷移到 3.9 時注意節(jié)奏面向3.9 / 3.10的代碼請完成本文所述的setComponent→addComponent替換并善用indexPriority面向3.11 及以后的新代碼則建議直接采用ToolbarServiceviewportActionMenu.location分區(qū)的方式編寫角標 UIOHIFViewportActionCorners.tsxextensions/cornerstone/src/components/OHIFViewportActionCorners.tsx中每個角落渲染一個Toolbar的實現(xiàn)就是這套新模式的直接參考。遷移檢查清單全局搜索setComponent/setComponents替換為addComponent/addComponents對同角標多組件顯式設(shè)置indexPriority以明確順序無順序要求時省略indexPriority利用左側(cè)末尾、右側(cè)開頭的默認插入行為檢查location取值確保來自ViewportActionCornersLocations枚舉四角 四邊中點若使用定制化方式確認viewportActionMenu.location鍵名與{ id, enabled, component }結(jié)構(gòu)正確規(guī)劃未來升級3.11 起改用ToolbarService.sections.viewportActionMenu.location。結(jié)語從setComponent到addComponent的變更本質(zhì)是把覆蓋式賦值的角標語義修正為增量插入 顯式排序。indexPriority的可選化與默認插入位置的設(shè)計讓 OHIF 的擴展開發(fā)者無需再為同角落多組件的共存問題提心吊膽。掌握這一遷移要點既能順利完成 3.8 → 3.9 的升級也能平滑銜接 3.10 的聲明式定制與 3.11 的ToolbarService架構(gòu)?!久赓M下載鏈接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages項目地址: https://gitcode.com/GitHub_Trending/vi/Viewers創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考