Skip to content

Commit 5394448

Browse files
authored
Merge pull request #10 from dcmjs-org/event-strategy
Event strategy
2 parents 8059ee1 + 061b483 commit 5394448

File tree

12 files changed

+817
-202
lines changed

12 files changed

+817
-202
lines changed

examples/basic/index.html

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6+
<meta name="theme-color" content="#000000">
7+
8+
<title>dicom-microscopy-viewer example</title>
9+
10+
<!-- Latest compiled and minified CSS -->
11+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
12+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
13+
</head>
14+
15+
<body>
16+
<noscript>
17+
You need to enable JavaScript to run this app.
18+
</noscript>
19+
20+
<script src="https://unpkg.com/dicomweb-client"></script>
21+
<script src="https://unpkg.com/dicom-microscopy-viewer"></script>
22+
<script>
23+
const url = 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs';
24+
const client = new DICOMwebClient.api.DICOMwebClient({url});
25+
const studyInstanceUID = '1.2.392.200140.2.1.1.1.2.799008771.2448.1519719572.518';
26+
const seriesInstanceUID = '1.2.392.200140.2.1.1.1.3.799008771.2448.1519719572.519';
27+
const searchInstanceOptions = {
28+
studyInstanceUID,
29+
seriesInstanceUID
30+
};
31+
client.searchForInstances(searchInstanceOptions).then((instances) => {
32+
const promises = []
33+
for (let i = 0; i < instances.length; i++) {
34+
const sopInstanceUID = instances[i]["00080018"]["Value"][0];
35+
const retrieveInstanceOptions = {
36+
studyInstanceUID,
37+
seriesInstanceUID,
38+
sopInstanceUID,
39+
};
40+
const promise = client.retrieveInstanceMetadata(retrieveInstanceOptions).then(metadata => {
41+
const imageType = metadata[0]["00080008"]["Value"];
42+
if (imageType[2] === "VOLUME") {
43+
return(metadata[0]);
44+
}
45+
});
46+
promises.push(promise);
47+
}
48+
return(Promise.all(promises));
49+
}).then(metadata => {
50+
metadata = metadata.filter(m => m);
51+
const viewer = new DICOMMicroscopyViewer.api.VLWholeSlideMicroscopyImageViewer({
52+
client,
53+
metadata
54+
});
55+
56+
var container = document.getElementById('root');
57+
viewer.render({container});
58+
});
59+
</script>
60+
61+
<div><h1>DICOM Microscopy Viewer Example</h1></div>
62+
<div id="root"></div>
63+
</body>
64+
</html>

examples/events/index.html

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta
6+
name="viewport"
7+
content="width=device-width, initial-scale=1, shrink-to-fit=no"
8+
/>
9+
<meta name="theme-color" content="#000000" />
10+
11+
<title>dicom-microscopy-viewer example</title>
12+
13+
<!-- Latest compiled and minified CSS -->
14+
<link
15+
rel="stylesheet"
16+
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
17+
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
18+
crossorigin="anonymous"
19+
/>
20+
<link
21+
rel="stylesheet"
22+
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
23+
integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0="
24+
crossorigin="anonymous"
25+
/>
26+
</head>
27+
28+
<body>
29+
<noscript>
30+
You need to enable JavaScript to run this app.
31+
</noscript>
32+
33+
<script src="https://unpkg.com/dicomweb-client"></script>
34+
<script src="https://unpkg.com/dicom-microscopy-viewer"></script>
35+
<!-- <script src="../../build/dicom-microscopy-viewer.js"></script> -->
36+
<script>
37+
38+
const CORE_ACTIONS = {
39+
ACTIVATE_DRAW : "activate_draw",
40+
DEACTIVATE_DRAW : "deactivate_draw",
41+
ACTIVATE_SELECTION : "activate_selection",
42+
ACTIVATE_MODIFICATIONS : "activate_modifications"
43+
};
44+
45+
document.addEventListener("DOMContentLoaded", () => {
46+
47+
document.getElementById("tools-list").addEventListener("click", (event) => {
48+
const geometryType = event.target.id;
49+
disableToolList();
50+
window.viewer.activateDrawInteraction({ geometryType });
51+
document.getElementById(`${geometryType}`).parentNode.setAttribute("class", "active");
52+
disableCoreActions();
53+
toggleElement("activate_draw", true);
54+
});
55+
56+
// Event list
57+
document.getElementById("event-list").addEventListener("click", (event) => {
58+
const eventType = event.target.id;
59+
60+
if(document.getElementById(eventType).classList.contains("active")){
61+
document.removeEventListener(`dicommicroscopyviewer_${eventType}`, logEvent);
62+
}else{
63+
addEventListener(eventType);
64+
}
65+
document.getElementById(eventType).classList.toggle("active");
66+
});
67+
68+
Object.keys(CORE_ACTIONS).forEach(action =>
69+
document.getElementById(CORE_ACTIONS[action]).addEventListener("click", toggleCoreAction, false)
70+
);
71+
72+
const rois = document.getElementById('rois');
73+
74+
rois.addEventListener("click", (e) => {
75+
const li = e.target.closest('li');
76+
let nodes = Array.from(rois.children);
77+
nodes = Array.from(li.closest('ul').children);
78+
const index = nodes.indexOf(li);
79+
viewer.removeROI(index);
80+
// if there is a selection when deleting the structure, the selection keeps there
81+
if(viewer.isSelectInteractionActive){
82+
viewer.deactivateSelectInteraction();
83+
viewer.deactivateDrawInteraction();
84+
disableCoreActions();
85+
toggleElement("deactivate_draw", true);
86+
}
87+
rois.removeChild(rois.children[index]);
88+
}, false)
89+
90+
});
91+
92+
function disableCoreActions(){
93+
const elements = document.getElementById("core-actions").querySelector("a.active");
94+
if(elements !== null){
95+
elements.classList.remove("active");
96+
}
97+
}
98+
99+
function toggleElement(element, state){
100+
if(state){
101+
document.getElementById(element).classList.add("active");
102+
}else{
103+
document.getElementById(element).classList.remove("active");
104+
}
105+
}
106+
107+
function toggleCoreAction(event){
108+
const targetId = event.target.id;
109+
disableCoreActions();
110+
111+
window.viewer.deactivateDrawInteraction();
112+
window.viewer.deactivateSelectInteraction();
113+
window.viewer.deactivateModifyInteraction();
114+
115+
switch (targetId){
116+
case CORE_ACTIONS.ACTIVATE_SELECTION:
117+
if(!window.viewer.isSelectInteractionActive){
118+
disableToolList();
119+
window.viewer.deactivateDrawInteraction();
120+
window.viewer.activateSelectInteraction();
121+
}
122+
break;
123+
case CORE_ACTIONS.ACTIVATE_MODIFICATIONS:
124+
if(!window.viewer.isModifyInteractionActive){
125+
disableToolList();
126+
window.viewer.deactivateDrawInteraction();
127+
window.viewer.activateModifyInteraction();
128+
}
129+
break;
130+
case CORE_ACTIONS.DEACTIVATE_DRAW:
131+
disableToolList();
132+
break;
133+
case CORE_ACTIONS.ACTIVATE_DRAW:
134+
viewer.activateDrawInteraction({ geometryType: "polygon" });
135+
document.getElementById("polygon").parentNode.setAttribute("class", "active");
136+
break;
137+
}
138+
toggleElement(targetId, true);
139+
}
140+
141+
function addEventListener(eventType){
142+
document.addEventListener(`dicommicroscopyviewer_${eventType}`, logEvent);
143+
}
144+
145+
function disableToolList(){
146+
const toolList = document.getElementById("tools-list").querySelector("li.active")
147+
if(toolList !== null){
148+
toolList.classList.remove("active");
149+
}
150+
}
151+
152+
function logEvent(event) {
153+
console.log(event)
154+
const eventType = event.type.split("dicommicroscopyviewer_")[1];
155+
const content = event.detail;
156+
const activeElements = document.getElementById("log").querySelector("a.active");
157+
if(activeElements){
158+
activeElements.classList.remove("active");
159+
}
160+
const new_event = `<a class="list-group-item active">
161+
<h4 class="list-group-item-heading">${eventType}</h4>
162+
<p class="list-group-item-text">${new Date(content.time).toLocaleTimeString()}</p>
163+
</a>`;
164+
165+
const log = document.getElementById("log");
166+
167+
let newNode = document.createElement("div");
168+
newNode.innerHTML = new_event.trim();
169+
log.prepend(newNode);
170+
171+
if(eventType === 'roi_added'){
172+
const rois = document.getElementById("rois");
173+
const json = JSON.stringify(content.payload.scoord3d, undefined, 2).replace(/"/g, "");
174+
const newROI = `<div class="list-group-item" title="${json}">
175+
<h4 class="list-group-item-heading">${Object.keys(content.payload.properties)[0]}</h4>
176+
<p class="list-group-item-text">${new Date(content.time).toLocaleTimeString()}</p>
177+
</div>`;
178+
let newROIDivElement = document.createElement("li");
179+
newROIDivElement.innerHTML = newROI.trim();
180+
rois.append(newROIDivElement);
181+
}
182+
}
183+
184+
const url = "https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs";
185+
const client = new DICOMwebClient.api.DICOMwebClient({ url });
186+
const studyInstanceUID = "1.2.392.200140.2.1.1.1.2.799008771.2448.1519719572.518";
187+
const seriesInstanceUID = "1.2.392.200140.2.1.1.1.3.799008771.2448.1519719572.519";
188+
189+
const searchInstanceOptions = {
190+
studyInstanceUID,
191+
seriesInstanceUID
192+
};
193+
194+
client.searchForInstances(searchInstanceOptions)
195+
.then(instances => {
196+
const promises = [];
197+
198+
for (let i = 0; i < instances.length; i++) {
199+
200+
const sopInstanceUID = instances[i]["00080018"]["Value"][0];
201+
202+
const retrieveInstanceOptions = {
203+
studyInstanceUID,
204+
seriesInstanceUID,
205+
sopInstanceUID
206+
};
207+
208+
const promise = client.retrieveInstanceMetadata(retrieveInstanceOptions)
209+
.then(metadata => {
210+
const imageType = metadata[0]["00080008"]["Value"];
211+
if (imageType[2] === "VOLUME") {
212+
return metadata[0];
213+
}
214+
});
215+
promises.push(promise);
216+
}
217+
return Promise.all(promises);
218+
})
219+
.then(metadata => {
220+
metadata = metadata.filter(m => m);
221+
const viewer = new DICOMMicroscopyViewer.api.VLWholeSlideMicroscopyImageViewer({client,metadata});
222+
223+
const container = document.getElementById("dicomImage");
224+
viewer.render({ container });
225+
226+
viewer.activateDrawInteraction({ geometryType: "polygon" });
227+
window.viewer = viewer;
228+
229+
});
230+
231+
addEventListener("move_started");
232+
addEventListener("move_ended");
233+
addEventListener("roi_added");
234+
235+
</script>
236+
</body>
237+
<body>
238+
<div class="container">
239+
<div class="page-header">
240+
<h1>
241+
Microscopy viewer Events Handler
242+
</h1>
243+
<p>
244+
This example demonstrates how to interact with Microscopy Events.
245+
</p>
246+
<a href="../">Go back to the Examples page</a>
247+
</div>
248+
249+
<div class="bs-example" data-example-id="simple-thumbnails">
250+
<div class="row">
251+
<div class="col-xs-6 col-md-2">
252+
<div class="alert alert-warning text-center" role="alert">Attach/Detach event listeners</div>
253+
<div class="list-group" id="event-list">
254+
<a id="roi_added" class="list-group-item active">ROI Added</a>
255+
<a id="roi_removed" class="list-group-item">ROI Removed</a>
256+
<a id="roi_drawn" class="list-group-item">ROI Drawn</a>
257+
<a id="roi_selected" class="list-group-item">ROI Selected</a>
258+
<a id="roi_modified" class="list-group-item">ROI Modified</a>
259+
<a id="move_started" class="list-group-item active">Move Started</a>
260+
<a id="move_ended" class="list-group-item active">Move Ended</a>
261+
</div>
262+
<div class="alert alert-warning text-center" role="alert">Core actions</div>
263+
<div class="list-group" id="core-actions">
264+
<a id="activate_draw" class="list-group-item active">Activate Draw</a>
265+
<a id="deactivate_draw" class="list-group-item">Deactivate Draw</a>
266+
<a id="activate_selection" class="list-group-item">Activation ROI Selection</a>
267+
<a id="activate_modifications" class="list-group-item">Activate ROI Modification</a>
268+
</div>
269+
</div>
270+
<div class="col-xs-6 col-md-7" >
271+
<div class="alert alert-warning text-center" role="alert">Select below the tool you want to use to draw</div>
272+
<ul class="nav nav-pills" id="tools-list">
273+
<li role="presentation" class="active"><a id="polygon">Polygon</a></li>
274+
<li role="presentation"><a id="point">Point</a></li>
275+
<li role="presentation"><a id="circle">Circle</a></li>
276+
<li role="presentation"><a id="box">Box</a></li>
277+
<li role="presentation"><a id="freehandpolygon">Freehand Polygon</a></li>
278+
<li role="presentation"><a id="line">Line</a></li>
279+
<li role="presentation"><a id="freehandline">Freehand Line</a></li>
280+
</ul>
281+
<br/>
282+
<div
283+
style="width:100%;height:550px;position:relative;display:inline-block;"
284+
oncontextmenu="return false"
285+
class="cornerstone-enabled-image"
286+
unselectable="on"
287+
onselectstart="return false;"
288+
onmousedown="return false;"
289+
>
290+
<div
291+
id="dicomImage"
292+
style="width:100%;height:550px;top:0px;left:0px; position:absolute; border: 1px solid black;"
293+
></div>
294+
295+
</div>
296+
<div class="alert alert-warning text-center" role="alert">ROIs added (mouseover to see the coordinates or click to remove)</div>
297+
<ul class="list-group" id="rois">
298+
</ul>
299+
</div>
300+
<div class="col-xs-6 col-md-3">
301+
<div class="alert alert-warning text-center" role="alert">Event Log</div>
302+
<div class="list-group scrollable" id="log"></div>
303+
</div>
304+
</div>
305+
</div>
306+
</div>
307+
<style>
308+
.scrollable {
309+
height: 600px;
310+
overflow-y: scroll;
311+
}
312+
#rois li {
313+
list-style-type: none;
314+
}
315+
</style>
316+
</body>
317+
</html>

0 commit comments

Comments
 (0)