changeset 400:1df8095649df

added rotation button in the viewer
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 04 Nov 2025 19:06:41 +0100
parents 2beac4eb0722
children 1be37c2e96c2
files NEWS Resources/CMake/JavaScriptLibraries.cmake ViewerPlugin/viewer.html ViewerPlugin/viewer.js
diffstat 4 files changed, 89 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Tue Nov 04 18:25:39 2025 +0100
+++ b/NEWS	Tue Nov 04 19:06:41 2025 +0100
@@ -1,6 +1,7 @@
 Pending changes in the mainline
 ===============================
 
+* Added rotation button in the viewer
 * Upgraded to OpenLayers 10.6.1
 
 
--- a/Resources/CMake/JavaScriptLibraries.cmake	Tue Nov 04 18:25:39 2025 +0100
+++ b/Resources/CMake/JavaScriptLibraries.cmake	Tue Nov 04 19:06:41 2025 +0100
@@ -26,19 +26,33 @@
   "${BASE_URL}/WSI/openlayers-10.6.1-package.tar.gz"
   "openlayers-10.6.1-package")
 
+DownloadPackage(
+  "102a4386a022f26a3b604e3852fffba8"
+  "${BASE_URL}/bootstrap-5.3.3.zip"
+  "${CMAKE_CURRENT_BINARY_DIR}/bootstrap-5.3.3")
+
+# curl -L https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js | gzip > /tmp/popper-2.11.8.min.js.gz
+
+DownloadCompressedFile(
+  "309f660accb8025e06ca99feae3c1d7c"
+  "${BASE_URL}/WSI/popper-2.11.8.min.js.gz"
+  "${CMAKE_CURRENT_BINARY_DIR}/popper.min.js")
+
 
 set(JAVASCRIPT_LIBS_DIR  ${CMAKE_CURRENT_BINARY_DIR}/javascript-libs)
 file(MAKE_DIRECTORY ${JAVASCRIPT_LIBS_DIR})
 
 
 file(COPY
+  ${CMAKE_CURRENT_BINARY_DIR}/bootstrap-5.3.3/dist/js/bootstrap.min.js
   ${CMAKE_CURRENT_BINARY_DIR}/openlayers-10.6.1-package/dist/ol.js
-  ${CMAKE_CURRENT_BINARY_DIR}/openlayers-10.6.1-package/dist/ol.js.map
+  ${CMAKE_CURRENT_BINARY_DIR}/popper.min.js
   DESTINATION
   ${JAVASCRIPT_LIBS_DIR}/js
   )
 
 file(COPY
+  ${CMAKE_CURRENT_BINARY_DIR}/bootstrap-5.3.3/dist/css/bootstrap.min.css
   ${CMAKE_CURRENT_BINARY_DIR}/openlayers-10.6.1-package/ol.css
   DESTINATION
   ${JAVASCRIPT_LIBS_DIR}/css
--- a/ViewerPlugin/viewer.html	Tue Nov 04 18:25:39 2025 +0100
+++ b/ViewerPlugin/viewer.html	Tue Nov 04 19:06:41 2025 +0100
@@ -6,30 +6,57 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>Orthanc for Whole-Slide Imaging</title>
 
+    <link rel="stylesheet" href="../libs/css/bootstrap.min.css" type="text/css">
     <link rel="stylesheet" href="../libs/css/ol.css" type="text/css">
 
     <style>
       html,
       body {
-        margin: 0;
-        height: 100%;
+          margin: 0;
+          height: 100%;
       }
 
       #map {
-        position: absolute;
-        top: 0;
-        bottom: 0;
-        width: 100%;
+          position: absolute;
+          top: 0;
+          bottom: 0;
+          width: 100%;
+      }
+
+      .ol-rotate {
+          top: 4em;
+          left: .5em;
+          right: initial;
       }
     </style>
 
   </head>
   <body>
-    <div id="map"></div>
+    <div id="map">
+    </div>
+
+    <div style="display:none">
+      <div id="popover-content">
+        <div class="container">
+          <div class="row mb-2">
+            <div class="btn-group btn-group-sm" role="group">
+              <button type="button" class="btn btn-outline-dark" id="rotation-reset">Reset</button>
+              <button type="button" class="btn btn-outline-dark" id="rotation-plus90">+90&deg;</button>
+              <button type="button" class="btn btn-outline-dark" id="rotation-minus90">-90&deg;</button>
+            </div>
+          </div>
+          <div class="row">
+            <input type="range" class="form-range" min="-180" max="180" id="rotation-slider">
+          </div>
+        </div>
+      </div>
+    </div>
 
     <!-- This is the version of jQuery that is used by Orthanc Explorer -->
     <script src="../../app/libs/jquery.min.js"></script>
 
+    <script src="../libs/js/popper.min.js"></script>
+    <script src="../libs/js/bootstrap.min.js"></script>
     <script src="../libs/js/ol.js"></script>
     <script src="viewer.js"></script>
   </body>
--- a/ViewerPlugin/viewer.js	Tue Nov 04 18:25:39 2025 +0100
+++ b/ViewerPlugin/viewer.js	Tue Nov 04 19:06:41 2025 +0100
@@ -77,6 +77,19 @@
 
   var extent = [0, -height, width, 0];
 
+  var rotateControl = new ol.control.Rotate({
+    autoHide: false,  // Show the button even if rotation is 0
+    resetNorth: function() {  // Disable the default action
+    }
+  });
+
+  new bootstrap.Popover(rotateControl.element, {
+    placement: 'right',
+    container: 'body',
+    html: true,
+    content: $('#popover-content')
+  });
+
   // Disable the rotation of the map, and inertia while panning
   // http://stackoverflow.com/a/25682186
   var interactions = ol.interaction.defaults.defaults({
@@ -93,6 +106,7 @@
   var controls = ol.control.defaults.defaults({
     attribution: false
   }).extend([
+    rotateControl,
     new ol.control.ScaleLine({
       minWidth: 100
     })
@@ -131,6 +145,31 @@
   });
 
   map.getView().fit(extent, map.getSize());
+
+
+  $('#rotation-slider').on('input change', function() {
+    map.getView().setRotation(this.value / 180 * Math.PI);
+  });
+
+  $('#rotation-reset').click(function() {
+    $('#rotation-slider').val(0).change();
+  });
+
+  $('#rotation-minus90').click(function() {
+    var angle = parseInt($('#rotation-slider').val()) - 90;
+    if (angle < -180) {
+      angle += 360;
+    }
+    $('#rotation-slider').val(angle).change();
+  });
+
+  $('#rotation-plus90').click(function() {
+    var angle = parseInt($('#rotation-slider').val()) + 90;
+    if (angle > 180) {
+      angle -= 360;
+    }
+    $('#rotation-slider').val(angle).change();
+  });
 }