今天我开始将
Windows Phone 7创建的页面转换示例转到WinRT(XAML,C#),以帮助在Stack Overflow中发布的
this问题.但是在移植过程中,我遇到了页面的剪辑部分.在windows手机示例中,他们使用路径几何裁剪来剪裁页面.但在WinRT中似乎只有矩形几何支持裁剪选项.
如何实现类似功能,如WinRT中的路径几何裁剪?
请查找源代码我试过please download
在那里请找到类PageTurn.cs,我评论了代码的问题,在:
void left_PointerEntered(object sender,Windows.UI.Xaml.Input.PointerRoutedEventArgs e) { //_workingOdd.Clip = _oddClipRegion; //_workingEven.Clip = _evenClipRegion; }
我迟到了一个更完整的答案,但我受到启发,并开始进行可重用的控制/页面转换.目前的原型工作与RenderTransforms和Clip Transforms相当不错,可以很好的独立动画支持.
我将为WinRT XAML Toolkit的可重用控件工作,但同时您可以检查此代码:
XAML
<Page x:Class="FlipControls.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:FlipControls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid x:Name="ManipulationGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" ManipulationMode="TranslateX,TranslateY,TranslateInertia" ManipulationStarted="ManipulationGrid_OnManipulationStarted" ManipulationDelta="ManipulationGrid_OnManipulationDelta" ManipulationCompleted="ManipulationGrid_OnManipulationCompleted"> <Grid x:Name="Page1"> <Grid.Clip> <RectangleGeometry Rect="0,80000,80000"> <RectangleGeometry.Transform> <TransformGroup> <TranslateTransform x:Name="Page1ClipTranslateTransform" /> <RotateTransform x:Name="Page1ClipRotateTransform" /> </TransformGroup> </RectangleGeometry.Transform> </RectangleGeometry> </Grid.Clip> <Grid x:Name="Page1ContentGrid"> <Image VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Stretch="UniformToFill" Source="http://bigbackground.com/wp-content/uploads/2013/07/tropical-beach-screensaver.jpg" /> </Grid> </Grid> <Grid x:Name="Page2" Opacity="0"> <Grid.Clip> <RectangleGeometry Rect="0,80000"> <RectangleGeometry.Transform> <TransformGroup> <TranslateTransform x:Name="Page2ClipTranslateTransform" /> <RotateTransform x:Name="Page2ClipRotateTransform" /> </TransformGroup> </RectangleGeometry.Transform> </RectangleGeometry> </Grid.Clip> <Grid x:Name="Page2ContentGrid"> <Image x:Name="Page2SampleContentImage" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Stretch="UniformToFill" Source="http://www.photography-match.com/views/images/gallery/Tropical_Lagoon.jpg" /> </Grid> </Grid> <Grid x:Name="TransitionGridContainer"> <Grid x:Name="TransitionGrid" Opacity="0"> <Grid.RenderTransform> <CompositeTransform x:Name="TransitionGridContainerTransform" /> </Grid.RenderTransform> <Grid.Clip> <RectangleGeometry Rect="0,80000"> <RectangleGeometry.Transform> <TransformGroup> <TranslateTransform x:Name="TransitionGridClipTranslateTransform" /> <RotateTransform x:Name="TransitionGridClipRotateTransform" /> </TransformGroup> </RectangleGeometry.Transform> </RectangleGeometry> </Grid.Clip> <Image x:Name="TransitionImage" Stretch="None" /> </Grid> </Grid> </Grid> </Page>
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","Angle",0); AddAnimation(sb,TransitionGridClipTranslateTransform,-80000 + (w / 2)); AddAnimation(sb,TransitionGridClipRotateTransform,TransitionGridContainerTransform,"TranslateX",0); AddAnimation(sb,"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(); } } }