[WP 7.5] 結合Toolkit GestureService 進行圖片裁切
有時候會需要結合Gesture
將裁切框移動以及做出Pinch 來放大縮小裁切框進行裁切
了解一下Windows Phone Toolkit 的Gesture後
以下是我的作法
首先在xaml處引入命名空間,這樣才可以使用Toolkit
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
裁切框以及圖片設置如下,裁切框採用Border才可以設定框線樣式,暫時先以這種方式處理
另外將GestureService.GestureListener置入,並且添加幾個關鍵事件
<Canvas x:Name="CanvasImg" Width="480" Height="720" VerticalAlignment="Top">
<Image x:Name="oriPhoto" Canvas.ZIndex="1" Canvas.Left="0" Canvas.Top="0" Stretch="Fill" Width="480" Height="720"/>
<Border x:Name="BorderCut" Canvas.ZIndex="2" Width="200" Height="200" BorderBrush="Red" BorderThickness="2" Canvas.Left="0" Canvas.Top="0" Background="Green" Opacity="0.3">
<Border.RenderTransform>
<CompositeTransform x:Name="transform"/>
</Border.RenderTransform>
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener
DragDelta="OnDragDelta" DragCompleted="OnDragCompleted"
PinchDelta="OnPinchDelta" PinchCompleted="OnPinchCompleted"/>
</toolkit:GestureService.GestureListener>
</Border>
</Canvas>
外觀設定好了
接下來來設定各個事件
首先先加入裁切框的暫存座標變數x y
private double x;
private double y;
並且在建構式將xy設為0,表示初始裁切框的位置在座標x=0 y=0的地方,這邊是依據xaml的設定,如果有設Canvas.Top 或者 Canvas.Left就要調整一下
public PhotoProc()
{
InitializeComponent();
x = 0;
y = 0;
}
接下來說明移動的事件
OnDragDelta為在手指移動的時候的處理事件,這邊加入裁切框的移動
OnDragCompleted為在手指移動完成要處理的事件,由於BorderCut裁切框放在CanvasImg中,
為了確保座標都可以保持在左上角,所以我就將他們的座標進行處理
private void OnDragDelta(object sender, DragDeltaGestureEventArgs e)
{
transform.TranslateX += e.HorizontalChange;
transform.TranslateY += e.VerticalChange;
}
private void OnDragCompleted(object sender, DragCompletedGestureEventArgs e)
{
Point CanvasP = e.GetPosition(CanvasImg);
Point BorderP = e.GetPosition(BorderCut);
x = CanvasP.X - BorderP.X;
y = CanvasP.Y - BorderP.Y;
}
接下來說明Pinch縮放的事件,這邊我採取固定縮放,並沒有角度的改變。
OnPinchDelta為在手指縮放的時候的處理事件,這邊加入裁切框比例的變化
OnPinchCompleted為在手指縮放完成要處理的事件
private void OnPinchDelta(object sender, PinchGestureEventArgs e)
{
transform.ScaleX = transform.ScaleY = e.DistanceRatio;
}
private void OnPinchCompleted(object sender, PinchGestureEventArgs e)
{
transform.ScaleX = transform.ScaleY = 1;
double change = e.DistanceRatio;
BorderCut.Width *= change;
BorderCut.Height *= change;
}
以下的做法是要將縮放比例回到比例1,讓下一次的縮放不會受到這次的影響
transform.ScaleX = transform.ScaleY = 1;
並且依據改變的比例來實際變換裁切框的大小
最後處理裁切後的圖片儲存將裁切的圖片以WriteableBitmap來作為處理後的物件
因為主要處理正方形裁切結果所以我用RetangleGeometry的方式來進行裁切,所以Size處都設同樣的長度
Canvas tmpCanvas = new Canvas();
BitmapImage bitimg = new BitmapImage();
bitimg.UriSource = new Uri("/Dragon.png", UriKind.Relative);
Image img = new Image();
img.Source = bitimg;
tmpCanvas.Children.Add(img);
tmpCanvas.Width = oriPhoto.Width;
tmpCanvas.Height = oriPhoto.Height;
img.Width = oriPhoto.Width;
img.Height = oriPhoto.Height;
img.Stretch = Stretch.Fill;
RectangleGeometry rectangleGeometry = new RectangleGeometry();
Point point = new Point(x, y);
Size size = new Size(BorderCut.Width, BorderCut.Width);
rectangleGeometry.Rect = new Rect(point,size);
tmpCanvas.Clip = rectangleGeometry;
//加上裁切結果的位置校正,讓圖片可以對齊左上角
TranslateTransform cuttransform = new TranslateTransform();
cuttransform.X = -x;
cuttransform.Y = -y;
TransformGroup transgroup = new TransformGroup();
transgroup.Children.Add(cuttransform);
WriteableBitmap wbitmap = new WriteableBitmap(tmpCanvas, transgroup);
WriteableBitmap bitmap = new WriteableBitmap(tmpCanvas, null);