2016-07-04 1 views
0

В тестовой форме UWP у меня есть базовый мануальный тест, код ниже. Он рисует 3 круга на CanvasControl и настраивает манипуляции с переводом и масштабированием.Реагирование на дельту манипуляции - странный эффект и переполнение

Когда я тестирую это на сенсорном экране, он в основном выполняет то, что я ожидаю, перевод и масштабирование кругов на основе положения двух пальцев на экране. Но если я ущемляюсь выше определенной точки, изображение начинает очень быстро колебаться между двумя экстентами и очень быстро заставляет код останавливаться с переполнением.

Я положил элемент управления холста в сетку и попытался сделать манипуляцию с элементом управления холстом из элемента управления сеткой, и он не страдает от той же проблемы, хотя эффект масштабирования и панорамирования не кажется правильным.

Таким образом, это похоже на эффект моего кода как есть, это итерация, когда манипуляция, вызывающая изменение визуального преобразования, может вызвать другую манипуляцию, и она идет кругами до тех пор, пока она не опустится - или если есть проблема точности , возможно, из-за того, что расстояние между точками касания становится слишком маленьким, итерация расходится до переполнения.

Ожидается ли это? Каков правильный способ сделать это?

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

Распространенным способом в UWP является использование CompositeTransform, он поддерживает Scale, Skew, Повернуть и Перевести.

Пожалуйста, смотрите пример 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 

Скриншот: Gif

0

Некоторые полезные информация в том, что тем временем я нашел опрятное решение, которое должно было оставить CanvasControl в сетке и взять манипуляции события из сетки и изменить rendertransform элемента Canvas, таким образом, нет рекурсии. Это также означает, что естественный перевод неверен, но его легко исправить, умножив его на совокупный масштаб, т.е. полный код обработки становится:

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