]> gitweb.michael.orlitzky.com - charm-bypass.git/commitdiff
index.html.in: more work on the QR focus
authorMichael Orlitzky <michael@orlitzky.com>
Tue, 9 Sep 2025 02:15:36 +0000 (22:15 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Tue, 9 Sep 2025 02:15:36 +0000 (22:15 -0400)
Tapping the QR code now brings it into focus and centers it in the
ticket, accompanied by a nice CSS transition that mimics the real
thing. The timing was adjusted to make the transition faster, and a
portability issue was hacked around. What does work, works in both
Firefox and WebKit (on the desktop) at least.

Still to-do is the ticket resizing that takes place when the QR code
gets bigger, and the vertical translation of the (growing) QR code.

index.html.in

index 9316fb991cc0ae72eb6c4ffae1d91cffc60db4c1..6813c4b900bd096c077d215fb56364aad3eb0698 100644 (file)
 
       #serviceid, #servicename, #codebg, #codetext {
         transition-property: opacity;
-        transition-duration: 0.5s;
+        transition-duration: 0.25s;
       }
       .transparent {
         opacity: 0;
       }
+
+      #qr {
+        transition-property: transform;
+        transition-duration: 0.25s;
+        transform-box: fill-box;
+        transform-origin: bottom right;
+      }
     </style>
   </head>
 
         }
       }
 
-
       /**
        * Center the security code within its container.
        *
        * ticket itself also grows somewhat, at least on BaltimoreLink
        * tickets. When the QR code is tapped again, this process
        * reverses.
+       *
+       * We use a CSS class to indicate whether or not the QR code is
+       * focused because that's cleaner than a global variable, but
+       * we perform the translation using Javascript because we need
+       * to compute the offset on-the-fly. It's easy to figure out
+       * the offset in SVG coordinates, but it turns out that WebKit
+       * won't do transition effects for the SVG "transform" attribute.
+       * So to get transitions, we have to use the "transform" style
+       * instead. But, the "transform" style uses pixels! Ergo, we
+       * must first convert between the two using an object whose
+       * size is known. We use the same trick when centering the
+       * security code within its box.
        */
       function toggle_qr_focus(event) {
         /* Don't swap night/day if the tap was on the QR code. */
         const codetext = document.getElementById("codetext");
         const codebg = document.getElementById("codebg");
 
+        /* Compute the QR translation amount in pixels using
+         * the (known) width of the security code box. */
+        const r1 = codebg.getBoundingClientRect();
+        const svg_to_css = r1.width / parseFloat(codebg.getAttribute("width"));
+        const offset = -6.56 * svg_to_css;
+
         let ticket_class;  /* transparent, or none (opaque) */
         let qr_class;      /* big, or none (normal sized) */
+        let qr_transform;  /* text of the transform style to be set */
 
         if (qr.getAttribute("class") == "big") {
           ticket_class = "";
           qr_class = "";
+          qr_transform = "";
         }
         else {
           ticket_class = "transparent";
           qr_class = "big";
+
+          /* The scale factor can easily be measured in CharmPass by
+           * taking two screenshots, pre- and post-tap. The magic offset
+           * was measured by scaling up the QR code in the SVG, and
+           * then centering it on the ticket. This gives you the offset
+           * in SVG units, which we then have to DIVIDE by 4.1333333,
+           * because the scale factor affects the translation. */
+          qr_transform = "scale(4.1333333) translate(" + offset + "px, 0px)";
         }
 
         serviceid.setAttribute("class", ticket_class);
         codetext.setAttribute("class", ticket_class);
         codebg.setAttribute("class", ticket_class);
 
+        qr.style.transform = qr_transform;
         qr.setAttribute("class", qr_class);
       }