Skip to content

Commit 23d41fc

Browse files
authored
Viewport (#10)
Adding the ability to use hotkeys with: ``` Default Tool Zoom Pan Angle measurement Scroll stack Length measurement Flip Horizontally Flip Vertically Rotate Right Rotate Left Invert Zoom In Zoom Out Zoom to Fit Reset Clear Tools Scroll Down Scroll Up ```
1 parent d5cc324 commit 23d41fc

File tree

2 files changed

+116
-4
lines changed

2 files changed

+116
-4
lines changed

example/src/App.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ export default class App extends Component {
1616
}
1717
}
1818

19+
const viewport = {
20+
invert: true,
21+
voi: {}
22+
};
23+
1924
const style = {
2025
'height': '512px'
2126
};
@@ -34,8 +39,9 @@ export default class App extends Component {
3439
<div className='col-xs-12 col-lg-6' style={style}>
3540
<CornerstoneViewport
3641
viewportData={exampleData}
37-
cornerstone={cornerstone}
42+
cornerstone={cornerstone}
3843
cornerstoneTools={cornerstoneTools}
44+
viewport={viewport}
3945
/>
4046
</div>
4147
</div>

src/CornerstoneViewport/CornerstoneViewport.js

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class CornerstoneViewport extends Component {
5959
isPlaying: false,
6060
cineFrameRate: 24
6161
},
62+
viewport: null,
6263
availableTools: [
6364
{ name: 'Pan', mouseButtonMasks: [1, 4] },
6465
{
@@ -94,6 +95,7 @@ class CornerstoneViewport extends Component {
9495
onMeasurementsChanged: PropTypes.func,
9596
onElementEnabled: PropTypes.func,
9697
isActive: PropTypes.bool.isRequired,
98+
viewport: PropTypes.object,
9799
layout: PropTypes.object,
98100
children: PropTypes.node,
99101
onDoubleClick: PropTypes.func,
@@ -127,7 +129,8 @@ class CornerstoneViewport extends Component {
127129
isLoading: false,
128130
numImagesLoaded: 0,
129131
error: null,
130-
viewport: cornerstone.getDefaultViewport(null, undefined)
132+
viewport:
133+
props.viewport || cornerstone.getDefaultViewport(null, undefined)
131134
};
132135

133136
const { loadHandlerManager } = cornerstoneTools;
@@ -421,8 +424,16 @@ class CornerstoneViewport extends Component {
421424
return;
422425
}
423426

424-
// Set Soft Tissue preset for all images by default
425-
const viewport = cornerstone.getDefaultViewportForImage(element, image);
427+
const defaultViewport = cornerstone.getDefaultViewportForImage(
428+
element,
429+
image
430+
);
431+
432+
const viewport = Object.assign(
433+
{},
434+
defaultViewport,
435+
this.state.viewport
436+
);
426437

427438
// Display the first image
428439
cornerstone.displayImage(element, image, viewport);
@@ -713,6 +724,101 @@ class CornerstoneViewport extends Component {
713724
);
714725
}
715726
}
727+
728+
// TODO? Should we shallow equality check these?
729+
if (this.props.viewport !== prevProps.viewport) {
730+
// Update the internal representation of the viewport parameters
731+
let viewport = Object.assign(
732+
{},
733+
this.state.viewport,
734+
this.props.viewport
735+
);
736+
737+
// Handle reset and fitToWindow cases
738+
// If viewport.scale === null or voi === null, call getDefaultViewportForImage
739+
// and use these values prior to calling setViewport
740+
741+
const defaultViewport = cornerstone.getDefaultViewportForImage(
742+
this.element,
743+
cornerstone.getImage(this.element)
744+
);
745+
if (viewport.voi === null) {
746+
viewport.voi = defaultViewport.voi;
747+
}
748+
749+
if (viewport.zoomScale !== null) {
750+
const maximumScale = 10;
751+
const minimumScale = 0.05;
752+
753+
if (viewport.zoomScale === 0) {
754+
viewport.scale = defaultViewport.scale;
755+
} else if (viewport.zoomScale < 0) {
756+
viewport.scale = Math.max(
757+
viewport.scale + viewport.zoomScale,
758+
minimumScale
759+
);
760+
} else {
761+
viewport.scale = Math.min(
762+
viewport.scale + viewport.zoomScale,
763+
maximumScale
764+
);
765+
}
766+
}
767+
768+
if (viewport.resetViewport) {
769+
viewport = defaultViewport;
770+
}
771+
772+
if (viewport.clearTools) {
773+
const toolStateManager =
774+
cornerstoneTools.globalImageIdSpecificToolStateManager;
775+
toolStateManager.clear(this.element);
776+
cornerstone.updateImage(this.element);
777+
}
778+
779+
if (viewport.scrollUp) {
780+
let stack = this.state.stack;
781+
stack.currentImageIdIndex = Math.min(
782+
this.state.numImagesLoaded,
783+
++stack.currentImageIdIndex
784+
);
785+
786+
scrollToIndex(this.element, stack.currentImageIdIndex);
787+
this.setState({ stack });
788+
}
789+
790+
if (viewport.scrollDown) {
791+
let stack = this.state.stack;
792+
stack.currentImageIdIndex = Math.max(0, --stack.currentImageIdIndex);
793+
scrollToIndex(this.element, stack.currentImageIdIndex);
794+
this.setState({ stack });
795+
}
796+
797+
if (viewport.scrollFirstImage) {
798+
let stack = this.state.stack;
799+
stack.currentImageIdIndex = 0;
800+
scrollToIndex(this.element, stack.currentImageIdIndex);
801+
this.setState({ stack });
802+
}
803+
804+
if (viewport.scrollLastImage) {
805+
let stack = this.state.stack;
806+
const numImagesLoaded = this.state.stack.imageIds.length - 1;
807+
scrollToIndex(this.element, numImagesLoaded);
808+
this.setState({ stack });
809+
}
810+
811+
if (viewport.nextPanel) {
812+
const enabledElements = cornerstone.getEnabledElements();
813+
this.element = enabledElements;
814+
}
815+
816+
this.setState({
817+
viewport
818+
});
819+
820+
cornerstone.setViewport(this.element, viewport);
821+
}
716822
}
717823

718824
setActiveTool = activeTool => {

0 commit comments

Comments
 (0)