如何在 UWP 中为 TextBlock 的缩放设置动画

How to animate scale of TextBlock in UWP

当我使用 Storyboard 放大 TextBlock 时,它会在缩放时像素化并仅在完成时重新渲染。

<DoubleAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)">
      <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1.5"/>

有没有办法在每一帧重新渲染 TextBlock?

这似乎是设计使然 - see this answer by Jerry Nixon 在一个非常相似的问题上。

显然这是为了确保动画流畅,因为在每一帧都渲染字体会很昂贵。

你可能克服这个问题的唯一方法是将 TextBlock 包裹在 Viewbox 元素中并缩放 ViewboxHeight 属性 .然而,这不会自动工作,您还必须将 EnableDependentAnimation="True" 添加到 DoubleAnimationUsingKeyFrames 元素。不幸的是,您会发现这种方法还会导致每一帧的布局更新,因此非常不和谐。

我找到了一个解决方案,虽然它不再是关于 TextBlock 的,但对我来说它有效:

    private void CreateText(string text)
    {
        _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
        CreateDevice();

        _spriteTextVisual = _compositor.CreateSpriteVisual();
        _spriteTextVisual.Size = new Vector2(512, 512);

        _drawingTextSurface = _graphicsDevice.CreateDrawingSurface(new Size(512, 512), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);

        using (var ds = CanvasComposition.CreateDrawingSession(_drawingTextSurface))
        {
            ds.Clear(Colors.Transparent);
            ds.DrawText(text, new Rect(0, 0, 512, 512), Colors.Black, new CanvasTextFormat
            {
                FontSize = 32,
                FontWeight = FontWeights.Light,
                VerticalAlignment = CanvasVerticalAlignment.Top,
                HorizontalAlignment = CanvasHorizontalAlignment.Center,
                LineSpacing = 32
            });
        }

        _surfaceTextBrush = _compositor.CreateSurfaceBrush(_drawingTextSurface);

        _spriteTextVisual.Brush = _surfaceTextBrush;

        ElementCompositionPreview.SetElementChildVisual(this, _spriteTextVisual);
    }

    private void CreateDevice()
    {
        _device = CanvasDevice.GetSharedDevice();
        _device.DeviceLost += Device_DeviceLost;

        if (_graphicsDevice == null)
        {
            _graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(_compositor, _device);
        }
        else
        {
            CanvasComposition.SetCanvasDevice(_graphicsDevice, _device);
        }
    }

    private async void Device_DeviceLost(CanvasDevice sender, object args)
    {
        _device.DeviceLost -= Device_DeviceLost;
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, CreateDevice);
    }

只需将此文本设为最大比例即可。