Windows タッチ&ジェスチャ研究室 Vol.02 ~Silverlightでのストレッチ/ピンチ~
前回の記事で、Sliverlightでマルチタッチを実装するには、Touchクラスを使用することを説明しました。
Touchクラスは、タッチされた座標等の生のデータを取得するクラスなので、ジェスチャーに対応したアプリを開発するには、生のデータを加工する必要があります。
今回は、Silverlightで2本の指を使用したストレッチ(2本の指の間隔を広げて拡大する)と、ピンチ(2本の指の間隔を狭めて縮小する)のサンプル アプリケーションを紹介します。
充分なテストをしている訳ではありませんので、実装時に参考する程度にしてください。
=======================
public partial class MainPage : UserControl
{
private Point FirstFingerOrigin = new Point();
private Point FirstFingerStart = new Point();
private Point FirstFingerEnd = new Point();
private Point FirstFingerFinish = new Point();
private int FirstFingerID = -1;
private Point SecondFingerOrigin = new Point();
private Point SecondFingerStart = new Point();
private Point SecondFingerEnd = new Point();
private Point SecondFingerFinish = new Point();
private int SecondFingerID = -1;
private Point FirstFingerTranslation = new Point();
private Point SecondFingerTranslation = new Point();
private Point Scale = new Point();
private double TotalScale;
public MainPage()
{
InitializeComponent();
Touch.FrameReported += new TouchFrameEventHandler(Touch_FrameReported);
}
void Touch_FrameReported(object sender, TouchFrameEventArgs e)
{
TouchPointCollection touchPoints = e.GetTouchPoints(null);
foreach (var touchPoint in touchPoints)
{
switch (touchPoint.Action)
{
case TouchAction.Down:
if (FirstFingerID == -1)
{
// 最初のタッチのID
FirstFingerID = touchPoint.TouchDevice.Id;
FirstFingerOrigin = touchPoint.Position;
FirstFingerStart = FirstFingerOrigin;
FirstFingerTranslation.X = 0;
FirstFingerTranslation.Y = 0;
}
else if (SecondFingerID == -1)
{
// 2番めのタッチのID
SecondFingerID = touchPoint.TouchDevice.Id;
SecondFingerOrigin = touchPoint.Position;
SecondFingerStart = SecondFingerOrigin;
SecondFingerTranslation.X = 0;
SecondFingerTranslation.Y = 0;
}
break;
case TouchAction.Move:
if (FirstFingerID == touchPoint.TouchDevice.Id)
{
FirstFingerEnd = touchPoint.Position;
// 指が移動しているときに何かするときは、ここに実装する
FirstFingerStart = FirstFingerEnd;
}
else if (SecondFingerID == touchPoint.TouchDevice.Id)
{
SecondFingerEnd = touchPoint.Position;
// 指が移動しているときに何かするときは、ここに実装する
SecondFingerStart = SecondFingerEnd;
}
break;
case TouchAction.Up:
if (FirstFingerID == touchPoint.TouchDevice.Id)
{
FirstFingerFinish = touchPoint.Position;
FirstFingerTranslation.X =
FirstFingerFinish.X - FirstFingerOrigin.X;
FirstFingerTranslation.Y =
FirstFingerFinish.Y - FirstFingerOrigin.Y;
FirstFingerID = -1;
}
else if (SecondFingerID == touchPoint.TouchDevice.Id)
{
SecondFingerFinish = touchPoint.Position;
SecondFingerTranslation.X =
SecondFingerFinish.X - SecondFingerOrigin.X;
SecondFingerTranslation.Y =
SecondFingerFinish.Y - SecondFingerOrigin.Y;
SecondFingerID = -1;
}
// 1つめの指、2つめの指の両方が動いていたとき
if ((FirstFingerTranslation.X != 0 ||
FirstFingerTranslation.Y != 0) &&
(SecondFingerTranslation.X != 0 ||
SecondFingerTranslation.Y != 0))
{
Point originDistance = new Point();
Point finishDistance = new Point();
// タッチしたときの2つの指の距離
originDistance.X =
SecondFingerOrigin.X - FirstFingerOrigin.X;
originDistance.Y =
SecondFingerOrigin.Y - FirstFingerOrigin.Y;
// 離したときの2つの指の距離
finishDistance.X =
SecondFingerFinish.X - FirstFingerFinish.X;
finishDistance.Y =
SecondFingerFinish.Y - FirstFingerFinish.Y;
// 縮小率または拡大率
Scale.X = finishDistance.X / originDistance.X;
Scale.Y = finishDistance.Y / originDistance.Y;
// 三平方の定理を使い、距離を計算
double distance1, distance2;
distance1 = Math.Sqrt(Math.Pow(originDistance.X, 2) +
Math.Pow(originDistance.Y, 2));
distance2 = Math.Sqrt(Math.Pow(finishDistance.X, 2) +
Math.Pow(finishDistance.Y, 2));
TotalScale = distance2 / distance1;
}
// 結果を表示させるためのプログラム
// テキストボックスを3つ貼り付け、そこに情報を表示している
textBlock1.Text = Scale.X.ToString();
textBlock2.Text = Scale.Y.ToString();
textBlock3.Text = TotalScale.ToString();
break;
}
}
}
}
=======================
このプログラムを試すときは、まずTextBlockコントロールを3つ貼り付け、そしてMainPageクラスを上記のプログラムで書き換えてください。
結論としては、TotalScaleというフィールドに、拡大率(または縮小率)が入ります。1より大きい場合は拡大、1より小さい場合は縮小です。
単純に、ストレッチがピンチかを検知する場合は、TotalScaleのみを使えば検知できます。
水平方向または垂直方向の拡大率を使いたい場合は、Scale.XまたはScale.Yをご使用ください。
このプログラムでは、画面をタッチしたときのイベント発生時の、Down、Move、Upのそれぞれの処理を行っています。
指を動かしている最中にも画面の拡大/縮小を反映させたいときは、Moveの処置を行っているときに実装します。
主なフィールドの説明は、以下のとおりです。
FirstFingerOrigin : 最初の指がタッチしたときの座標
FirstFingerStart : 前回のMoveが呼ばれた時の座標 (Moveの処理を行うときに使用)
FirstFingerEnd : Moveが呼ばれたときの座標 (Moveの処理を行うときに使用)
FirstFingerFinish : 最初の指が離れたときの座標
Secondで始まるフィールドは、2本目にタッチした指に関する情報です。
Silverlightでも、Windows Phone 7の場合は、同じ機能をもったManipulationという機能がありますので、そちらをご使用ください。
[Windows タッチ&ジェスチャ研究室]
Vol.01 ~Silverlightのマルチタッチ検出~
マイクロソフト
田中達彦