Path Geometry Clipping Equvalent in WinRT

后端 未结 5 495
长情又很酷
长情又很酷 2020-12-05 15:34

Today I started porting the page turn sample created here for Windows Phone 7 to WinRT (XAML, C#) for helping this question posted in Stack Overflow. But during porting I go

5条回答
  •  难免孤独
    2020-12-05 16:37

    I'm a bit late to give a more complete answer, but I got inspired and started working on a reusable control/page transition. The current prototype is working quite nicely with RenderTransforms and Clip Transforms for nice independent animation support.

    enter image description here

    I'll work on that reusable control for WinRT XAML Toolkit, but meanwhile you can check this code:

    XAML

    
    
        
            
                
                    
                        
                            
                                
                                
                            
                        
                    
                
                
                    
                
            
            
                
                    
                        
                            
                                
                                
                            
                        
                    
                
                
                    
                
            
            
                
                    
                        
                    
                    
                        
                            
                                
                                    
                                    
                                
                            
                        
                    
                    
                
            
        
    
    

    C#

    using System;
    using System.Threading.Tasks;
    using Windows.Foundation;
    using Windows.UI.Popups;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media.Animation;
    using Windows.UI.Xaml.Media.Imaging;
    
    namespace FlipControls
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
                PreloadTransitionGridContentAsync();
            }
    
            private async Task PreloadTransitionGridContentAsync()
            {
                #region Waiting for page 2 content to load
                var bi = Page2SampleContentImage.Source as BitmapImage;
    
                if (bi.PixelWidth == 0)
                {
                    bi.ImageFailed += (s, e) => new MessageDialog("Need a different sample image.").ShowAsync();
                    bi.ImageOpened += (s, e) => PreloadTransitionGridContentAsync();
                    return;
                }
    
                if (Page2ContentGrid.ActualWidth == 0)
                {
                    SizeChangedEventHandler sizeChangedEventHandler = null;
                    sizeChangedEventHandler = (s, e) =>
                    {
                        PreloadTransitionGridContentAsync();
                        Page2ContentGrid.SizeChanged -= sizeChangedEventHandler;
                    };
    
                    Page2ContentGrid.SizeChanged += sizeChangedEventHandler;
    
                    return;
                } 
                #endregion
    
                var rtb = new RenderTargetBitmap();
                await rtb.RenderAsync(Page2ContentGrid);
                TransitionImage.Source = rtb;
                await Task.Delay(40000);
            }
    
            private bool isCancellationRequested;
    
            private enum FlipDirections
            {
                Left,
                Right
            }
    
            private FlipDirections flipDirection;
            private Point manipulationStartPosition;
            private double rotationCenterX;
            private double rotationCenterY;
    
            private void ManipulationGrid_OnManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
            {
                if (TransitionImage.Source == null)
                {
                    CancelManipulation(e);
                    return;
                }
    
                manipulationStartPosition = e.Position;
    
                if (Page1.Opacity == 1)
                {
                    flipDirection = FlipDirections.Left;
                    Page2ClipTranslateTransform.X = ManipulationGrid.ActualWidth;
                    Page2.Opacity = 1;
                    TransitionGridClipTranslateTransform.X = -80000;
                    TransitionGridContainerTransform.TranslateX = ManipulationGrid.ActualWidth;
                    TransitionGrid.Opacity = .975;
                }
                else
                {
                    if (manipulationStartPosition.X >= this.ManipulationGrid.ActualWidth / 2)
                    {
                        // Can't flip left since there is no page after the current one
                        CancelManipulation(e);
                        return;
                    }
    
                    flipDirection = FlipDirections.Right;
    
                    Page1.Opacity = 1;
                }
            }
    
            private void ManipulationGrid_OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
            {
                if (this.isCancellationRequested)
                {
                    return;
                }
    
                if (flipDirection == FlipDirections.Left)
                {
                    var w = this.ManipulationGrid.ActualWidth;
                    var h = this.ManipulationGrid.ActualHeight;
    
                    var cx = Math.Min(0, Math.Max(e.Position.X - w, -w));
                    var cy = e.Cumulative.Translation.Y;
                    var angle = (Math.Atan2(cx + manipulationStartPosition.Y - w, -cy) * 180 / Math.PI + +90) % 360;
    
                    this.rotationCenterX = w + cx / 2;
    
                    if (cy < 0)
                    {
                        this.rotationCenterY = h;
                    }
                    else
                    {
                        this.rotationCenterY = 0;
                    }
    
                    Page2ClipTranslateTransform.X = w + cx / 2;
                    Page2ClipTranslateTransform.Y = -40000 + h / 2;
                    Page2ClipRotateTransform.CenterX = this.rotationCenterX;
                    Page2ClipRotateTransform.CenterY = this.rotationCenterY;
                    Page2ClipRotateTransform.Angle = angle;
    
                    TransitionGridClipTranslateTransform.X = -80000 - (cx / 2);
                    TransitionGridClipTranslateTransform.Y = -40000 + h / 2;
                    TransitionGridClipRotateTransform.CenterX = -cx / 2;
                    TransitionGridClipRotateTransform.CenterY = this.rotationCenterY;
                    TransitionGridClipRotateTransform.Angle = -angle;
    
                    TransitionGridContainerTransform.TranslateX = w + cx;
                    TransitionGridContainerTransform.CenterX = -cx / 2;
                    TransitionGridContainerTransform.CenterY = this.rotationCenterY;
                    TransitionGridContainerTransform.Rotation = 2 * angle;
                }
            }
    
            private void ManipulationGrid_OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
            {
                if (this.isCancellationRequested)
                {
                    this.isCancellationRequested = false;
                    return;
                }
    
                var w = this.ManipulationGrid.ActualWidth;
                var h = this.ManipulationGrid.ActualHeight;
    
                var sb = new Storyboard();
                AddAnimation(sb, Page2ClipTranslateTransform, "X", w / 2);
                AddAnimation(sb, Page2ClipRotateTransform, "CenterX", w / 2);
                AddAnimation(sb, Page2ClipRotateTransform, "Angle", 0);
    
                AddAnimation(sb, TransitionGridClipTranslateTransform, "X", -80000 + (w / 2));
                AddAnimation(sb, TransitionGridClipRotateTransform, "CenterX", w / 2);
                AddAnimation(sb, TransitionGridClipRotateTransform, "Angle", 0);
    
                AddAnimation(sb, TransitionGridContainerTransform, "TranslateX", 0);
                AddAnimation(sb, TransitionGridContainerTransform, "CenterX", w / 2);
                AddAnimation(sb, TransitionGridContainerTransform, "Rotation", 0);
                sb.Begin();
            }
    
            private static void AddAnimation(Storyboard sb, DependencyObject dob, string path, double to)
            {
                var da = new DoubleAnimation();
                Storyboard.SetTarget(da, dob);
                Storyboard.SetTargetProperty(da, path);
                da.To = to;
                da.Duration = TimeSpan.FromSeconds(.2);
                sb.Children.Add(da);
            }
    
            private void CancelManipulation(ManipulationStartedRoutedEventArgs e)
            {
                this.isCancellationRequested = true;
                e.Complete();
            }
        }
    }
    

提交回复
热议问题