ピンチイン・ピンチアウトでズームする方法
いわゆるズームです。タッチデバイスのピンチイン、ピンチアウトの動作を検出し、それによって画像を縮小、拡大してみましょう。難易度は高く、タッチした位置の取得方法など基本的な知識がある方を前提にしています。
サンプルコード
要点はピンチイン、ピンチアウトを開始した時と、指を動かした時の距離の比率を求めることです。
基本の距離
2本以上の指でピンチイン、ピンチアウトを開始した時の、2点間の距離を基本の距離(baseDistance)とします。touchstartイベントで距離を取りたいと思いがちですが、ここで重大な問題があります。2017年8月現在、Androidだとtouchstartイベントで1ヶ所のタッチしか受け取れません。だからtouchmoveイベントでまかないましょう。
JavaScript
// 基本の距離
var baseDistance = 0 ;
// 距離を測る関数
function getDistance ( event ) {
event.preventDefault() ;
var touches = event.changedTouches ;
// 2本以上の指の場合だけ処理
if ( touches.length > 1 ) {
// 座標1 (1本目の指)
var x1 = touches[0].pageX ;
var y1 = touches[0].pageY ;
// 座標2 (2本目の指)
var x2 = touches[1].pageX ;
var y2 = touches[1].pageY ;
// 2点間の距離
return Math.sqrt( Math.pow( x2-x1, 2 ) + Math.pow( y2-y1, 2 ) ) ;
}
return 0 ;
}
// touchmove
element.ontouchmove = function ( event ) {
// 操作開始時の距離
baseDistance = getDistance( event ) ;
}
変化後の距離
次に開始位置から2本指を動かした時、その距離を変化後の距離(movedDistance)とします。先ほどのtouchmoveイベント内を変更します。
element.ontouchmove = function ( event ) {
if ( baseDistance ) {
// 変化後の距離
var movedDistance = getDistance( event ) ;
} else {
// 基本の距離
baseDistance = getDistance( event ) ;
}
}
比率の計算
基本の距離と変化後の距離の比率を算出します。当たり前ですが、ピンチインで距離が縮めば比率は1以下、ピンチアウトで距離が拡がれば比率は1以上になりますよね。この比率を、そのまま画像の横幅、高さに適用すれば縮小、拡大できるというわけです。
var scale = movedDistance / baseDistance ;
デモ
前章で説明した要点を踏襲して作成したコードです。タッチデバイスを使って、枠内の黄色い部分でピンチイン、ピンチアウトをしてみて下さい。それに合わせて画像が縮小、拡大するはずです。ピンチイン、ピンチアウトの操作が少しでも止まったら、基本の距離を更新するようにしましょう。
// <div id="target1"></div>
var divElement = document.getElementById( "target1" ) ;
// <img id="target2">
var imgElement = document.getElementById( "target2" ) ;
// base
var beseDistance = 0 ;
var baseImageWidth = 0 ;
var baseImageHeight = 0 ;
// timeout id
var timeoutId ;
// touchmove
divElement.ontouchmove = function ( event ) {
event.preventDefault() ;
var touches = event.changedTouches ;
if ( touches.length > 1 ) {
var x1 = touches[0].pageX ;
var y1 = touches[0].pageY ;
var x2 = touches[1].pageX ;
var y2 = touches[1].pageY ;
var distance = Math.sqrt( Math.pow( x2-x1, 2 ) + Math.pow( y2-y1, 2 ) ) ;
clearTimeout( timeoutId ) ;
if ( beseDistance && baseImageWidth && baseImageHeight ) {
var scale = distance / beseDistance ;
if ( scale && scale != Infinity ) {
imgElement.width = baseImageWidth * scale ;
imgElement.height = baseImageHeight * scale ;
}
timeoutId = setTimeout( function () {
beseDistance = 0 ;
baseImageWidth = 0 ;
baseImageHeight = 0 ;
}, 100 ) ;
} else {
beseDistance = distance ;
baseImageWidth = imgElement.width ;
baseImageHeight = imgElement.height ;
}
}
}

関連記事
- クリックした位置を取得する方法
- マウスでクリックした位置を取得するには、eventオブジェクトのpageX、pageYを参照します。
- タッチした位置を取得する方法
- スマホなどでタッチした位置座標を取得します。
- ドラッグオーバー中だけスタイルを適用する方法
- ドロップできる要素にドラッグオーバー中だけスタイルを適用するには、dragoverイベントと、setTimeout()を組み合わせましょう。
- 回転ジェスチャーを検出する方法
- タッチデバイスの回転ジェスチャーで画像を回転させます。
- マウスデバイスとタッチデバイスを判別する方法
- ユーザーがマウスデバイスなのか、タッチデバイスなのかを判定します。