I am attempting to implement a feature which will change text size using pinch on iPhone. I am using meta/viewport tag to override default behavior, as well as css touch-action to override default zooming with pinch.
The problem is, even if my touchstart
listener is attached to window
or document.body
, if I initiate the pinch with each finger over 2 different elements, touches
or changedTouches
array only contains one element, thus I cannot evaluate the pinch action. If I start my pinch with both fingers over the same element, then the array contains 2 elements (one for each finger) and I can evaluate the pinch action.
How can I make this agnostic to which element the fingers are over upon initiation?
Here is the code I am using: (Note this is a naive implementation only evaluating horizontal movement for demo purposes.)
HTML:
<!DOCTYPE html>
<html>
<head>
<title>TOUCH</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
<script src="touch.js?<?php print $ts ?>"></script>
<style type="text/css">
/* Disable default zooming */
:root, html {
touch-action: pan-x pan-y;
height: 100%
}
html, body {
margin: 0;
padding: 0;
}
body {
padding: 10px;
min-height: 100vh;
font-family: Verdana;
font-size: 18px;
background-color: #fee;
}
#info {
padding: 40px 0 0 20px;
font-family: monospace;
font-size: 18px;
}
</style>
</head>
<body>
<div id="info">The info window</div>
<div id="info2" style="color: red">The info window2</div>
<div style="height: 10px"></div>
<div>
This is the way we wash our clothes This is the way we wash our clothes This is the way we wash our clothes This is the way we wash our clothes This is the way we wash our clothes This is the way we wash our clothes This is the way we wash our clothes
</div>
<div>
Every good boy deserves fudge Every good boy deserves fudge Every good boy deserves fudge Every good boy deserves fudge Every good boy deserves fudge Every good boy deserves fudge Every good boy deserves fudge Every good boy deserves fudge Every good boy deserves fudge
</div>
</body>
</html>
JS:
function init() {
window.addEventListener("touchstart", onTouchstart, { passive: false, capture: true });
}
function onTouchstart(evt) {
evt.preventDefault();
evt.stopPropagation();
let lastDistX = 0;
window.addEventListener("touchmove", onTouchmove, { passive: false, capture: true });
window.addEventListener("touchend", (evt) => {
window.removeEventListener("touchmove", onTouchmove, { passive: false, capture: true });
}, { once: true });
window.addEventListener("touchcancel", (evt) => {
window.removeEventListener("touchmove", onTouchmove, { passive: false, capture: true });
}, { once: true });
function onTouchmove(evt) {
let touches = Array.from(evt.changedTouches);
if (touches.length == 2) {
let distX = Math.abs(touches[1].screenX - touches[0].screenX);
if (!lastDistX) {
lastDistX = distX;
return;
}
let incDec = distX < lastDistX ? -1 : 1;
let initFS = parseFloat(getComputedStyle(document.body).fontSize);
let offset = (incDec * .25);
let fs = Math.max(initFS + offset, 12);
let fontSize = fs + "px";
document.body.style.fontSize = fontSize;
__("info").innerHTML = "touchmove " + lastDistX + " " + distX + " " + incDec + " " + initFS + " " + offset + " " + fontSize;
lastDistX = distX;
} else {
__("info2").innerHTML = touches[0].clientX;
}
evt.preventDefault();
evt.stopPropagation();
document.body.style.zoom = "100%";
document.body.style.transform = "scale(1)";
}
}
2