stack.image.viewer.tsx 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. import React, { useEffect, useRef } from 'react';
  2. import * as cornerstone from '@cornerstonejs/core';
  3. import type { Types } from '@cornerstonejs/core';
  4. import * as cornerstoneTools from '@cornerstonejs/tools';
  5. import * as cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader';
  6. import { useSelector } from 'react-redux';
  7. import { RootState } from '@/states/store';
  8. import { SystemMode } from '@/states/systemModeSlice';
  9. import store from '@/states/store';
  10. import { clearAction } from '@/states/view/functionAreaSlice';
  11. import { useDispatch } from 'react-redux';
  12. const {
  13. MagnifyTool,
  14. PanTool,
  15. WindowLevelTool,
  16. StackScrollTool,
  17. ZoomTool,
  18. LabelTool,
  19. ToolGroupManager,
  20. Enums: csToolsEnums,
  21. PlanarRotateTool,
  22. } = cornerstoneTools;
  23. const { MouseBindings } = csToolsEnums;
  24. let toolGroup: cornerstoneTools.Types.IToolGroup;
  25. let currentViewportId: string;
  26. function registerTools(viewportId, renderingEngineId) {
  27. // Add tools to Cornerstone3D
  28. cornerstoneTools.addTool(MagnifyTool);
  29. cornerstoneTools.addTool(PanTool);
  30. cornerstoneTools.addTool(WindowLevelTool);
  31. cornerstoneTools.addTool(StackScrollTool);
  32. cornerstoneTools.addTool(ZoomTool);
  33. cornerstoneTools.addTool(LabelTool);
  34. cornerstoneTools.addTool(PlanarRotateTool);
  35. // Define a tool group
  36. const toolGroupId = 'STACK_TOOL_GROUP_ID';
  37. const toolGroupTmp = ToolGroupManager.createToolGroup(toolGroupId);
  38. if (!toolGroupTmp) {
  39. return;
  40. }
  41. toolGroup = toolGroupTmp;
  42. // Add tools to the tool group
  43. toolGroup.addTool(MagnifyTool.toolName);
  44. toolGroup.addTool(PanTool.toolName);
  45. toolGroup.addTool(WindowLevelTool.toolName);
  46. toolGroup.addTool(StackScrollTool.toolName);
  47. toolGroup.addTool(ZoomTool.toolName);
  48. toolGroup.addTool(LabelTool.toolName);
  49. toolGroup.addTool(PlanarRotateTool.toolName);
  50. // Set the LabelTool as active
  51. // toolGroup.setToolActive(LabelTool.toolName, {
  52. // bindings: [
  53. // {
  54. // mouseButton: MouseBindings.Primary, // Left Click
  55. // },
  56. // ],
  57. // });
  58. // Set the initial state of the tools
  59. // toolGroup.setToolActive(WindowLevelTool.toolName, {
  60. // bindings: [
  61. // {
  62. // mouseButton: MouseBindings.Primary, // Left Click
  63. // },
  64. // ],
  65. // });
  66. toolGroup.setToolActive(PanTool.toolName, {
  67. bindings: [
  68. {
  69. mouseButton: MouseBindings.Auxiliary, // Middle Click
  70. },
  71. ],
  72. });
  73. toolGroup.setToolActive(ZoomTool.toolName, {
  74. bindings: [
  75. {
  76. mouseButton: MouseBindings.Secondary, // Right Click
  77. },
  78. ],
  79. });
  80. toolGroup.setToolActive(StackScrollTool.toolName, {
  81. bindings: [
  82. {
  83. mouseButton: MouseBindings.Wheel, // Mouse Wheel
  84. },
  85. ],
  86. });
  87. toolGroup.addViewport(viewportId, renderingEngineId);
  88. }
  89. function addLMark(): void {
  90. // Implement the logic to add an L mark
  91. console.log('Adding L Mark');
  92. toolGroup.setToolActive(LabelTool.toolName, {
  93. bindings: [
  94. // {
  95. // mouseButton: MouseBindings.Primary, // Left Click
  96. // },
  97. ],
  98. });
  99. const position: Types.Point3 = [100, 100, 0]; // Example position
  100. const text = 'L'; // Predefined text
  101. LabelTool.hydrate(currentViewportId, position, text);
  102. toolGroup.setToolPassive(LabelTool.toolName, {
  103. removeAllBindings: true,
  104. });
  105. // const enabledElement = cornerstone.getEnabledElementByViewportId(currentViewportId);
  106. // cursors.elementCursor.resetElementCursor(elementRef.current as HTMLDivElement);
  107. }
  108. function addRLabel(viewportId) {
  109. toolGroup.setToolActive(LabelTool.toolName, {
  110. bindings: [],
  111. });
  112. const element = document.getElementById(viewportId);
  113. const elementHeight = element ? element.getBoundingClientRect().height : 0;
  114. const position: Types.Point3 = [100, elementHeight / 2, 0]; // Example position
  115. const text = 'R'; // Predefined text
  116. LabelTool.hydrate(viewportId, position, text);
  117. toolGroup.setToolPassive(LabelTool.toolName, { removeAllBindings: true });
  118. }
  119. function adjustBrightnessAndContrast() {
  120. const planar = toolGroup.getToolInstance(WindowLevelTool.toolName); // Reset rotation angle
  121. const isActive = planar.mode === csToolsEnums.ToolModes.Active;
  122. if (isActive) {
  123. toolGroup.setToolPassive(WindowLevelTool.toolName, {
  124. removeAllBindings: true,
  125. });
  126. } else {
  127. toolGroup.setToolActive(WindowLevelTool.toolName, {
  128. bindings: [
  129. {
  130. mouseButton: MouseBindings.Primary, // Left Click
  131. },
  132. ],
  133. });
  134. }
  135. }
  136. function fitImageSize() {
  137. const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
  138. .viewport as cornerstone.StackViewport;
  139. viewport.resetCamera();
  140. viewport.render();
  141. }
  142. function deleteSelectedMark(): void {
  143. const viewport =
  144. cornerstone.getEnabledElementByViewportId(currentViewportId).viewport;
  145. const allAnnotations = cornerstoneTools.annotation.state.getAllAnnotations();
  146. for (const annotation of allAnnotations) {
  147. if (annotation.data.text === 'L' || annotation.data.text === 'R') {
  148. cornerstoneTools.annotation.state.removeAnnotation(
  149. annotation.annotationUID!
  150. );
  151. }
  152. }
  153. viewport.render();
  154. }
  155. function HorizontalFlip(): void {
  156. const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
  157. .viewport as cornerstone.StackViewport;
  158. // 切换水平翻转状态
  159. const { flipHorizontal } = viewport.getCamera();
  160. viewport.setCamera({ flipHorizontal: !flipHorizontal });
  161. console.log('Flipping Image Horizontally');
  162. }
  163. function VerticalFlip(): void {
  164. const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
  165. .viewport as cornerstone.StackViewport;
  166. // 切换竖直翻转状态
  167. const { flipVertical } = viewport.getCamera();
  168. viewport.setCamera({ flipVertical: !flipVertical });
  169. }
  170. function ApplyColormap(): void {
  171. const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
  172. .viewport as cornerstone.StackViewport;
  173. // Implement the logic to apply colormap
  174. viewport.setProperties({ colormap: { name: 'hsv' } });
  175. viewport.render();
  176. console.log('Applying Colormap');
  177. }
  178. function RotateCounterclockwise90(): void {
  179. const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
  180. .viewport as cornerstone.StackViewport;
  181. // let { rotation } = viewport.getViewPresentation();
  182. // const currentRotataion = viewport.getRotation();
  183. // viewport.rotation(22)
  184. // console.log(`rotation:${rotation}`)
  185. // if(!!rotation){
  186. // rotation=0;
  187. // }
  188. // viewport.setViewPresentation({ rotation: rotation ?? 0 + 30 });
  189. // // // Implement the logic to rotate the image counterclockwise
  190. // // viewport.setCamera({ rotation: -90 });
  191. // viewport.render();
  192. // // 1. 获取当前的视图表现状态(一个完整的对象)
  193. // const currentViewPresentation = viewport.getViewPresentation();
  194. // // 2. 创建一个新的对象,基于当前状态,只更新你需要修改的属性
  195. // // 使用展开运算符 (...) 来复制所有现有属性
  196. // const newViewPresentation = {
  197. // ...currentViewPresentation, // 保留所有原有属性,如 scale, translation, flip 等
  198. // rotation: currentViewPresentation.rotation ?? + 30, // 只覆盖 rotation 属性
  199. // };
  200. // // 3. 将完整的新状态对象设置回 viewport
  201. // viewport.setViewPresentation(newViewPresentation);
  202. // viewport.render();
  203. //----------------------------------------
  204. // // 获取当前的完整视图状态
  205. // const currentViewState = viewport.getViewPresentation();
  206. // // 创建新的视图状态对象,保持所有其他属性不变
  207. // const newViewState = {
  208. // ...currentViewState, // 保留所有现有属性
  209. // rotation: (currentViewState.rotation ?? 0 + 30) % 360 // 只修改rotation
  210. // };
  211. // // 设置新的视图状态
  212. // viewport.setViewPresentation(newViewState);
  213. // viewport.render();
  214. //-----------------------------------------
  215. // 获取当前相机
  216. const camera = viewport.getCamera();
  217. // // 计算新的旋转角度(当前角度 + 90度)
  218. // const newRotation = (camera.rotation ?? 0) + 90;
  219. // // 转换为弧度
  220. // const radians = newRotation * Math.PI / 180;
  221. // // 计算新的viewUp向量(顺时针旋转90度)
  222. // const newViewUp:[number, number, number] = [
  223. // Math.cos(radians), // X分量
  224. // Math.sin(radians), // Y分量
  225. // 0 // Z分量
  226. // ];
  227. // // 设置新的相机参数
  228. // viewport.setCamera({
  229. // ...camera, // 保持其他相机参数不变
  230. // viewUp: newViewUp, // 更新向上向量
  231. // rotation: newRotation // 更新旋转角度(可选,但推荐)
  232. // });
  233. // 计算新的旋转角度(当前角度 + 90度)
  234. const newRotation = (camera.rotation ?? 0) + 90;
  235. // 但计算viewUp向量时,我们应该使用90度的弧度,而不是新角度的弧度!
  236. const ninetyDegreesRadians = (90 * Math.PI) / 180;
  237. // 获取当前的viewUp向量
  238. const currentViewUp = camera.viewUp || [0, 1, 0];
  239. // 计算旋转后的viewUp向量(这才是正确的相对旋转)
  240. const newViewUp: [number, number, number] = [
  241. currentViewUp[0] * Math.cos(ninetyDegreesRadians) -
  242. currentViewUp[1] * Math.sin(ninetyDegreesRadians),
  243. currentViewUp[0] * Math.sin(ninetyDegreesRadians) +
  244. currentViewUp[1] * Math.cos(ninetyDegreesRadians),
  245. 0,
  246. ];
  247. // 设置新的相机参数
  248. viewport.setCamera({
  249. ...camera,
  250. viewUp: newViewUp,
  251. rotation: newRotation % 360, // 确保角度在0-359范围内
  252. });
  253. viewport.render();
  254. console.log('Rotating Image Counterclockwise 90°');
  255. }
  256. function RotateClockwise90(): void {
  257. const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
  258. .viewport as cornerstone.StackViewport;
  259. const camera = viewport.getCamera();
  260. // 计算新的旋转角度(当前角度 + 90度)
  261. const newRotation = (camera.rotation ?? 0) - 90;
  262. // 但计算viewUp向量时,我们应该使用90度的弧度,而不是新角度的弧度!
  263. const ninetyDegreesRadians = (90 * Math.PI) / 180;
  264. // 获取当前的viewUp向量
  265. const currentViewUp = camera.viewUp || [0, 1, 0];
  266. // 计算旋转后的viewUp向量(这才是正确的相对旋转)
  267. const newViewUp: [number, number, number] = [
  268. currentViewUp[0] * Math.cos(ninetyDegreesRadians) -
  269. currentViewUp[1] * Math.sin(ninetyDegreesRadians),
  270. currentViewUp[0] * Math.sin(ninetyDegreesRadians) +
  271. currentViewUp[1] * Math.cos(ninetyDegreesRadians),
  272. 0,
  273. ];
  274. // 设置新的相机参数
  275. viewport.setCamera({
  276. ...camera,
  277. viewUp: newViewUp,
  278. rotation: newRotation % 360, // 确保角度在0-359范围内
  279. });
  280. viewport.render();
  281. console.log('Rotating Image Clockwise 90°');
  282. }
  283. function ResetImage(): void {
  284. const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
  285. .viewport as cornerstone.StackViewport;
  286. // Implement the logic to reset the image
  287. // Resets the viewport's camera
  288. viewport.resetCamera();
  289. // Resets the viewport's properties
  290. viewport.resetProperties();
  291. viewport.render();
  292. console.log('Resetting Image');
  293. }
  294. function InvertImage(): void {
  295. const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
  296. .viewport as cornerstone.StackViewport;
  297. // Implement the logic to invert the image
  298. const invert = !viewport.getProperties().invert;
  299. viewport.setProperties({ invert });
  300. viewport.render();
  301. console.log('Inverting Image');
  302. }
  303. function setOriginalSize(viewport) {
  304. // 1) 先正常 fit(或本来就是 fit 状态)
  305. viewport.resetCamera();
  306. // 2) 计算“fit → 1:1”的放大倍数
  307. const { dimensions, spacing } = viewport.getImageData();
  308. console.log(`dimensions:${dimensions}, spacing:${spacing}`);
  309. const canvas = viewport.canvas;
  310. // 水平方向 1:1 需要的倍率
  311. const cssPixelsPerDicomPx = canvas.clientWidth / (dimensions[0] * spacing[0]);
  312. // 垂直方向 1:1 需要的倍率
  313. const cssPixelsPerDicomPy =
  314. canvas.clientHeight / (dimensions[1] * spacing[1]);
  315. // 取两者最小值,保证整张图不会被裁剪
  316. const zoomFactor = Math.min(cssPixelsPerDicomPx, cssPixelsPerDicomPy);
  317. console.log(`zoomFactor:${zoomFactor}`);
  318. console.log(
  319. `canvas.clientWidth:${canvas.clientWidth}, dimensions[0]:${dimensions[0]}, spacing[0]:${spacing[0]}`
  320. );
  321. console.log(
  322. `canvas.clientHeight:${canvas.clientHeight}, dimensions[1]:${dimensions[1]}, spacing[1]:${spacing[1]}`
  323. );
  324. // 3) 直接放大
  325. const zoom = viewport.getZoom();
  326. viewport.setZoom((zoom * 1) / zoomFactor);
  327. viewport.render();
  328. }
  329. const StackViewer = ({
  330. imageIndex = 0,
  331. imageUrls = [],
  332. }: {
  333. imageIndex?: number;
  334. imageUrls?: string[];
  335. }) => {
  336. const elementRef = useRef<HTMLDivElement>(null);
  337. const action = useSelector((state: RootState) => state.functionArea.action);
  338. const dispatch = useDispatch();
  339. useEffect(() => {
  340. const setup = async () => {
  341. // 初始化 Cornerstone
  342. cornerstone.init();
  343. cornerstoneTools.init();
  344. const state = store.getState();
  345. console.log(`当前系统模式:${state.systemMode.mode}`);
  346. const token =
  347. state.systemMode.mode === SystemMode.Emergency
  348. ? state.product.guest
  349. : state.userInfo.token;
  350. console.log(`token stack.image.viewer: ${token}`);
  351. cornerstoneDICOMImageLoader.init({
  352. maxWebWorkers: navigator.hardwareConcurrency || 1,
  353. errorInterceptor: (error) => {
  354. if (error.status === 401) {
  355. console.error('Authentication failed. Please refresh the token.');
  356. }
  357. console.error(`请求dcm文件出错:${error}`);
  358. },
  359. beforeSend: (xhr, imageId, defaultHeaders) => {
  360. return {
  361. ...defaultHeaders,
  362. Authorization: `Bearer ${token}`,
  363. Language: 'en',
  364. Product: 'DROS',
  365. Source: 'Electron',
  366. };
  367. },
  368. });
  369. // Instantiate a rendering engine
  370. const renderingEngineId = 'myRenderingEngine';
  371. const renderingEngine = new cornerstone.RenderingEngine(
  372. renderingEngineId
  373. );
  374. const viewportId = 'CT_AXIAL_STACK';
  375. currentViewportId = viewportId;
  376. const viewportInput: cornerstone.Types.PublicViewportInput = {
  377. viewportId,
  378. element: elementRef.current!,
  379. type: cornerstone.Enums.ViewportType.STACK,
  380. };
  381. renderingEngine.enableElement(viewportInput);
  382. registerTools(viewportId, renderingEngineId);
  383. // Get the stack viewport that was created
  384. const viewport = renderingEngine.getViewport(
  385. viewportId
  386. ) as cornerstone.Types.IStackViewport;
  387. // 给定一个dcm文件路径,加载并显示出来
  388. try {
  389. await viewport.setStack(imageUrls, imageIndex);
  390. } catch (error) {
  391. if (error instanceof Error) {
  392. console.error(
  393. '[stack.image.viewer] Error setting image stack:',
  394. error.message
  395. );
  396. } else {
  397. console.error('[stack.image.viewer] Unknown error:', error);
  398. }
  399. }
  400. viewport.render();
  401. };
  402. setup();
  403. }, [elementRef, imageIndex]);
  404. useEffect(() => {
  405. if (action) {
  406. // Handle the action
  407. switch (action) {
  408. case 'Add L Mark':
  409. addLMark();
  410. break;
  411. case 'Add R Mark':
  412. // Implement the logic to add an R mark
  413. addRLabel(currentViewportId);
  414. console.log('Adding R Mark');
  415. break;
  416. case 'Delete Selected Mark': {
  417. deleteSelectedMark();
  418. break;
  419. }
  420. case 'Horizontal Flip': {
  421. HorizontalFlip();
  422. break;
  423. }
  424. case 'Vertical Flip': {
  425. VerticalFlip();
  426. break;
  427. }
  428. case 'Rotate Counterclockwise 90': {
  429. RotateCounterclockwise90();
  430. break;
  431. }
  432. case 'Rotate Clockwise 90':
  433. RotateClockwise90();
  434. break;
  435. case 'Rotate Any Angle':
  436. // Implement the logic to rotate the image by any angle
  437. {
  438. const planar = toolGroup.getToolInstance(PlanarRotateTool.toolName); // Reset rotation angle
  439. const isActive = planar.mode === csToolsEnums.ToolModes.Active;
  440. console.log(
  441. `PlanarRotateTool is currently ${isActive ? 'active' : 'inactive'}`
  442. );
  443. if (isActive) {
  444. toolGroup.setToolPassive(PlanarRotateTool.toolName, {
  445. removeAllBindings: true,
  446. });
  447. } else {
  448. toolGroup.setToolActive(PlanarRotateTool.toolName, {
  449. bindings: [
  450. {
  451. mouseButton: MouseBindings.Primary, // Left Click
  452. },
  453. ],
  454. });
  455. }
  456. console.log('Rotating Image by Any Angle');
  457. }
  458. break;
  459. case 'Crop Image':
  460. // Implement the logic to crop the image
  461. console.log('Cropping Image');
  462. break;
  463. case 'Delete Digital Mask':
  464. // Implement the logic to delete the digital mask
  465. console.log('Deleting Digital Mask');
  466. break;
  467. case 'Adjust Brightness and Contrast':
  468. adjustBrightnessAndContrast();
  469. break;
  470. case 'Crop Selected Area':
  471. // Implement the logic to crop the selected area
  472. console.log('Cropping Selected Area');
  473. break;
  474. case 'Delete Mask':
  475. // Implement the logic to delete the mask
  476. console.log('Deleting Mask');
  477. break;
  478. case 'Image Comparison':
  479. // Implement the logic for image comparison
  480. console.log('Comparing Images');
  481. break;
  482. case 'Invert Contrast':
  483. // Implement the logic to invert the contrast
  484. {
  485. const viewport =
  486. cornerstone.getEnabledElementByViewportId(
  487. currentViewportId
  488. ).viewport;
  489. const targetBool = !viewport.getProperties().invert;
  490. viewport.setProperties({
  491. invert: targetBool,
  492. });
  493. viewport.render();
  494. }
  495. console.log('Inverting Contrast');
  496. break;
  497. case '1x1 Layout':
  498. // Implement the logic for 1x1 layout
  499. console.log('Setting 1x1 Layout');
  500. break;
  501. case '1x2 Layout':
  502. // Implement the logic for 1x2 layout
  503. console.log('Setting 1x2 Layout');
  504. break;
  505. case '2x2 Layout':
  506. // Implement the logic for 2x2 layout
  507. console.log('Setting 2x2 Layout');
  508. break;
  509. case '4x4 Layout':
  510. // Implement the logic for 4x4 layout
  511. console.log('Setting 4x4 Layout');
  512. break;
  513. case 'Magnifier': {
  514. // Implement the logic for magnifier
  515. console.log('Activating Magnifier');
  516. const isActive =
  517. toolGroup.getActivePrimaryMouseButtonTool() ===
  518. MagnifyTool.toolName;
  519. if (isActive) {
  520. toolGroup.setToolPassive(MagnifyTool.toolName, {
  521. removeAllBindings: true,
  522. });
  523. } else {
  524. toolGroup.setToolActive(MagnifyTool.toolName, {
  525. bindings: [
  526. {
  527. mouseButton: MouseBindings.Primary, // Left Click
  528. },
  529. ],
  530. });
  531. }
  532. break;
  533. }
  534. case 'Fit Size': {
  535. // Implement the logic to fit the image size
  536. fitImageSize();
  537. console.log('Fitting Image Size');
  538. break;
  539. }
  540. case 'Original Size': {
  541. // Implement the logic to set the image to original size
  542. console.log('Setting Image to Original Size');
  543. setOriginalSize(
  544. cornerstone.getEnabledElementByViewportId(currentViewportId)
  545. .viewport as cornerstone.StackViewport
  546. );
  547. break;
  548. }
  549. case 'Zoom Image':
  550. // Implement the logic to zoom the image
  551. console.log('Zooming Image');
  552. break;
  553. case 'Reset Cursor':
  554. // Implement the logic to reset the cursor
  555. console.log('Resetting Cursor');
  556. break;
  557. case 'Pan':
  558. // Implement the logic to pan the image
  559. console.log('Panning Image');
  560. break;
  561. case 'Invert Image':
  562. InvertImage();
  563. break;
  564. case 'Reset Image':
  565. ResetImage();
  566. break;
  567. case 'Snapshot':
  568. // Implement the logic to take a snapshot
  569. console.log('Taking Snapshot');
  570. break;
  571. case 'Advanced Processing':
  572. // Implement the logic for advanced processing
  573. console.log('Performing Advanced Processing');
  574. break;
  575. case 'Musician':
  576. // Implement the logic for musician
  577. console.log('Activating Musician');
  578. break;
  579. case 'Image Measurement':
  580. // Implement the logic for image measurement
  581. console.log('Measuring Image');
  582. break;
  583. case 'More':
  584. // Implement the logic for more options
  585. console.log('Showing More Options');
  586. break;
  587. case 'Apply Colormap':
  588. ApplyColormap();
  589. break;
  590. default:
  591. break;
  592. }
  593. dispatch(clearAction()); //清理后可连续同一个action触发响应
  594. }
  595. }, [action]);
  596. return (
  597. <div
  598. ref={elementRef}
  599. style={{ width: '100%', height: '100%', backgroundColor: '#000' }}
  600. />
  601. );
  602. };
  603. export default StackViewer;