Преглед на файлове

Reimplement pan and zoom functionality.

Andrew Klopper преди 6 години
родител
ревизия
e55299bc44
променени са 3 файла, в които са добавени 73 реда и са изтрити 534 реда
  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
 <html>
2
 <html>
3
     <head>
3
     <head>
4
         <meta charset="UTF-8">
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
         <script src="js/vendor/opencv/opencv.js"></script>
6
         <script src="js/vendor/opencv/opencv.js"></script>
7
+        <script src="js/vendor/interact/interact.min.js"></script>
7
         <script src="js/vendor/load-image/load-image.all.min.js"></script>
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
         <script src="js/vendor/moment/moment.min.js"></script>
9
         <script src="js/vendor/moment/moment.min.js"></script>
11
         <script src="js/xword.js"></script>
10
         <script src="js/xword.js"></script>
12
         <style>
11
         <style>
13
-            canvas {
14
-                width: 400px;
15
-            }
16
             #sourceImageContainer {
12
             #sourceImageContainer {
17
-                width: 400px;
18
-                overflow: hidden;
13
+                width: 100%;
14
+                overflow: scroll;
15
+                touch-action: pan-x pan-y;
19
             }
16
             }
20
             #sourceImage {
17
             #sourceImage {
21
                 position: relative;
18
                 position: relative;
22
-                width: min-content;
23
-            }
24
-            #sourceImage canvas {
25
-                width: auto;
26
             }
19
             }
27
             #sourceImage .overlay {
20
             #sourceImage .overlay {
28
                 position: absolute;
21
                 position: absolute;
32
             .handle {
25
             .handle {
33
                 position: absolute;
26
                 position: absolute;
34
                 box-sizing: border-box;
27
                 box-sizing: border-box;
35
-                width: 301px;
36
-                height: 301px;
28
+                width: 71px;
29
+                height: 71px;
37
                 border-radius: 50%;
30
                 border-radius: 50%;
38
-                border: 6px solid red;
31
+                border: 2px solid red;
39
                 transform: translate(-50%, -50%);
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
         </style>
41
         </style>
46
     </head>
42
     </head>
52
             <div id="sourceImage"></div>
48
             <div id="sourceImage"></div>
53
         </div>
49
         </div>
54
         <button id="recalculateButton">Recalculate</button>
50
         <button id="recalculateButton">Recalculate</button>
55
-        <div>
51
+        <div id="outputContainer">
56
             <canvas id="output"></canvas>
52
             <canvas id="output"></canvas>
57
         </div>
53
         </div>
58
         <div>
54
         <div>
59
             <a id="download" href="#" download="crossword.png">Download</a>
55
             <a id="download" href="#" download="crossword.png">Download</a>
60
         </div>
56
         </div>
61
-        <div id="graph"></div>
62
         <script>
57
         <script>
63
             'use strict';
58
             'use strict';
64
 
59
 
67
             let fileInput = document.getElementById("fileInput");
62
             let fileInput = document.getElementById("fileInput");
68
             let output = document.getElementById('output');
63
             let output = document.getElementById('output');
69
             let downloadLink = document.getElementById('download');
64
             let downloadLink = document.getElementById('download');
65
+            let recalculateButton = document.getElementById('recalculateButton');
70
 
66
 
71
             let isSquare = true;
67
             let isSquare = true;
72
 
68
 
88
 
84
 
89
             let src = null;
85
             let src = null;
90
             let img = null;
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
             sourceImageParent.addEventListener('wheel', function(event) {
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
             fileInput.onchange = function(e) {
105
             fileInput.onchange = function(e) {
109
                         function(canvas) {
109
                         function(canvas) {
110
                             let imageWidth = canvas.width;
110
                             let imageWidth = canvas.width;
111
                             let imageHeight = canvas.height;
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
                             if (src != null) {
116
                             if (src != null) {
116
                                 src.delete();
117
                                 src.delete();
127
                             }
128
                             }
128
                             sourceImage.appendChild(canvas);
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
                             let overlay = document.createElement('canvas');
131
                             let overlay = document.createElement('canvas');
137
                             overlay.className = 'overlay';
132
                             overlay.className = 'overlay';
138
                             overlay.width = imageWidth;
133
                             overlay.width = imageWidth;
145
 
140
 
146
                             let handles = [];
141
                             let handles = [];
147
 
142
 
148
-                            function getNewCorners() {
143
+                            function getCornersFromHandles() {
149
                                 let corners = [];
144
                                 let corners = [];
150
                                 handles.forEach(function(handle) {
145
                                 handles.forEach(function(handle) {
151
                                     corners.push(new cv.Point(
146
                                     corners.push(new cv.Point(
157
                             }
152
                             }
158
 
153
 
159
                             function redrawOverlay() {
154
                             function redrawOverlay() {
160
-                                let corners = getNewCorners();
161
-                                context.lineWidth = 1 / zoomer.getScale();
155
+                                let corners = getCornersFromHandles();
156
+                                context.lineWidth = imageWidth / scaledWidth;
162
                                 context.clearRect(0, 0, imageWidth, imageHeight);
157
                                 context.clearRect(0, 0, imageWidth, imageHeight);
163
                                 context.beginPath();
158
                                 context.beginPath();
164
                                 let corner = corners[corners.length - 1];
159
                                 let corner = corners[corners.length - 1];
169
                                 context.stroke();
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
                             function dragMoveListener(event) {
179
                             function dragMoveListener(event) {
173
                                 let target = event.target;
180
                                 let target = event.target;
174
-                                let newLeft = Math.min(
181
+                                let scale = scaledWidth / imageWidth;
182
+                                target.dataset.left = Math.min(
175
                                     imageWidth - 1,
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
                                     imageHeight - 1,
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
                                 redrawOverlay();
191
                                 redrawOverlay();
187
                             }
192
                             }
188
 
193
 
189
                             function recalculate() {
194
                             function recalculate() {
190
                                 let numRows;
195
                                 let numRows;
191
                                 let numCols;
196
                                 let numCols;
192
-                                let corners = getNewCorners();
197
+                                let corners = getCornersFromHandles();
193
                                 let square = extractSquare(img, corners);
198
                                 let square = extractSquare(img, corners);
194
                                 try {
199
                                 try {
195
                                     numRows = getLineFrequency(square, lineDetectorElementSize, 1);
200
                                     numRows = getLineFrequency(square, lineDetectorElementSize, 1);
219
                                 downloadLink.download = 'crossword_' + moment().format('YYYYMMDD_HHmmss') + '.png';
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
                             src = cv.imread(canvas);
245
                             src = cv.imread(canvas);
228
 
246
 
261
                                 handles.push(handle);
279
                                 handles.push(handle);
262
                             });
280
                             });
263
 
281
 
264
-                            redrawOverlay();
282
+                            resize();
265
                             recalculate();
283
                             recalculate();
266
                         },
284
                         },
267
                         {
285
                         {

Файловите разлики са ограничени, защото са твърде много
+ 0 - 472
js/vendor/panzoom/panzoom.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 7
js/vendor/plotly/plotly-latest.min.js