3

m trying to replicate a plane projection rotation in UWP using the composition api. But I'm having trouble with a projection matrix in my composition code. Here就是我所拥有的:

private void Perspective(FrameworkElement element, double duration, float rotationDepth = 750f)
{
    var parent = ElementCompositionPreview.GetElementVisual(element.Parent as FrameworkElement);

    var width = (float)element.ActualWidth;
    var height = (float)element.ActualHeight;
    var halfWidth = (float)(width / 2.0);
    var halfHeight = (float)(height / 2.0);

    // Initialize the Compositor
    var visual = ElementCompositionPreview.GetElementVisual(element);

    // Create Scoped batch for animations
    var batch = visual.Compositor.CreateScopedBatch(CompositionBatchTypes.Animation);

    // Rotation animation
    var projectionMatrix = new Matrix4x4(1, 0, 0, 0,
                                            0, 1, 0, 0,
                                            0, 0, 1, 1 / rotationDepth,
                                            0, 0, 0, 1);

    // To ensure that the rotation occurs through the center of the visual rather than the
    // left edge, pre-multiply the rotation matrix with a translation that logically shifts
    // the axis to the point of rotation, then restore the original location
    parent.TransformMatrix = Matrix4x4.CreateTranslation(-halfWidth, -halfHeight, 0) *
                            projectionMatrix *
                            Matrix4x4.CreateTranslation(halfWidth, halfHeight, 0);

    // Rotate along the Y-axis
    visual.RotationAxis = new Vector3(0, 1, 0);
    visual.CenterPoint = new Vector3(halfWidth, halfHeight, 0f);
    visual.RotationAngleInDegrees = 0.0f;

    var rotateAnimation = visual.Compositor.CreateScalarKeyFrameAnimation();

    rotateAnimation.InsertKeyFrame(0.0f, 90);
    rotateAnimation.InsertKeyFrame(1f, 0);
    rotateAnimation.Duration = TimeSpan.FromMilliseconds(duration);

    visual.StartAnimation("RotationAngleInDegrees", rotateAnimation);

    // Batch is ended an no objects can be added
    batch.End();
}

所以上面的这段代码将沿 Y 轴旋转。在下面的 gif 中,您会看到我在另一个由 PlaneProjection 驱动的动画之上制作了动画以进行比较:

在此处输入图像描述

两者的“视角”都很好,都在中间。现在让我们更改这行代码以将其切换为 X 轴上的旋转:

// Rotate along the Y-axis
visual.RotationAxis = new Vector3(0, 1, 0);

现在注意下面的 gif:

在此处输入图像描述

合成动画似乎以更向右而不是完全居中的视角旋转。我的投影矩阵需要改变吗?

4

2 回答 2

1

终于得到了修复,正如这里提到的,通过简单地用容器包装受影响的控件来解决问题:

所以在我的 Xaml 中,我有:

<Border Width="300"
        Height="250"
        Background="LightSeaGreen"
        x:Name="Persp"
        Margin="0,0,0,40">
    <TextBlock Text="Composition"
                FontSize="28"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                FontWeight="Bold"
                Foreground="White" />
</Border>

我改为:

<Border Width="300"
        Height="250">
    <Border Background="LightSeaGreen"
            x:Name="Persp"
            Margin="0,0,0,40">
        <TextBlock Text="Composition"
                    FontSize="28"
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    FontWeight="Bold"
                    Foreground="White" />
    </Border>
</Border>
于 2019-10-10T13:46:09.237 回答
0

快速回答。

yourVisual.Offset = new Vector3((float)Window.Current.Bounds.Width / 2, (float)Window.Current.Bounds.Height / 2, 0);

这会成功的。应用了变换矩阵的 Shift 视觉对象。没有它,您的透视中心位于左上角。

于 2019-09-24T14:29:40.087 回答