aboutsummaryrefslogtreecommitdiff
path: root/src/web/pinch.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/web/pinch.js')
-rw-r--r--src/web/pinch.js60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/web/pinch.js b/src/web/pinch.js
new file mode 100644
index 0000000..14f843a
--- /dev/null
+++ b/src/web/pinch.js
@@ -0,0 +1,60 @@
+class Pinch {
+ constructor(element) {
+ this.event_cache = [];
+ this.previous_diff = null;
+ this.onpinch = () => {};
+ this.onfinish = () => {};
+
+ element.onpointerdown = (e) => this.pointer_down_handler(e);
+ element.onpointermove = (e) => this.pointer_move_handler(e);
+ element.onpointerup = (e) => this.pointer_up_handler(e);
+ element.onpointercancel = (e) => this.pointer_up_handler(e);
+ element.onpointerout = (e) => this.pointer_up_handler(e);
+ element.onpointerleave = (e) => this.pointer_up_handler(e);
+ }
+
+ pointer_down_handler(event) {
+ this.event_cache.push(event);
+ }
+
+ pointer_move_handler(event) {
+ const index = this.event_cache.findIndex(
+ (cached) => cached.pointerId == event.pointerId,
+ );
+ this.event_cache[index] = event;
+
+ if (this.event_cache.length === 2) {
+ event.preventDefault();
+
+ const diff = Math.hypot(
+ this.event_cache[0].clientX - this.event_cache[1].clientX,
+ this.event_cache[0].clientY - this.event_cache[1].clientY,
+ );
+
+ if (this.previous_diff != null) {
+ const point = {
+ x: (this.event_cache[0].clientX + this.event_cache[1].clientX) / 2,
+ y: (this.event_cache[0].clientY + this.event_cache[1].clientY) / 2,
+ };
+
+ const delta = this.previous_diff - diff;
+ this.onpinch(delta, point);
+ }
+
+ this.previous_diff = diff;
+ }
+ }
+
+ pointer_up_handler(event) {
+ const index = this.event_cache.findIndex(
+ (cached) => cached.pointerId === event.pointerId,
+ );
+ this.event_cache.splice(index, 1);
+
+ if (this.event_cache.length < 2) {
+ this.previous_diff = null;
+ }
+
+ this.onfinish();
+ }
+}