| $ cat ./dom-examples/pointerevents/Pinch_zoom_gestures.html
|
| <!DOCTYPE html>
|
| <html lang=en>
|
| <!--
|
| This application demonstrates using Pointer Events for simple 2-pointer
|
| pinch/zoom gesture recognition.
|
| -->
|
| <head>
|
| <title>Pointer Events pinch/zoom example</title>
|
| <meta name="viewport" content="width=device-width">
|
| <style>
|
| #target {
|
| border: 1px solid black;
|
| }
|
| </style>
|
| </head>
|
|
|
| <script>
|
|
|
| // Log events flag
|
| var logEvents = false;
|
|
|
| // Global vars to cache event state
|
| var evCache = new Array();
|
| var prevDiff = -1;
|
|
|
| function updateLogTag() {
|
| document.getElementById("LOG_TEXT").innerHTML = "Log (" + (logEvents ? "Enabled" : "Disabled") + ")";
|
| }
|
|
|
| // Logging/debugging functions
|
| function toggleLog() {
|
| logEvents = logEvents ? false : true;
|
| updateLogTag();
|
| }
|
|
|
| function logInner(msg) {
|
| var p = document.getElementById('log');
|
| p.innerHTML = msg + "\n" + p.innerHTML;
|
| }
|
|
|
| function log(prefix, ev) {
|
| if (!logEvents) return;
|
| logInner(prefix + ": pointerID = " + ev.pointerId + " ; pointerType = " + ev.pointerType + " ; isPrimary = " + ev.isPrimary);
|
| }
|
|
|
| function clearLog(event) {
|
| var p = document.getElementById('log');
|
| p.innerHTML = "";
|
| }
|
|
|
| function pointerdown_handler(ev) {
|
| // The pointerdown event signals the start of a touch interaction.
|
| // This event is cached to support 2-finger gestures
|
| evCache.push(ev);
|
| log("pointerDown", ev);
|
| }
|
|
|
| function pointermove_handler(ev) {
|
| // This function implements a 2-pointer horizontal pinch/zoom gesture.
|
| //
|
| // If the distance between the two pointers has increased (zoom in),
|
| // the taget element's background is changed to "pink" and if the
|
| // distance is decreasing (zoom out), the color is changed to "lightblue".
|
| //
|
| // This function sets the target element's border to "dashed" to visually
|
| // indicate the pointer's target received a move event.
|
| log("pointerMove", ev);
|
| ev.target.style.border = "dashed";
|
|
|
| // Find this event in the cache and update its record with this event
|
| for (var i = 0; i < evCache.length; i++) {
|
| if (ev.pointerId == evCache[i].pointerId) {
|
| evCache[i] = ev;
|
| break;
|
| }
|
| }
|
|
|
| // If two pointers are down, check for pinch gestures
|
| if (evCache.length == 2) {
|
| // Calculate the distance between the two pointers
|
| var curDiff = Math.sqrt(Math.pow(evCache[1].clientX - evCache[0].clientX, 2) + Math.pow(evCache[1].clientY - evCache[0].clientY, 2));
|
|
|
| if (prevDiff > 0) {
|
| if (curDiff > prevDiff) {
|
| // The distance between the two pointers has increased
|
| log("Pinch moving OUT -> Zoom in", ev);
|
| ev.target.style.background = "pink";
|
| }
|
| if (curDiff < prevDiff) {
|
| // The distance between the two pointers has decreased
|
| log("Pinch moving IN -> Zoom out",ev);
|
| ev.target.style.background = "lightblue";
|
| }
|
| }
|
|
|
| // Cache the distance for the next move event
|
| prevDiff = curDiff;
|
| }
|
| }
|
|
|
| function pointerup_handler(ev) {
|
| log(ev.type, ev);
|
| // Remove this pointer from the cache and reset the target's
|
| // background and border
|
| remove_event(ev);
|
| ev.target.style.background = "blueviolet";
|
| ev.target.style.border = "1px solid black";
|
|
|
| // If the number of pointers down is less than two then reset diff tracker
|
| if (evCache.length < 2) prevDiff = -1;
|
| }
|
|
|
| function remove_event(ev) {
|
| // Remove this event from the target's cache
|
| for (var i = 0; i < evCache.length; i++) {
|
| if (evCache[i].pointerId == ev.pointerId) {
|
| evCache.splice(i, 1);
|
| break;
|
| }
|
| }
|
| }
|
|
|
| function init() {
|
| // Install event handlers for the pointer target
|
| var el=document.getElementById("target");
|
| el.onpointerdown = pointerdown_handler;
|
| el.onpointermove = pointermove_handler;
|
|
|
| // Use same handler for pointer{up,cancel,out,leave} events since
|
| // the semantics for these events - in this app - are the same.
|
| el.onpointerup = pointerup_handler;
|
| el.onpointercancel = pointerup_handler;
|
| el.onpointerout = pointerup_handler;
|
| el.onpointerleave = pointerup_handler;
|
| updateLogTag();
|
| logInner("Initialized");
|
| }
|
|
|
|
|
| </script>
|
| <body
|
| onload="init();"
|
| style="
|
| background-color: aqua;
|
| touch-action: none;
|
| clip-path: fill-box;
|
| border: 2px solid red;
|
| "
|
| >
|
| <div style="background-color: brown;"> links: </div>
|
| <object style="background-color: chartreuse;" data="uploaded_links.txt" width="300" height="200">
|
| Not supported
|
| </object>
|
| <h1>Pointer Event pinch/zoom gesture</h1>
|
| <!-- Create element for pointer gestures. -->
|
| <div style="border: 2px solid black; background-color: blueviolet;" id="target">Touch and Hold with 2 pointers, then pinch in or out.<br/>
|
| The background color will change to pink if the pinch is opening (Zoom In)
|
| or changes to lightblue if the pinch is closing (Zoom out).</div>
|
| <!-- UI for logging/debugging -->
|
| <button onclick="toggleLog();">Start/Stop event logging</button>
|
| <button onclick="clearLog();">Clear the log https://bpa.st/UJEMK</button>
|
| <div id="LOG_TEXT"></div>
|
| <div
|
| style="
|
| border: 2px solid black;
|
| clip-path: fill-box;
|
| "
|
| >
|
| <pre id="log"
|
| style="
|
| border: 2px solid #ccc;
|
| clip-path: fill-box;
|
| "
|
| ></pre>
|
| </div>
|
| </body>
|
| </html>
|