ピンチで画像を拡大縮小

#wp7dev_jp #wpdev_jp

ピンチ操作で画像の拡大縮小、よくありそうなシナリオですが実装もそれほど難しくはありません。

まずは、UI側の準備です。Imageコントロールだけですが。

  • ピンチで画像の拡大縮小
  • 最小サイズは画面幅=480
  • 最大サイズは2000
  • ひとまず真ん中に表示

MainPage.xaml

拡大縮小処理の、最大・最少サイズの管理は本来面倒なのですが、プロパティに用意されているのでその辺は実装する必要はありません。これはうれしい。

 <!--LayoutRoot は、すべてのページ コンテンツが配置されるルート グリッドです-->
<Grid x:Name="LayoutRoot" Background="Transparent">
    <Image Name="image1" Stretch="Uniform" 
            Source="/ImageTouchSample;component/cat.jpg" 
            VerticalAlignment="Center" HorizontalAlignment="Center" 
            Width="480" Height="480" 
            MinHeight="480" MinWidth="480" 
            MaxHeight="2000" MaxWidth="2000" 
            ManipulationDelta="image1_ManipulationDelta" 
            />
</Grid>

さて、ピンチの処理です。

MainPage.xaml.cs

操作するごとに、ManipulationDelta  イベントが発生します。その中で、ManipulationDelta.Scale の値で、前回との比率を取得できます。なのでそのままそれを使って、それをImageのサイズを変えるだけです。

 private void image1_ManipulationDelta(
  object sender, ManipulationDeltaEventArgs e)
{
    double scale = Math.Max( 
        e.DeltaManipulation.Scale.X,
        e.DeltaManipulation.Scale.Y );
    if (scale != 0)
    {
        image1.Width *= scale;
        image1.Height *= scale;
    }
}

天使な小生意気のさくらさん。拡大縮小も自由自在。

image  image

移動にも対応

拡大縮小ができると、今度は移動もしたくなります。

MainPage.xaml

前回との違いは、位置情報をMarginで管理するために、左上を中心とした座標系にしています。

 <!--LayoutRoot は、すべてのページ コンテンツが配置されるルート グリッドです-->
<Grid x:Name="LayoutRoot" Background="Transparent">
    <Image Name="image1" Stretch="Uniform" 
            Source="/ImageTouchSample;component/cat.jpg" 
            VerticalAlignment="Top" HorizontalAlignment="Left" 
            Height="320" Width="480" 
            MinHeight="320" MinWidth="480" 
            MaxHeight="2000" MaxWidth="2000" 
            ManipulationDelta="image1_ManipulationDelta" 
            Margin="0,240,0,0" />
</Grid>

コード側はこんな感じ。拡大縮小した時に左上が起点になるため、中心起点で拡大縮小するよう、拡大縮小するたびに移動しています。

移動処理も DeltaManipulation.Translation で移動量を取得できるので、Margin を変化させています。Margin は Left だけ、Topだけ、と指定できないのでちょっと面倒。そんなわけで、MoveMargin でまとめちゃいました。

MainPage.xaml.cs

 private void image1_ManipulationDelta(
    object sender, ManipulationDeltaEventArgs e)
{
    double scale = Math.Max( 
        e.DeltaManipulation.Scale.X,
        e.DeltaManipulation.Scale.Y );
    if (scale != 0)
    {
        MoveImage(
            image1.Width * (1 - scale) /2 , 
            image1.Height * (1 - scale) /2);
        image1.Width *= scale;
        image1.Height *= scale;
    }
    MoveImage(
        e.DeltaManipulation.Translation.X, 
        e.DeltaManipulation.Translation.Y);
}
private void MoveImage(double x, double y)
{
    image1.Margin = new Thickness( 
        image1.Margin.Left + x, 
        image1.Margin.Top + y, 0,0 );
}

 

Manipulation のおかげでこの辺の処理はすごく楽になります。