Parcourir la Source

Reimplement pan and zoom functionality.

Andrew Klopper il y a 6 ans
Parent
révision
e55299bc44
3 fichiers modifiés avec 73 ajouts et 534 suppressions
  1. 73 55
      index.html
  2. 0 472
      js/vendor/panzoom/panzoom.js
  3. 0 7
      js/vendor/plotly/plotly-latest.min.js

+ 73 - 55
index.html

@@ -2,27 +2,20 @@
2 2
 <html>
3 3
     <head>
4 4
         <meta charset="UTF-8">
5
-        <script src="js/vendor/interact/interact.min.js"></script>
5
+        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6 6
         <script src="js/vendor/opencv/opencv.js"></script>
7
+        <script src="js/vendor/interact/interact.min.js"></script>
7 8
         <script src="js/vendor/load-image/load-image.all.min.js"></script>
8
-        <script src="js/vendor/plotly/plotly-latest.min.js"></script>
9
-        <script src="js/vendor/panzoom/panzoom.js"></script>
10 9
         <script src="js/vendor/moment/moment.min.js"></script>
11 10
         <script src="js/xword.js"></script>
12 11
         <style>
13
-            canvas {
14
-                width: 400px;
15
-            }
16 12
             #sourceImageContainer {
17
-                width: 400px;
18
-                overflow: hidden;
13
+                width: 100%;
14
+                overflow: scroll;
15
+                touch-action: pan-x pan-y;
19 16
             }
20 17
             #sourceImage {
21 18
                 position: relative;
22
-                width: min-content;
23
-            }
24
-            #sourceImage canvas {
25
-                width: auto;
26 19
             }
27 20
             #sourceImage .overlay {
28 21
                 position: absolute;
@@ -32,15 +25,18 @@
32 25
             .handle {
33 26
                 position: absolute;
34 27
                 box-sizing: border-box;
35
-                width: 301px;
36
-                height: 301px;
28
+                width: 71px;
29
+                height: 71px;
37 30
                 border-radius: 50%;
38
-                border: 6px solid red;
31
+                border: 2px solid red;
39 32
                 transform: translate(-50%, -50%);
33
+                touch-action: none;
34
+            }
35
+            #outputContainer {
36
+                width: 100%;
40 37
             }
41
-            #graph {
42
-                width: 1000px;
43
-                height: 800px;
38
+            canvas {
39
+                width: 100%;
44 40
             }
45 41
         </style>
46 42
     </head>
@@ -52,13 +48,12 @@
52 48
             <div id="sourceImage"></div>
53 49
         </div>
54 50
         <button id="recalculateButton">Recalculate</button>
55
-        <div>
51
+        <div id="outputContainer">
56 52
             <canvas id="output"></canvas>
57 53
         </div>
58 54
         <div>
59 55
             <a id="download" href="#" download="crossword.png">Download</a>
60 56
         </div>
61
-        <div id="graph"></div>
62 57
         <script>
63 58
             'use strict';
64 59
 
@@ -67,6 +62,7 @@
67 62
             let fileInput = document.getElementById("fileInput");
68 63
             let output = document.getElementById('output');
69 64
             let downloadLink = document.getElementById('download');
65
+            let recalculateButton = document.getElementById('recalculateButton');
70 66
 
71 67
             let isSquare = true;
72 68
 
@@ -88,18 +84,22 @@
88 84
 
89 85
             let src = null;
90 86
             let img = null;
91
-            let zoomCallback = null;
92 87
 
93
-            let zoomer = Panzoom(sourceImage, {
94
-                excludeClass: 'handle'
95
-            });
96
-            sourceImage.addEventListener('panzoomzoom', function(event) {
97
-                if (zoomCallback != null) zoomCallback(event);
98
-            });
99
-            
88
+            let wheelCallback = null;
89
+            let gestureCallback = null;
90
+
100 91
             sourceImageParent.addEventListener('wheel', function(event) {
101
-                if (! event.shiftKey) return;
102
-                zoomer.zoomWithWheel(event, {disablePan: true});
92
+                if (wheelCallback != null) {
93
+                    wheelCallback(event);
94
+                }
95
+            });
96
+
97
+            interact(sourceImageParent).gesturable({
98
+                onmove: function(event) {
99
+                    if (gestureCallback != null) {
100
+                        gestureCallback(event);
101
+                    }
102
+                }
103 103
             });
104 104
 
105 105
             fileInput.onchange = function(e) {
@@ -109,8 +109,9 @@
109 109
                         function(canvas) {
110 110
                             let imageWidth = canvas.width;
111 111
                             let imageHeight = canvas.height;
112
-                            let imageScale = sourceImageParent.offsetWidth / imageWidth;
113
-                            sourceImageParent.style.height = Math.round(imageHeight * imageScale) + 'px';
112
+                            let containerWidth = sourceImageParent.offsetWidth;
113
+                            let scaledWidth = containerWidth;
114
+                            sourceImageParent.style.height = Math.round(imageHeight * scaledWidth / imageWidth) + 'px';
114 115
 
115 116
                             if (src != null) {
116 117
                                 src.delete();
@@ -127,12 +128,6 @@
127 128
                             }
128 129
                             sourceImage.appendChild(canvas);
129 130
 
130
-                            zoomer.setOptions({
131
-                                minScale: imageScale,
132
-                                maxScale: 1
133
-                            });
134
-                            zoomer.zoomToPoint(imageScale, {clientX: sourceImageParent.offsetLeft, clientY: sourceImageParent.offsetTop});
135
-
136 131
                             let overlay = document.createElement('canvas');
137 132
                             overlay.className = 'overlay';
138 133
                             overlay.width = imageWidth;
@@ -145,7 +140,7 @@
145 140
 
146 141
                             let handles = [];
147 142
 
148
-                            function getNewCorners() {
143
+                            function getCornersFromHandles() {
149 144
                                 let corners = [];
150 145
                                 handles.forEach(function(handle) {
151 146
                                     corners.push(new cv.Point(
@@ -157,8 +152,8 @@
157 152
                             }
158 153
 
159 154
                             function redrawOverlay() {
160
-                                let corners = getNewCorners();
161
-                                context.lineWidth = 1 / zoomer.getScale();
155
+                                let corners = getCornersFromHandles();
156
+                                context.lineWidth = imageWidth / scaledWidth;
162 157
                                 context.clearRect(0, 0, imageWidth, imageHeight);
163 158
                                 context.beginPath();
164 159
                                 let corner = corners[corners.length - 1];
@@ -169,27 +164,37 @@
169 164
                                 context.stroke();
170 165
                             }
171 166
 
167
+                            function repositionHandle(handle) {
168
+                                let scale = scaledWidth / imageWidth;
169
+                                handle.style.left = (parseFloat(handle.dataset.left) * scale) + 'px';
170
+                                handle.style.top = (parseFloat(handle.dataset.top) * scale) + 'px';
171
+                            }
172
+
173
+                            function resize() {
174
+                                sourceImage.style.width = scaledWidth + 'px';
175
+                                handles.forEach(repositionHandle);
176
+                                redrawOverlay();
177
+                            }
178
+
172 179
                             function dragMoveListener(event) {
173 180
                                 let target = event.target;
174
-                                let newLeft = Math.min(
181
+                                let scale = scaledWidth / imageWidth;
182
+                                target.dataset.left = Math.min(
175 183
                                     imageWidth - 1,
176
-                                    Math.max(0, parseFloat(target.dataset.left) + event.dx / zoomer.getScale())
184
+                                    Math.max(0, parseFloat(target.dataset.left) + event.dx / scale)
177 185
                                 );
178
-                                let newTop = Math.min(
186
+                                target.dataset.top = Math.min(
179 187
                                     imageHeight - 1,
180
-                                    Math.max(0, parseFloat(target.dataset.top) + event.dy / zoomer.getScale())
188
+                                    Math.max(0, parseFloat(target.dataset.top) + event.dy / scale)
181 189
                                 );
182
-                                target.dataset.left = newLeft;
183
-                                target.dataset.top = newTop;
184
-                                target.style.left = newLeft + 'px';
185
-                                target.style.top = newTop + 'px';
190
+                                repositionHandle(target);
186 191
                                 redrawOverlay();
187 192
                             }
188 193
 
189 194
                             function recalculate() {
190 195
                                 let numRows;
191 196
                                 let numCols;
192
-                                let corners = getNewCorners();
197
+                                let corners = getCornersFromHandles();
193 198
                                 let square = extractSquare(img, corners);
194 199
                                 try {
195 200
                                     numRows = getLineFrequency(square, lineDetectorElementSize, 1);
@@ -219,10 +224,23 @@
219 224
                                 downloadLink.download = 'crossword_' + moment().format('YYYYMMDD_HHmmss') + '.png';
220 225
                             }
221 226
 
222
-                            document.getElementById('recalculateButton').onclick = recalculate;
223
-                            zoomCallback = function(event) {
224
-                                redrawOverlay();
225
-                            };
227
+                            function zoomChanged(delta) {
228
+                                scaledWidth = Math.min(
229
+                                    imageWidth,
230
+                                    Math.max(containerWidth, scaledWidth + delta)
231
+                                );
232
+                                resize();
233
+                            }
234
+
235
+                            recalculateButton.onclick = recalculate;
236
+                            wheelCallback = function(event) {
237
+                                if (! event.shiftKey) return;
238
+                                event.preventDefault();
239
+                                zoomChanged(-event.deltaY);
240
+                            }
241
+                            gestureCallback = function(event) {
242
+                                zoomChanged(scaledWidth * event.ds);
243
+                            }
226 244
 
227 245
                             src = cv.imread(canvas);
228 246
 
@@ -261,7 +279,7 @@
261 279
                                 handles.push(handle);
262 280
                             });
263 281
 
264
-                            redrawOverlay();
282
+                            resize();
265 283
                             recalculate();
266 284
                         },
267 285
                         {

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 472
js/vendor/panzoom/panzoom.js


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 7
js/vendor/plotly/plotly-latest.min.js