WinRT中如何获取一指触摸总旋转角度?
How to get the total rotation angle by one finger touch in WinRT?
我正在尝试按照Jerry's tutorial进行拨号控制。因为方法 GetAngle
是基于触摸点的位置,所以计算出的角度总是等于或小于 360°。但我需要的是,如果我将结旋转两个半圈,我想得到 900° (360°*2 + 180°)
。
我知道e.Cumulative.Rotation
(e
是ManipulationDeltaRoutedEventArgs
)可以给我总旋转角度,但是好像只能用两根手指触发旋转。
我是不是漏掉了一些简单的解决方案??
我在这上面花了一段时间,结果证明这是一个很好玩的程序 (thanks to Jerry for great blog post)。最后,我得到了一些不同的解决方案 - 下面是一些。
如果你需要计算整个圆圈,那么你需要记住角度从360度变为0的那一刻,并记住有一个完整的圆圈。在我的例子中,我记得最后一个象限,这有助于我处理这个问题。主要代码如下所示:
private Quadrants currentQuadrant = Quadrants.I;
private Quadrants lastQuadrant = Quadrants.I;
private double lastAngle = 0;
public enum Quadrants { I, IV, III, II } // counterclockwise quadrants
private double CheckAngle(Point touchPoint, Size bounds)
{
// find point position relative to bounds
double valX = touchPoint.X - (bounds.Width / 2d);
double valY = (bounds.Height / 2d) - touchPoint.Y;
// determine the quadrant and save it
currentQuadrant = (valX >= 0) ?
(valY >= 0) ? Quadrants.I : Quadrants.IV :
(valY >= 0) ? Quadrants.II : Quadrants.III;
double quadrantAngle = Math.Atan(valX / valY) * (180 / Math.PI); // calculate angle within quadrant
return currentQuadrant == Quadrants.II ? 360 + quadrantAngle :
currentQuadrant != Quadrants.I ? 180 + quadrantAngle : quadrantAngle;
}
private void Grid_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
double currentAngle = CheckAngle(e.Position, this.RenderSize);
if (Math.Abs(lastAngle - currentAngle) < 1) return; // don't update UI always - performance
if (currentQuadrant == Quadrants.I && lastQuadrant == Quadrants.II) // check for full circle
{ spinNumber++; RaiseProperty("SpinNumber"); }
else if ((currentQuadrant > lastQuadrant + 1)) return; // check if proper movement
// update quadrants and Angle
lastQuadrant = currentQuadrant;
Angle = lastAngle = currentAngle;
}
private void Grid_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
// reset all things
Angle = lastAngle = spinNumber =0;
currentQuadrant = lastQuadrant = Quadrants.I;
}
和一些 XAML 部分:
<Grid>
<Grid ManipulationMode="All" ManipulationDelta="Grid_ManipulationDelta" ManipulationCompleted="Grid_ManipulationCompleted">
<Ellipse Width="300" Height="300" Fill="Red"/>
<Path Fill="Green" Data="M 0 0 L 50 0 L 100 150 L 0 150 L 50 0 Z" HorizontalAlignment="Center" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<RotateTransform Angle="{Binding Angle}"/>
</Path.RenderTransform>
</Path>
</Grid>
<TextBlock Text="{Binding AngleTxt}" VerticalAlignment="Bottom" Margin="0,0,0,50" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding SpinNumber}" VerticalAlignment="Bottom" Margin="0,0,0,25" HorizontalAlignment="Center"/>
</Grid>
请注意,如果您从第一象限开始顺时针移动手指,这将起作用。它还需要更多改进,比如处理逆时针移动时的情况,尤其是从 0 度到 360 度的变化。
我正在尝试按照Jerry's tutorial进行拨号控制。因为方法 GetAngle
是基于触摸点的位置,所以计算出的角度总是等于或小于 360°。但我需要的是,如果我将结旋转两个半圈,我想得到 900° (360°*2 + 180°)
。
我知道e.Cumulative.Rotation
(e
是ManipulationDeltaRoutedEventArgs
)可以给我总旋转角度,但是好像只能用两根手指触发旋转。
我是不是漏掉了一些简单的解决方案??
我在这上面花了一段时间,结果证明这是一个很好玩的程序 (thanks to Jerry for great blog post)。最后,我得到了一些不同的解决方案 - 下面是一些。
如果你需要计算整个圆圈,那么你需要记住角度从360度变为0的那一刻,并记住有一个完整的圆圈。在我的例子中,我记得最后一个象限,这有助于我处理这个问题。主要代码如下所示:
private Quadrants currentQuadrant = Quadrants.I;
private Quadrants lastQuadrant = Quadrants.I;
private double lastAngle = 0;
public enum Quadrants { I, IV, III, II } // counterclockwise quadrants
private double CheckAngle(Point touchPoint, Size bounds)
{
// find point position relative to bounds
double valX = touchPoint.X - (bounds.Width / 2d);
double valY = (bounds.Height / 2d) - touchPoint.Y;
// determine the quadrant and save it
currentQuadrant = (valX >= 0) ?
(valY >= 0) ? Quadrants.I : Quadrants.IV :
(valY >= 0) ? Quadrants.II : Quadrants.III;
double quadrantAngle = Math.Atan(valX / valY) * (180 / Math.PI); // calculate angle within quadrant
return currentQuadrant == Quadrants.II ? 360 + quadrantAngle :
currentQuadrant != Quadrants.I ? 180 + quadrantAngle : quadrantAngle;
}
private void Grid_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
double currentAngle = CheckAngle(e.Position, this.RenderSize);
if (Math.Abs(lastAngle - currentAngle) < 1) return; // don't update UI always - performance
if (currentQuadrant == Quadrants.I && lastQuadrant == Quadrants.II) // check for full circle
{ spinNumber++; RaiseProperty("SpinNumber"); }
else if ((currentQuadrant > lastQuadrant + 1)) return; // check if proper movement
// update quadrants and Angle
lastQuadrant = currentQuadrant;
Angle = lastAngle = currentAngle;
}
private void Grid_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
// reset all things
Angle = lastAngle = spinNumber =0;
currentQuadrant = lastQuadrant = Quadrants.I;
}
和一些 XAML 部分:
<Grid>
<Grid ManipulationMode="All" ManipulationDelta="Grid_ManipulationDelta" ManipulationCompleted="Grid_ManipulationCompleted">
<Ellipse Width="300" Height="300" Fill="Red"/>
<Path Fill="Green" Data="M 0 0 L 50 0 L 100 150 L 0 150 L 50 0 Z" HorizontalAlignment="Center" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<RotateTransform Angle="{Binding Angle}"/>
</Path.RenderTransform>
</Path>
</Grid>
<TextBlock Text="{Binding AngleTxt}" VerticalAlignment="Bottom" Margin="0,0,0,50" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding SpinNumber}" VerticalAlignment="Bottom" Margin="0,0,0,25" HorizontalAlignment="Center"/>
</Grid>
请注意,如果您从第一象限开始顺时针移动手指,这将起作用。它还需要更多改进,比如处理逆时针移动时的情况,尤其是从 0 度到 360 度的变化。