1

我有一个 uwp xaml 应用程序,在 UI 中有一系列按钮。

我正在使用 Windows 组合可视层 API 为 Button 的视觉对象之一的 RotationAngleInDegrees 设置动画。

按钮的内容在我预期的正面是可见的,但是当视觉对象的背面旋转到视图中时,它也是可见的(尽管反转)。

期望的结果是按钮看起来类似于被翻转的扑克牌,其中内容从正面可见,但在卡片翻转时隐藏。

我尝试了很多事情,包括:

  • 修改按钮模板以将内容演示者嵌套在父边框控件中,认为从后面查看时包含可能会遮挡前面

  • 将 Visual 的 BackfaceVisibility 属性设置为 CompositionBackfaceVisibility.Visible

  • 摆弄按钮背景颜色和视觉效果的不透明度设置

但是,Visual 元素似乎仍然是透明的,并且内容显示在旋转的视觉对象的两个面上。

这是 Windows 组合 API 中的限制还是错误?是否有一种简单的解决方法可以使视觉效果的背面显示的内容与正面显示的内容不同?

以下是生成动画的旋转代码的基础知识:

var btnVisual = ElementCompositionPreview.GetElementVisual(btn);            
var compositor = btnVisual.Compositor;

ScalarKeyFrameAnimation flipAnimation = compositor.CreateScalarKeyFrameAnimation();
flipAnimation.InsertKeyFrame(0.0f, 0);
flipAnimation.InsertKeyFrame(0.0001f, 180);
flipAnimation.InsertKeyFrame(1f, 0);
flipAnimation.Duration = TimeSpan.FromMilliseconds(800);
flipAnimation.IterationBehavior = AnimationIterationBehavior.Count;
flipAnimation.IterationCount = 1;
btnVisual.CenterPoint = new Vector3((float)(0.5 * btn.ActualWidth),(float) (0.5f * btn.ActualHeight), (float)(btn.ActualWidth/4));
btnVisual.RotationAxis = new Vector3(0.0f, 1f, 0f);

btnVisual.StartAnimation(nameof(btnVisual.RotationAngleInDegrees), flipAnimation);

被翻转的按钮是一个默认的 xaml 按钮,最初的样式非常简单:

<Style x:Key="ButtonStyle" TargetType="Button">
    <Setter Property="HorizontalAlignment" Value="Stretch" />
    <Setter Property="VerticalAlignment" Value="Stretch" />
    <Setter Property="Margin" Value="10" />
    <Setter Property="FontSize" Value="80" />
    <Setter Property="FontFamily" Value="Webdings" />
</Style>

我的一项实验涉及修改默认按钮模板以将内容呈现器嵌套在几个边框容器中:

<Style x:Key="ButtonStyle" TargetType="Button">
        <Setter Property="HorizontalAlignment" Value="Stretch" />
        <Setter Property="VerticalAlignment" Value="Stretch" />
        <Setter Property="Margin" Value="10" />
        <Setter Property="FontSize" Value="80" />
        <Setter Property="FontFamily" Value="Webdings" />
        <Setter Property="Background" Value="Silver" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal">
                                    <Storyboard>
                                        <PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="PointerOver">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                               Storyboard.TargetProperty="BorderBrush">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                               Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
                                               Storyboard.TargetProperty="Background">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                               Storyboard.TargetProperty="BorderBrush">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                               Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <PointerDownThemeAnimation Storyboard.TargetName="RootGrid" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
                                               Storyboard.TargetProperty="Background">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                               Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                               Storyboard.TargetProperty="BorderBrush">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledTransparentBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Border Background="Red">
                            <Border Background="#FF62FB0A" Margin="10,10,10,10">
                                <ContentPresenter x:Name="ContentPresenter"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Content="{TemplateBinding Content}"
                                ContentTransitions="{TemplateBinding ContentTransitions}"
                                ContentTemplate="{TemplateBinding ContentTemplate}"
                                Padding="{TemplateBinding Padding}"
                                HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                AutomationProperties.AccessibilityView="Raw"/>
                            </Border>
                        </Border>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

    </Style>

特别是部分修改部分是

<Border Background="Red">
    <Border Background="#FF62FB0A" Margin="10,10,10,10">
        <ContentPresenter x:Name="ContentPresenter"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Content="{TemplateBinding Content}"
                                ContentTransitions="{TemplateBinding ContentTransitions}"
                                ContentTemplate="{TemplateBinding ContentTemplate}"
                                Padding="{TemplateBinding Padding}"
                                HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                AutomationProperties.AccessibilityView="Raw"/>
    </Border>
</Border>

这帮助我确认将按钮内容放在边框容器中并不会阻止视觉在旋转时被看到。

4

1 回答 1

0

我找到了解决方法,但仍然欢迎任何使合成视觉效果尊重它们的包容性的解决方案,因为前面的项目的 3D 可见性没有通过父母的背面显示。

我想出的解决方法是伸手抓住内容视觉,然后对其不透明度进行动画处理,使其仅在旋转的中间标记处可见。我还添加了一个线性缓动,这似乎有助于儿童视觉在正确时间出现的时间。

//Get a visual for the content
var btnContent = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(btn,0),0);
var btnContentVisual = ElementCompositionPreview.GetElementVisual(btnContent as FrameworkElement);  

var easing = compositor.CreateLinearEasingFunction();  

ScalarKeyFrameAnimation appearAnimation = compositor.CreateScalarKeyFrameAnimation();
appearAnimation.InsertKeyFrame(0.0f, 0);
appearAnimation.InsertKeyFrame(0.499999f, 0);
appearAnimation.InsertKeyFrame(0.5f, 1);
appearAnimation.InsertKeyFrame(1f, 1);
appearAnimation.Duration = TimeSpan.FromMilliseconds(800);

btnContentVisual.StartAnimation(nameof(btnContentVisual.Opacity), appearAnimation);

注意:我删除了带有额外边框的自定义模板,这就是为什么上述解决方法只需要使用 VisualTreeHelper 深入挖掘两个级别来获取 contentpresenter 以便我可以检索其视觉效果。

于 2018-12-10T19:51:26.030 回答