在测试UWP表单中,我有一个基本的操作测试,代码如下。它在CanvasControl上绘制3个圆圈,并设置平移和缩放操作。
当我在触摸屏上测试它时,它基本上完成了我的预期,根据屏幕上2个手指的位置来平移和缩放圆圈。但是,如果我捏了一下超过某一点,图像开始在两个范围之间非常快地振荡,并且会很快导致代码因溢出而停止。
我将画布控件放在网格中并尝试从网格控件对画布控件进行操作,虽然缩放和平移的效果看起来不正确,但它不会遇到同样的问题。
所以看起来像我的代码的效果,是一个迭代,其中导致渲染转换更改的操作可能导致另一个操作,并且它进入圆圈直到它结算 - 或者如果存在精度问题,也许是由于触摸点之间的距离太小,迭代会发散直到溢出。
这是预期的吗?这样做的正确方法是什么?
Private WithEvents Canv As New CanvasControl
Private WithEvents gr As New Grid
Private Sub Canv_Draw(sender As CanvasControl, args As CanvasDrawEventArgs) Handles Canv.Draw
args.DrawingSession.DrawCircle(50, 50, 25, Windows.UI.Colors.Blue)
args.DrawingSession.DrawCircle(250, 250, 25, Windows.UI.Colors.Blue)
args.DrawingSession.DrawCircle(500, 500, 25, Windows.UI.Colors.Blue)
End Sub
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Content = gr
gr.Children.Add(Canv)
Canv.ManipulationMode = ManipulationModes.Scale Or ManipulationModes.TranslateX Or ManipulationModes.TranslateY
end sub
Private Sub Canv_ManipulationDelta(sender As Object, e As ManipulationDeltaRoutedEventArgs) Handles Canv.ManipulationDelta
Dim t As New TranslateTransform
t.X = e.Cumulative.Translation.X
t.Y = e.Cumulative.Translation.Y
Dim s As New ScaleTransform
s.ScaleX = e.Cumulative.Scale
s.ScaleY = e.Cumulative.Scale
s.CenterX = e.Position.X
s.CenterY = e.Position.Y
Dim g As New TransformGroup
g.Children.Add(s)
g.Children.Add(t)
Canv.RenderTransform = g
End Sub
答案 0 :(得分:0)
UWP的常用方法是使用CompositeTransform,它支持缩放,偏斜,旋转和翻译。
请参阅BasicInput示例,尤其是the forth scenario
对于缩放问题,您可以通过以下方式避免它:
Public NotInheritable Class MainPage
Inherits Page
Private WithEvents Canv As New CanvasControl
Private WithEvents gr As New Grid
Private Sub Canv_Draw(sender As CanvasControl, args As CanvasDrawEventArgs) Handles Canv.Draw
args.DrawingSession.DrawCircle(50, 50, 25, Windows.UI.Colors.Blue)
args.DrawingSession.DrawCircle(250, 250, 25, Windows.UI.Colors.Blue)
args.DrawingSession.DrawCircle(500, 500, 25, Windows.UI.Colors.Blue)
End Sub
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Content = gr
gr.Children.Add(Canv)
Canv.ManipulationMode = ManipulationModes.Scale Or ManipulationModes.TranslateX Or ManipulationModes.TranslateY
End Sub
Private Sub Canv_ManipulationDelta(sender As Object, e As ManipulationDeltaRoutedEventArgs) Handles Canv.ManipulationDelta
Dim tran = Transform(sender)
tran.ScaleX = tran.ScaleX * e.Delta.Scale
tran.ScaleY = tran.ScaleY * e.Delta.Scale
'System.Diagnostics.Debug.WriteLine("tran.ScaleX =" + tran.ScaleX.ToString() + " tran.ScaleY =" + tran.ScaleY.ToString())
End Sub
Private Function Transform(sender As Object) As CompositeTransform
Dim rect = TryCast(sender, CanvasControl)
rect.RenderTransformOrigin = New Point(0.5, 0.5)
Dim tran As New CompositeTransform
If TryCast(rect.RenderTransform, CompositeTransform) IsNot Nothing Then
tran = DirectCast(rect.RenderTransform, CompositeTransform)
Else
rect.RenderTransform = New CompositeTransform()
End If
Return tran
End Function
' utility method
Private Function Boundary(value As Double, min As Double, max As Double) As Double
If value > max Then
Return max
ElseIf value < min Then
Return min
Else
Return value
End If
End Function
End Class
答案 1 :(得分:0)
其中一些有用的信息,与此同时我发现了一个整洁的解决方案,即将CanvasControl留在网格中,并从网格中获取操作事件并更改Canvas控件的rendertransform,这样就没有了递归。这也意味着自然翻译是不正确的 - 但这很容易通过乘以累积尺度来解决,即。完整的操作代码变为:
Private Sub GerberCanvGrid_ManipulationDelta(sender As Object, e As ManipulationDeltaRoutedEventArgs) Handles GerberCanvGrid.ManipulationDelta
Dim sf As New ScaleTransform
sf.ScaleX = e.Cumulative.Scale
sf.ScaleY = e.Cumulative.Scale
sf.CenterX = e.Position.X
sf.CenterY = e.Position.Y
Dim tt As New TranslateTransform
tt.X = e.Cumulative.Translation.X * e.Cumulative.Scale
tt.Y = e.Cumulative.Translation.Y * e.Cumulative.Scale
ManipulationTransform = New TransformGroup
ManipulationTransform.Children.Add(sf)
ManipulationTransform.Children.Add(tt)
GerberCanv.RenderTransform = ManipulationTransform
End Sub