代码之家  ›  专栏  ›  技术社区  ›  Sean O'Neil

故事板动画UIElement.平面投影完全使用合成API时损坏

uwp
  •  0
  • Sean O'Neil  · 技术社区  · 7 年前

    我正在使用合成API来制作各种动画和效果。我也在尝试合并 3D perspective effect 在相同的元素上。不幸的是,使用合成API重新创建3D透视效果的唯一方法是使用Visual.TransformMatrix财产 can't be animated AFAIK

    然后我意识到这种坏行为只会发生在埃莱姆身上ntCompositionPreview.GetElementVisual已对UIElement调用。即使我不改变任何视觉效果的属性或者对它做任何事情,简单地调用它,就不可能使用目标为的故事板动画UIElement.平面投影如果你不想让它在完成后重置。

    复制和粘贴下面的代码在一个新的UWP项目目标1809或1803将提供一个完整的复制项目。

    主页.xaml

    <Page
        x:Class="PlaneProjectionStoryboardBugRepro.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Background="Transparent">
    
        <Grid x:Name="LayoutRoot">
            <TextBlock x:Name="StandardText" Visibility="Visible" Foreground="DarkGreen" HorizontalAlignment="Center" TextAlignment="Center" VerticalAlignment="Top" Margin="100" FontSize="24">
                Press the rotate button several times<LineBreak/>
                Notice Storyboard that is rotating the plane projection about Y axis is working properly.<LineBreak/>
                Now try it after pressing the second button.
            </TextBlock>
            <TextBlock x:Name="WarningText" Visibility="Collapsed" Foreground="DarkRed" HorizontalAlignment="Center" TextAlignment="Center" VerticalAlignment="Top" Margin="100" FontSize="24">
                Composition API has been invoked.<LineBreak/>
                Notice that now the rotation Storyboard animation's FillBehavior is broken.<LineBreak/>
                Simply from calling 'ElementCompositionPreview.GetElementVisual'
            </TextBlock>
            <Image x:Name="Logo" Source="Assets\StoreLogo.png"  Height="500" Width="500" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="30">
                <Button Content="Rotate Logo" Margin="12" HorizontalAlignment="Center" Click="Button_Click"/>
                <Button Content="Call 'GetElementVisual' On Logo" Margin="12" HorizontalAlignment="Center" Click="Button_Click_2"/>
                <Button Content="Reset" HorizontalAlignment="Center" Margin="12" Click="Button_Click_3"/>
            </StackPanel>
        </Grid>
    </Page>
    

    主页.xaml.cs

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices.WindowsRuntime;
    using Windows.ApplicationModel.Core;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Hosting;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Media.Animation;
    using Windows.UI.Xaml.Navigation;
    
    namespace PlaneProjectionStoryboardBugRepro
    {
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.Loaded += MainPage_Loaded;
                this.InitializeComponent();
            }
    
            void MainPage_Loaded(object sender, RoutedEventArgs e)
            {
                var pp = new PlaneProjection();
                Logo.Projection = pp;
            }
    
            double EndAngle = 0;
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                EndAngle = (EndAngle == 0) ? 45 : 0;
                var storyboard = new Storyboard();
                var animation = new DoubleAnimation();
                animation.Duration = TimeSpan.FromMilliseconds(500);
                animation.To = EndAngle;
                Storyboard.SetTarget(animation, Logo);
                Storyboard.SetTargetProperty(animation, "(UIElement.Projection).(PlaneProjection.RotationY)");
                storyboard.Children.Add(animation);
                storyboard.Begin();
            }
    
            private void Button_Click_2(object sender, RoutedEventArgs e)
            {
                // Simply instantiating a Visual object of the UIElement breaks the Storyboard.
                var visual = ElementCompositionPreview.GetElementVisual(Logo);
    
                StandardText.Visibility = Visibility.Collapsed;
                WarningText.Visibility = Visibility.Visible;
            }
    
            async void Button_Click_3(object sender, RoutedEventArgs e)
            {
                await CoreApplication.RequestRestartAsync("");
            }
        }
    }
    
    0 回复  |  直到 7 年前
    推荐文章