原文地址:https://wpf.2000things.com/2013/01/25/742-using-touch-manipulation-events-to-rotate-an-element/
在上一篇中,我们使用触摸事件移动控件,我们同样可以用类似的方法来旋转和缩放控件。
这次我们在ManipulationDelta 事件处理函数中同时对控件支持位移、旋转和缩放。事件参数中的ManipulationDelta 实例会提供位移矢量、旋转角度和缩放倍数。
下面是XAML代码:
<Canvas Name="canvMain" Background="Transparent">
<Image Source="JamesII.jpg" Width="100"
IsManipulationEnabled="True"
RenderTransform="{Binding ImageTransform}"
ManipulationStarting="Image_ManipulationStarting" ManipulationDelta="Image_ManipulationDelta"/>
</Canvas>
在ManipulationDelta 事件处理函数中通过矩阵同时处理对控件的位移、旋转和缩放。
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
ImageTransform = new MatrixTransform();
}
private MatrixTransform imageTransform;
public MatrixTransform ImageTransform
{
get { return imageTransform; }
set
{
if (value != imageTransform)
{
imageTransform = value;
RaisePropertyChanged("ImageTransform");
}
}
}
private void Image_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
// Ask for manipulations to be reported relative to the canvas
e.ManipulationContainer = canvMain;
}
private void Image_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
ManipulationDelta md = e.DeltaManipulation;
Vector trans = md.Translation; // 获得位移矢量
double rotate = md.Rotation; // 获得旋转角度
Vector scale = md.Scale; // 获得缩放倍数
Matrix m = imageTransform.Matrix;
// Find center of element and then transform to get current location of center
FrameworkElement fe = e.Source as FrameworkElement;
Point center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
// Update matrix to reflect translation/rotation
m.Translate(trans.X, trans.Y); // 移动
m.RotateAt(rotate, center.X, center.Y); // 旋转
m.ScaleAt(scale.X, scale.Y, center.X, center.Y); // 缩放
imageTransform.Matrix = m;
RaisePropertyChanged("ImageTransform");
e.Handled = true;
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
通过这篇文章和上篇文章,我们可以让控件随手指移动、放大和旋转。但是如果我们仅仅只想控件在水平或者垂直某一个方向上移动,又或者只想控件旋转或者缩放,而没有其他操作,我们可以在ManipulationStarting 事件的处理函数中设置ManipulationStartingEventArgs.Mode 属性来控制控件随手指变换的模式。
ManipulationStartingEventArgs.Mode属性的值是一个ManipulationModes 类型的枚举。枚举成员如下:
- None 所有操作都不会发生
- Rotate 只有旋转操作
- Scale 只有缩放操作
- Translate 仅支持水平和垂直移动
- TranslateX 仅支持水平移动
- TranslateY 仅支持垂直移动
- All 所有操作都支持(移动、缩放和旋转)
默认情况下它的值是All。下面的示例代码中,表示仅支持水平移动。
private void Image_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
// Ask for manipulations to be reported relative to the canvas
e.ManipulationContainer = canvMain;
// 仅支持水平移动
e.Mode = ManipulationModes.TranslateX;
}
如果想要支持其中的多种触摸操作,可以使用于运算符(|)计算然后赋值:
// 支持移动和缩放
e.Mode = ManipulationModes.Translate | ManipulationModes.Scale;