File size: 8,814 Bytes
68d68c5
 
 
 
071e902
 
68d68c5
 
 
 
 
 
 
 
bab49c3
 
 
 
 
 
 
 
 
 
68d68c5
 
d223af2
68d68c5
071e902
68d68c5
071e902
68d68c5
071e902
 
 
 
 
68d68c5
 
 
 
 
7d341ff
7ad4738
 
 
 
 
68d68c5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
071e902
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bca8e40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7ad4738
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68d68c5
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
<html>
    <head>
        <title>Whole Slide Image Annotation</title>
        
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

        <link rel="stylesheet" href="node_modules/@recogito/annotorious/dist/annotorious.min.css">
        <link rel="stylesheet" href="node_modules/@recogito/annotorious-selector-pack/dist/annotorious-selector-pack.min.css">
        
        <!-- Dependencies -->
        <script src="node_modules/openseadragon/build/openseadragon/openseadragon.min.js"></script>
        <script src="node_modules/@recogito/annotorious-openseadragon/dist/openseadragon-annotorious.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/@recogito/[email protected]/dist/annotorious-toolbar.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/@recogito/[email protected]/dist/annotorious-selector-pack.min.js"></script>

        <style>
            /** New style for the annotation outlines **/
            svg.a9s-annotationlayer .a9s-selection .a9s-inner,
            svg.a9s-annotationlayer .a9s-annotation .a9s-inner  {
                stroke-width:4;
                stroke:blue;
                fill: rgba(0, 0, 255, 0.4);
            }
        </style>
    </head>
    <body>
        <div style="padding: 0 0em; height: 100%; background: #303030">
            <div class="sidebar-left" style="float: left; width: 10%;">
                <h1 style="color: white; font-size: 16px; padding: 0 1.5em;">Whole Slide Image Annotation Demo</h1>

                <hr style="border: 2px solid white;">

                <div id="annotations-container">
                    <h2 style="color: white; padding: 0 0.5em; font-size: 14px;">Annotations</h2>
                    <hr style="border: 0.25px solid white;">
                    <div id="annotations-list"></div>
                </div>
            </div>
            <div id="wsi-canvas" style="float: left; width: 80%; height: 100%; background: white;"></div>
            <div id="annotation-toolbar"></div>

            <div class="sidebar-right" style="float: right; width: 10%;">
                <h2 style="color: white; padding: 0 0.5em; font-size: 14px;">View tracking information</h2>
                <hr style="border: 0.25px solid white;">

                <div class="position" style="color: white; padding: 0 0.5em; font-size: 14px;"></div>
                <hr style="border: 0.25px solid white;">
                <div class="zoom" style="color: white; padding: 0 0.5em; font-size: 14px;"></div>
            </div>
            
            <div id="annotation_list" style="display: none;"></div>
        </div>
        <link rel="stylesheet" href="annotorious.min.css">
        <script type="text/javascript">
            var viewer = OpenSeadragon({
                id: "wsi-canvas",
                prefixUrl: "node_modules/openseadragon/build/openseadragon/images/",
                zoomPerScroll: 2,
                zoomPerClick: 1,
                showNavigator:  true,
                showHomeControl: false,
                showFullPageControl: false,
                showZoomControl: false,
                minZoomLevel: 0.25,
                maxZoomLevel: 40,
                tileSources: {
                    Image: {
                        xmlns: "http://schemas.microsoft.com/deepzoom/2008",
                        Url: "A05_files/",
                        Format: "jpeg",
                        Overlap: "0",
                        TileSize: "256",
                        Size: {
                            Height: 42625,
                            Width: 51553
                        }
                    },
                    overlays: [],
                },
            });
            viewer.innerTracker.keyHandler = null;

            var anno = OpenSeadragon.Annotorious(viewer);
            Annotorious.SelectorPack(anno);

            const toolbar = new Annotorious.Toolbar(anno, document.getElementById('annotation-toolbar'));
            viewer.addControl(document.getElementById("annotation-toolbar"), {anchor: OpenSeadragon.ControlAnchor.TOP_LEFT});

            document.getElementById('annotation-toolbar').addEventListener('click', function(event) {
                event.preventDefault();
            });

            // Listen for annotation creation event
            anno.on('createAnnotation', function(annotation) {
                // Create a new div element for the annotation
                var annotationItem = document.createElement('div');
                annotationItem.className = 'annotation-item';
                annotationItem.style.color = 'white';
                annotationItem.style.padding = '10px';
                annotationItem.style.border = '1px solid white';
                annotationItem.style.marginTop = '10px';
                annotationItem.style.cursor = 'pointer';
                annotationItem.style.fontSize = '12px'; // Set font size in pixels
                annotationItem.dataset.annotationId = annotation.id;

                // Add annotation details to the item
                annotationItem.innerHTML = `
                    ${annotation.body[0].value}
                `;

                // Add click event to make the annotation active
                annotationItem.addEventListener('click', function() {
                    anno.selectAnnotation(annotation.id);
                });

                // Append the annotation item to the annotations list in the sidebar
                document.getElementById('annotations-list').appendChild(annotationItem);
            });

            // Listen for annotation deletion event
            anno.on('deleteAnnotation', function(annotation) {
                // Find the corresponding annotation item in the sidebar
                var annotationItems = document.querySelectorAll('.annotation-item');
                annotationItems.forEach(function(item) {
                    if (item.dataset.annotationId === annotation.id) {
                        item.remove();
                    }
                });
            });

            // Disable panning when polygon tool is active
            anno.on('startSelection', function(event) {
                if (event.tool === 'polygon') {
                    viewer.setMouseNavEnabled(false);
                }
            });

            // Re-enable panning when polygon tool is deactivated
            anno.on('cancelSelection', function(event) {
                if (event.tool === 'polygon') {
                    viewer.setMouseNavEnabled(true);
                }
            });

            anno.on('createAnnotation', function(event) {
                if (event.tool === 'polygon') {
                    viewer.setMouseNavEnabled(true);
                }
            });
            
            // Add a listener to the viewer to update the position and zoom info
            var positionEl = document.querySelectorAll('.sidebar-right .position')[0];
            var zoomEl = document.querySelectorAll('.sidebar-right .zoom')[0];
            
            // Default values
            positionEl.innerHTML = 'Web:<br> (NA) <br><br>Viewport:<br> (NA) <br><br>Image:<br> (NA)';
            zoomEl.innerHTML = 'Zoom:<br> NA <br><br>Image Zoom:<br> NA';

            var updateZoom = function() {
                var zoom = viewer.viewport.getZoom(true);
                var imageZoom = viewer.viewport.viewportToImageZoom(zoom);

                zoomEl.innerHTML = 'Zoom:<br>' + (Math.round(zoom * 100) / 100) + 
                    '<br><br>Image Zoom:<br>' + (Math.round(imageZoom * 100) / 100);
            }

            viewer.addHandler('open', function() {
                var tracker = new OpenSeadragon.MouseTracker({
                    element: viewer.container,
                    moveHandler: function(event) {
                        var webPoint = event.position;
                        var viewportPoint = viewer.viewport.pointFromPixel(webPoint);
                        var imagePoint = viewer.viewport.viewportToImageCoordinates(viewportPoint);
                        var zoom = viewer.viewport.getZoom(true);
                        var imageZoom = viewer.viewport.viewportToImageZoom(zoom);

                        positionEl.innerHTML = 'Web:<br>' + webPoint.toString() + 
                            '<br><br>Viewport:<br>' + viewportPoint.toString() +
                            '<br><br>Image:<br>' + imagePoint.toString();
                        
                        updateZoom();     
                    }
                });
                tracker.setTracking(true);  
                viewer.addHandler('animation', updateZoom);   
            });
        </script>
    </body>
</html>