HTML 5 キャンバス要素でマルチタッチのピンチ、パン、ズームを処理するモジュールのほとんどを作成しました。以下に共有します。私はしばらくの間 JavaScript で開発してきましたが、これは私を悩ませ続けています。誰かが洞察を持っている場合は、iPadで動作することが確認されたら、最終バージョンをスタックに投稿して、全員が共有できるようにします.
これが私がやっていることです:
touchmove
イベントは、変数の変更をトリガーします。これらの変数を使用して、イメージをキャンバスにペイントする方法を変更します。8 つの変数があり、それぞれが関数に入れることができるオプションに対応していますdrawImage()
。これらの 8 つの変数は、値をインクリメント/デクリメントし、特定の範囲内に保つ関数によって更新されます。変数はクロージャー変数であるため、モジュール全体でグローバルです。過剰な処理を防ぐためにdrawImage()
、ユーザーがsetInterval()
. 問題は次のとおりです。
touchmove
イベントは、同じイベントの多くの異なるインスタンスによって変数が更新されるという競合状態を引き起こしているようです。これは、20 を下回らないように制限された 1 つの変数を追跡するコンソール出力である程度確認できます。一方向にすばやくスワイプすると、その変数は 20 をはるかに下回ります。次に指を離すと、ゆっくりとスワイプすると、 20 に戻ります。この方向に私を向けるもう 1 つのことは、プログラムをステップ実行しているときにこれらの変数を見ると、それらは私のconsole.log()
ポンプ出力とは異なります。
注: コードは、最初は正常に画像を描画しますが、それ以降は描画しません。私のコードの基本的な表現は以下のとおりです... 完全版はGitHubの Scripts フォルダー内にあります。それは本質的に Sencha Touch v1.1 アプリです
function PinchPanZoomFile(config)
{
/*
* Closure variable declaration here...
* Canvas Declaration here...
*/
function handleTouchStart(e) {
whatDown.oneDown = (e.originalEvent.targetTouches.length == 1) ? true : false;
whatDown.twoDown = (e.originalEvent.targetTouches.length >= 2) ? true : false;
drawInterval = setInterval(draw, 100);
}
function handleTouchEnd(e) {
whatDown.oneDown = (e.originalEvent.targetTouches.length == 1) ? true : false;
whatDown.twoDown = (e.originalEvent.targetTouches.length >= 2) ? true : false;
clearInterval(drawInterval);
}
function handleTouchMove(e) {
if(whatDown.twoDown) {
/*
* Do Panning & Zooming
*/
changeWindowXBy(deltaDistance); //deltaDistance
changeWindowYBy(deltaDistance); //deltaDistance
changeCanvasXBy(deltaX); //Pan
changeCanvasYBy(deltaY); //Pan
changeWindowDimsBy(deltaDistance*-1,deltaDistance*-1); //(deltaDistance)*-1 -- get smaller when zooming in.
changeCanvasWindowDimsBy(deltaDistance,deltaDistance); //deltaDistance -- get bigger when zooming in
} else if(whatDown.oneDown) {
/*
* Do Panning
*/
changeWindowXBy(0);
changeWindowYBy(0);
changeCanvasXBy(deltaX);
changeCanvasYBy(deltaY);
changeWindowDimsBy(0,0);
changeCanvasWindowDimsBy(0,0);
}
}
function draw() {
//Draw Image Off Screen
var offScreenCtx = offScreenCanvas[0].getContext('2d');
offScreenCtx.save();
offScreenCtx.clearRect(0, 0, canvasWidth, canvasHeight);
offScreenCtx.restore();
offScreenCtx.drawImage(base64Image,
parseInt(windowX),
parseInt(windowY),
parseInt(windowWidth),
parseInt(windowHeight),
parseInt(canvasX),
parseInt(canvasY),
parseInt(canvasWindowWidth),
parseInt(canvasWindowHeight)
);
//Draw Image On Screen
var offScreenImageData = offScreenCtx.getImageData(0, 0, canvasWidth, canvasHeight);
var onScreenCtx = canvas[0].getContext('2d');
onScreenCtx.putImageData(offScreenImageData, 0, 0);
}
}