ピンチイン(ピンチアウト)の倍率を取得するJavaScript

pinch-in / pinch-out で、拡大縮小の割合を計算するスクリプトです。
写真を拡大縮小して見るスクリプトの一部です。

See the Pen get pinch-in / pinch-out zoom ratio by webdev (@webdev-jp-net) on CodePen.0

サンプルは、タッチデバイスで動作します。
マルチタッチを感知すると白背景にかわり、ピンチイン(アウト)で倍率を取得します。

写真を拡大縮小して見る機能を前提としているので
最小倍率と最大倍率をもうけ
離した瞬間のtouchendで補正をかけています。

マルチタッチ判定

touchstarttouchmoveは、
TouchEventのtouchesプロパティへタッチした場所の座標を配列で持っています。

デバイスの複数箇所をさわっている場合
時系列順で

e.touches[0]、e.touches[1]

…と配列に格納されていきます。

参考:
TouchEvent – Web API インターフェイス | MDN

倍率の取得

最初にさわったポイントと、2番目にさわったポイントの距離を
さわった瞬間のtouchstart
動かしている状態touchmoveで比較…

…したらいいかなと思いましたが、ジェスチャーイベントのプロパティですでに用意されていました。
event.scaleで取得できます。

せっせとピタゴラスの定理で距離をはかった私は何だったのかと、ため息が出たんですが
さらにしらべてみたところ

ジェスチャーイベントは Android でサポートされていませんでした

あ ぶ な い !

参考:
GestureEvent – Web APIs | MDN

倍率の計算

ということで、ピタゴラスの定理復活。

このようにして
1箇所目のタップポイント x1 と y1の座標、
2箇所目のタップポイント x2 と y2の座標を当てはめると距離がわかります。

Math.sqrt( Math.pow(x1-x2, 2) - Math.pow(y1-y2, 2) );

倍率は、このように割り算したら取得できます。

touchmove中の2点間の距離 / touchstart時点で保存しておいた2点間の距離

Math.sqrtは負の数を扱えない

ピタゴラスの定理で使用する、平方根を計算するためのMath.sqrt
負の数を与えるとNaNを返す仕様になっています。

参考:
Math.sqrt() – JavaScript | MDN

このサンプルの場合、touchstart時点より1箇所目と2箇所目のタップ位置の左右が逆転すると
Math.sqrtに投入する値が負の数になるため
あらかじめMath.absで絶対値に変換することで対応しています。

getDistance = function(e) {
	var x = Math.pow(e.touches[0].pageX - e.touches[1].pageX, 2) - Math.pow(e.touches[0].pageY - e.touches[1].pageY, 2);
	return Math.sqrt( Math.abs(x) );
};

関連記事