有没有办法在UWP中转储表达式动画值?

时间:2019-07-08 05:55:49

标签: animation uwp

我有兴趣转储所有使用的动画表达式值。甚至有可能吗?

假设offsetExpression的值是position的值是什么?

MainPage.xaml

    <ListView x:Name="ListView" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ListView.Header>
            <RelativePanel x:Name="ScrollHeader" Background="#2D2D30">
                <Border
                    RelativePanel.AlignLeftWithPanel="True"
                    x:Name="HeaderLogo"
                    Width="100"
                    Height="100"
                    BorderThickness="10" >
                    <Ellipse Fill="{StaticResource HeaderLogoGradient}" />
                </Border>

                <StackPanel RelativePanel.AlignVerticalCenterWithPanel="True" RelativePanel.RightOf="HeaderLogo">
                    <TextBlock x:Name="HeaderText" FontSize="25" Text="Sticky Header" Foreground="#FFFFFF"/>
                </StackPanel>
            </RelativePanel>
        </ListView.Header>
        <ListView.Items>
            <Rectangle Fill="#DAECF4" Height="200" />
            <Rectangle Fill="#91C5DD" Height="200" />
            <Rectangle Fill="#DAECF4" Height="200" />
            <Rectangle Fill="#91C5DD" Height="200" />
            <Rectangle Fill="#DAECF4" Height="200" />
            <Rectangle Fill="#91C5DD" Height="200" />
            <Rectangle Fill="#DAECF4" Height="200" />
            <Rectangle Fill="#91C5DD" Height="200" />
            <Rectangle Fill="#DAECF4" Height="200" />
            <Rectangle Fill="#91C5DD" Height="200" />
        </ListView.Items>
    </ListView>

MainPage.xaml.cs

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            // Retrieve the ScrollViewer that the GridView is using internally
            var scrollViewer = ListView.GetFirstDescendantOfType<ScrollViewer>();
            CompositionPropertySet scrollerPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer);
            Compositor compositor = scrollerPropertySet.Compositor;

            // Get the visual that represents our HeaderTextBlock 
            // And define the progress animation string
            var headerVisual = ElementCompositionPreview.GetElementVisual(ScrollHeader);
            String progress = "Clamp(Abs(scroller.Translation.Y) / 100.0, 0.0, 1.0)";

            // Create the expression and add in our progress string.
            var textExpression = compositor.CreateExpressionAnimation("Lerp(1.5, 1, " + progress + ")");
            textExpression.SetReferenceParameter("scroller", scrollerPropertySet);

            // Shift the header by 50 pixels when scrolling down
            var offsetExpression = compositor.CreateExpressionAnimation($"(-scroller.Translation.Y - {progress} * 50)");
            offsetExpression.SetReferenceParameter("scroller", scrollerPropertySet);
            headerVisual.StartAnimation("Offset.Y", offsetExpression);

            // Logo scale and transform
            var logoHeaderScaleAnimation = compositor.CreateExpressionAnimation("Lerp(Vector2(1,1), Vector2(0.5, 0.5), " + progress + ")");
            logoHeaderScaleAnimation.SetReferenceParameter("scroller", scrollerPropertySet);

            var logoVisual = ElementCompositionPreview.GetElementVisual(HeaderLogo);
            logoVisual.StartAnimation("Scale.xy", logoHeaderScaleAnimation);

            var logoVisualOffsetAnimation = compositor.CreateExpressionAnimation($"Lerp(0, 50, {progress})");
            logoVisualOffsetAnimation.SetReferenceParameter("scroller", scrollerPropertySet);
            logoVisual.StartAnimation("Offset.Y", logoVisualOffsetAnimation);

            // Offset the header title
            Visual textVisual = ElementCompositionPreview.GetElementVisual(HeaderText);
            Vector3 finalOffset = new Vector3(-45, 22, 0);
            var headerOffsetAnimation = compositor.CreateExpressionAnimation($"Lerp(Vector3(0,0,0), finalOffset, {progress})");
            headerOffsetAnimation.SetReferenceParameter("scroller", scrollerPropertySet);
            headerOffsetAnimation.SetVector3Parameter("finalOffset", finalOffset);
            textVisual.StartAnimation(nameof(Visual.Offset), headerOffsetAnimation);
        }

该示例是对stickyheader的略微修改。我试图消除不必要的动画(或执行其他动画,例如放大),如果您在开始时就拉下ListView会发生这种情况。在此之前,我试图通过转储表达式的值来了解动画的工作方式。

   public static class VisualTreeHelperExtensions
    {
        public static T GetFirstDescendantOfType<T>(this DependencyObject start) where T : DependencyObject
        {
            return start.GetDescendantsOfType<T>().FirstOrDefault();
        }

        public static IEnumerable<T> GetDescendantsOfType<T>(this DependencyObject start) where T : DependencyObject
        {
            return start.GetDescendants().OfType<T>();
        }

        public static IEnumerable<DependencyObject> GetDescendants(this DependencyObject start)
        {
            var queue = new Queue<DependencyObject>();
            var count = VisualTreeHelper.GetChildrenCount(start);

            for (int i = 0; i < count; i++)
            {
                var child = VisualTreeHelper.GetChild(start, i);
                yield return child;
                queue.Enqueue(child);
            }

            while (queue.Count > 0)
            {
                var parent = queue.Dequeue();
                var count2 = VisualTreeHelper.GetChildrenCount(parent);

                for (int i = 0; i < count2; i++)
                {
                    var child = VisualTreeHelper.GetChild(parent, i);
                    yield return child;
                    queue.Enqueue(child);
                }
            }
        }

        public static T GetFirstAncestorOfType<T>(this DependencyObject start) where T : DependencyObject
        {
            return start.GetAncestorsOfType<T>().FirstOrDefault();
        }

        public static IEnumerable<T> GetAncestorsOfType<T>(this DependencyObject start) where T : DependencyObject
        {
            return start.GetAncestors().OfType<T>();
        }

        public static IEnumerable<DependencyObject> GetAncestors(this DependencyObject start)
        {
            var parent = VisualTreeHelper.GetParent(start);

            while (parent != null)
            {
                yield return parent;
                parent = VisualTreeHelper.GetParent(parent);
            }
        }

        public static bool IsInVisualTree(this DependencyObject dob)
        {
            return Window.Current.Content != null && dob.GetAncestors().Contains(Window.Current.Content);
        }

        public static Rect GetBoundingRect(this FrameworkElement dob, FrameworkElement relativeTo = null)
        {
            if (relativeTo == null)
            {
                relativeTo = Window.Current.Content as FrameworkElement;
            }

            if (relativeTo == null)
            {
                throw new InvalidOperationException("Element not in visual tree.");
            }

            if (dob == relativeTo)
                return new Rect(0, 0, relativeTo.ActualWidth, relativeTo.ActualHeight);

            var ancestors = dob.GetAncestors().ToArray();

            if (!ancestors.Contains(relativeTo))
            {
                throw new InvalidOperationException("Element not in visual tree.");
            }

            var pos =
                dob
                    .TransformToVisual(relativeTo)
                    .TransformPoint(new Point());
            var pos2 =
                dob
                    .TransformToVisual(relativeTo)
                    .TransformPoint(
                        new Point(
                            dob.ActualWidth,
                            dob.ActualHeight));

            return new Rect(pos, pos2);
        }
    }
}

0 个答案:

没有答案