word/edit: custom crop interface superior to croppie
[sheet.git] / word / editor.js
index 0e54c62fe349a571727d1266af945bf12bddcbc2..5fc985446b6f128e8e3859e8061b43fe6237a413 100644 (file)
@@ -120,26 +120,74 @@ document.addEventListener('DOMContentLoaded', () => {
        let thumbpreview = document.getElementById('convertpreview');
        if (thumbpreview && imgpreview) {
                thumbpreview.onclick = e => {
+                       thumbpreview.onclick = null; // setup once
                        const cropinput = document.getElementById('crop32');
-                       let border = { width: 600, height: 400 };
-                       let crop = new Croppie(thumbpreview, {
-                               boundary: { width: border.width * 1.3, height: border.height * 1.2 },
-                               viewport: border,
-                               update: e => {
-                                       cropinput.value = e.points.map((pos, axis) => {
-                                               Math.round(1000 * pos / (axis % 2 ? border.height : border.width))
-                                       }).join(',');
-                               },
-                       });
-                       crop.bind({
-                               url: imgpreview.src,
-                               points: cropinput.value.split(/[^0-9]/).map((rel, axis) => {
-                                       return rel * (axis % 2 ? border.height : border.width) / 1000
-                               }),
-                       });
-                       crop.elements.overlay.addEventListener('dblclick', e => {
-                               crop.destroy();
-                       });
+                       const imgselect = thumbpreview.children[0];
+                       const border = [300,200];
+                       let crop = cropinput.value.split(/[^0-9]/).map(pos => pos / 1000);
+                       let scale = 1 / (crop[2] - crop[0]) || 1;
+                       crop.push(0); // defined y dimension
+                       crop.splice(2); // end coordinates applied to zoom
+                       crop = crop.map((rel, axis) => rel * border[axis % 2] * scale);
+
+                       let drag = false;
+                       function applydrag(e) {
+                               const pos = [e.pageX, e.pageY];
+                               if (drag) {
+                                       // apply drag delta to crop position
+                                       crop[0] += drag[0] - pos[0];
+                                       crop[1] += drag[1] - pos[1];
+                                       recrop();
+                               }
+                               drag = pos;
+                       }
+                       function recrop() {
+                               [0, 1].forEach(axis => {
+                                       if (crop[axis] > border[axis] * (scale - 1)) {
+                                               crop[axis] = border[axis] * (scale - 1);
+                                       }
+                                       if (crop[axis] < 0) {
+                                               crop[axis] = 0;
+                                       }
+                               });
+                               imgselect.style.left = -crop[0]+'px';
+                               imgselect.style.top  = -crop[1]+'px';
+                               imgselect.style.width = (scale * 100)+'%';
+                               cropinput.value = [
+                                       crop[0] / border[0],     crop[1] / border[1],
+                                       crop[0] / border[0] + 1, crop[1] / border[1] + 1,
+                               ].map(pos => Math.round(1000 * pos / scale));
+                       }
+
+                       imgselect.src = imgpreview.children[0].src;
+                       imgselect.style.position = 'absolute';
+                       recrop();
+
+                       imgselect.onmousedown = e => {
+                               e.preventDefault();
+                               applydrag(e);
+                       };
+                       imgselect.onmouseup = e => {
+                               e.preventDefault();
+                               drag = false;
+                       };
+                       imgselect.onmousemove = e => {
+                               if (!drag) return;
+                               applydrag(e);
+                       };
+                       imgselect.onwheel = e => {
+                               e.preventDefault();
+                               let zoom = e.deltaY * -.05 * scale;
+                               if (scale + zoom < 1) {
+                                       zoom = 1 - scale; // scale = 1
+                               }
+                               [0, 1].forEach(axis => {
+                                       // same area center at altered scale
+                                       crop[axis] += (crop[axis] + border[axis] / 2) / scale * zoom;
+                               });
+                               scale += zoom;
+                               recrop();
+                       };
                };
        }