Multiple Image Annotation
basicviewportannotations
Console
Multiple images parallel annotation
multiple_image_annotation.html
1<!doctype >
2<html lang="en">
3
4<head>
5 <meta charset="utf-8">
6 <meta http-equiv="X-UA-Compatible" content="IE=10">
7 <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
8
9 <!-- Include PMA.UI required libraries downloaded or from CDN -->
10 <script src="./pma.ui/jquery-3.1.0.js"></script>
11 <link href="./pma.ui/font-awesome.min.css" type="text/css" rel="stylesheet">
12 <script src="https://code.jquery.com/jquery-3.1.0.js" integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" crossorigin="anonymous">
13 </script>
14
15 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
16 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css" integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous">
17 <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
18
19 <!-- Include PMA.UI script & css -->
20 <script src="./pma.ui/pma.ui.js"></script>
21 <link href="./pma.ui/pma.ui.css" type="text/css" rel="stylesheet">
22
23 <!-- Include custom script & css -->
24 <script src="./js/multiple_image_annotation.js"></script>
25 <link href="./css/multiple_image_annotation.css" type="text/css" rel="stylesheet">
26
27 <title>Multiple Image Annotation</title>
28</head>
29
30<body>
31 <div id="annotations" class="slide">
32 <div class="btn-group btn-group-sm">
33 <button type="button" class="btn btn-default" data-action="draw" data-type="Freehand" title="Freehand">
34 <i class="fa fa-pencil"></i>
35 </button>
36 <button type="button" class="btn btn-default" data-action="draw" data-type="ClosedFreehand" title="Closed freehand">
37 <i class="fa fa-pencil-square"></i>
38 </button>
39 </div>
40 <div class="btn-group btn-group-sm" data-toggle="buttons">
41 <button type="button" class="btn btn-primary" data-action="deleteall" data-type title="Delete all">
42 <i class="fa fa-times-circle"></i>
43 </button>
44 <button type="button" class="btn btn-primary" data-action="save" data-type title="Save">
45 <i class="fa fa-save"></i>
46 </button>
47 </div>
48 <span class="annotation-helper-icon">
49 <i class="fa fa-spinner fa-spin"></i>
50 <span class="label label-success">
51 <i class="fa fa-check"></i> Saved</span>
52 <span class="label label-danger">
53 <i class="fa fa-times"></i> Error</span>
54 </span>
55 </div>
56 <div class="container">
57 <div id="viewer1" tabindex="0" class="column">
58 </div>
59 <div id="viewer2" tabindex="0" class="column">
60 </div>
61 </div>
62 <div class="container-menu">
63 <div id="viewer1Content" class="viewer-content">
64 <form class="dropdown">
65 <select id="pathsViewer1">
66 <option value="cases2/fuhrmann/Assessment set/07250086C0001S.mrxs">07250086C0001S.mrxs</option>
67 <option value="cases2/fuhrmann/Assessment set/07250133C0001S.mrxs">07250133C0001S.mrxs</option>
68 <option value="cases2/fuhrmann/Assessment set/07250166C0001S.mrxs">07250166C0001S.mrxs</option>
69 </select>
70 </form>
71 </div>
72 <div id="viewer2Content" class="viewer-content">
73 <form class="dropdown">
74 <select id="pathsViewer2">
75 <option value="cases2/fuhrmann/Assessment set/07250169C0001S.mrxs">07250169C0001S.mrxs</option>
76 <option value="cases2/fuhrmann/Assessment set/07250174C0001S.mrxs">07250174C0001S.mrxs</option>
77 <option value="cases2/fuhrmann/Assessment set/07250189C0001S.mrxs">07250189C0001S.mrxs</option>
78 </select>
79 </form>
80 </div>
81 </div>
82</body>
multiple_image_annotation.css
1html,
2body {
3 height: 100%;
4 overflow: hidden;
5 display: flex;
6 flex-direction: column;
7}
8
9#annotations {
10 padding: 10px 0 0 0;
11 text-align: center;
12}
13
14.container {
15 flex-grow: 1;
16 display: flex;
17 height: 100%;
18 width: 100%;
19}
20
21.container-menu {
22 flex-grow: 1;
23 display: flex;
24 width: 100%;
25}
26
27.column {
28 flex-grow: 1;
29 background-color: lightgray;
30 border: 1px gray solid;
31 border-radius: 5px;
32 margin: 10px 10px 0 10px;
33 display: flex;
34 flex-direction: column;
35 align-items: center;
36}
37
38.viewer-content {
39 flex-grow: 1;
40 width: 100%;
41}
42
43.dropdown {
44 width: 100%;
45 display: flex;
46 justify-content: center;
47 padding: 10px;
48}
49
50select {
51 width: 30%;
52 height: auto;
53}
54
55.annotation-helper-icon i,
56.annotation-helper-icon span {
57 display: none;
58}
59
60.annotation-helper-icon.loading i {
61 display: initial;
62}
63
64.annotation-helper-icon.loading span {
65 display: none;
66}
67
68.annotation-helper-icon.saved i,
69.annotation-helper-icon.saved span.label-danger {
70 display: none;
71}
72
73.annotation-helper-icon.saved span.label-success {
74 display: initial;
75}
76
77.annotation-helper-icon.error i,
78.annotation-helper-icon.error span.label-success {
79 display: none;
80}
multiple_image_annotation.js
1var serverUrl = "https://host.pathomation.com/pma.core.3/";
2var username = "zuidemo";
3var password = "zuidemo";
4var slideLoader1, slideLoader2;
5var annotationManager1, annotationManager2;
6
7function loadImage(slideLoader, imagePath) {
8 slideLoader.load(serverUrl, imagePath);
9}
10
11function initAnnotationToolbar() {
12 $("button[data-action][data-type], a[data-action][data-type]").on("click", function (e) {
13 const action = $(this).data("action");
14 const type = $(this).data("type");
15 if (annotationManager1) {
16 annotationManager1.finishDrawing(false);
17 annotationManager1.stopTool();
18 if (action === 'draw') {
19 annotationManager1.startDrawing({
20 type: type,
21 color: "#00ff00",
22 lineThickness: 2,
23 });
24 }
25 else if (action === "deleteall") {
26 var allAnnotations = slideLoader1.mainViewport.getAnnotations();
27
28 for (var i = 0; i < allAnnotations.length; i++) {
29 annotationManager1.deleteAnnotation(allAnnotations[i].getId());
30 }
31 }
32 else if (action === "save") {
33 $(".annotation-helper-icon").addClass("loading");
34 annotationManager1.saveAnnotations();
35 annotationManager1.listen(PMA.UI.Components.Events.AnnotationsSaved, function (e) {
36 if (e && e.success) {
37 $(".annotation-helper-icon").removeClass("loading").addClass("saved");
38 } else {
39 $(".annotation-helper-icon").removeClass("loading").addClass("error");
40 }
41
42 $("button[data-action=save][data-type]").removeClass("active");
43
44 setTimeout(function () {
45 $(".annotation-helper-icon").removeClass("loading error saved");
46 }, 1000);
47 });
48 }
49 }
50
51 if (annotationManager2) {
52 annotationManager2.finishDrawing(false);
53 annotationManager2.stopTool();
54 if (action === 'draw') {
55 annotationManager2.startDrawing({
56 type: type,
57 color: "#00ff00",
58 lineThickness: 2,
59 });
60 }
61 else if (action === "deleteall") {
62 var allAnnotations = slideLoader2.mainViewport.getAnnotations();
63
64 for (var i = 0; i < allAnnotations.length; i++) {
65 annotationManager2.deleteAnnotation(allAnnotations[i].getId());
66 }
67 }
68 else if (action === "save") {
69 annotationManager2.saveAnnotations();
70 annotationManager2.listen(PMA.UI.Components.Events.AnnotationsSaved, function (e) {
71 if (e && e.success) {
72 $(".annotation-helper-icon").removeClass("loading").addClass("saved");
73 } else {
74 $(".annotation-helper-icon").removeClass("loading").addClass("error");
75 }
76
77 $("button[data-action=save][data-type]").removeClass("active");
78
79 setTimeout(function () {
80 $(".annotation-helper-icon").removeClass("loading error saved");
81 }, 1000);
82 });
83 }
84 }
85 });
86}
87
88$(document).ready(function () {
89 var context = new PMA.UI.Components.Context({
90 caller: "public demo",
91 });
92
93 new PMA.UI.Authentication.AutoLogin(context, [
94 { serverUrl: serverUrl, username: username, password: password },
95 ]);
96
97 var options1 = {
98 element: "#viewer1",
99 annotations: true,
100 };
101
102 slideLoader1 = new PMA.UI.Components.SlideLoader(context, options1);
103 slideLoader1.listen(
104 PMA.UI.Components.Events.SlideLoaded,
105 function (args) {
106 annotationManager1 = new PMA.UI.Components.Annotations({
107 context: context,
108 element: null,
109 viewport: slideLoader1.mainViewport,
110 serverUrl: args.serverUrl,
111 path: args.path,
112 enabled: true,
113 });
114 });
115
116 $("#pathsViewer1").change(function () {
117 loadImage(slideLoader1, $(this).val());
118 });
119
120 loadImage(slideLoader1, $("#pathsViewer1").val());
121
122 var options2 = {
123 element: "#viewer2",
124 annotations: true,
125 };
126
127 slideLoader2 = new PMA.UI.Components.SlideLoader(context, options2);
128 slideLoader2.listen(
129 PMA.UI.Components.Events.SlideLoaded,
130 function (args) {
131 annotationManager2 = new PMA.UI.Components.Annotations({
132 context: context,
133 element: null,
134 viewport: slideLoader2.mainViewport,
135 serverUrl: args.serverUrl,
136 path: args.path,
137 enabled: true,
138 });
139 });
140
141 $("#pathsViewer2").change(function () {
142 loadImage(slideLoader2, $(this).val());
143 });
144
145 loadImage(slideLoader2, $("#pathsViewer2").val());
146 initAnnotationToolbar();
147});