是否有针对UWP合成API的非Win2D文本解决方案
为了避免XY问题,首先问Y:有没有办法在SpriteVisual上创建不需要Win2D的文本 现在,我要解决的问题是,我需要SpriteVisual(而不是TextBlock)上的文本来应用透视旋转3D表达式动画。SpriteVisual上的文本可以使用Win2D完成。这里有一个例子: 要在其中为文本着色,需要Win2D笔刷。但是我想在表达式动画中设置颜色的动画,所以我需要文本颜色来自合成笔刷。现在我可以创建一个CompositionMaskBrush,其中文本笔刷作为掩码,CompositionBrush作为源。但使用合成MaskBrush,我无法添加额外的遮罩或任何其他合成效果,这对我来说是个问题是否有针对UWP合成API的非Win2D文本解决方案,uwp,windows-runtime,win2d,Uwp,Windows Runtime,Win2d,为了避免XY问题,首先问Y:有没有办法在SpriteVisual上创建不需要Win2D的文本 现在,我要解决的问题是,我需要SpriteVisual(而不是TextBlock)上的文本来应用透视旋转3D表达式动画。SpriteVisual上的文本可以使用Win2D完成。这里有一个例子: 要在其中为文本着色,需要Win2D笔刷。但是我想在表达式动画中设置颜色的动画,所以我需要文本颜色来自合成笔刷。现在我可以创建一个CompositionMaskBrush,其中文本笔刷作为掩码,Compositio
在我不熟悉的内部构建中,是否有一种替代方法或可能是对合成API的增强?Y-回答:不,您只能使用Win2d
CanvasDrawingSession
在CompositionDrawingSurface
上绘制文本。但是您可以使用ElementCompositionPreview.GetElementVisual(yourTextBlock)
从XAMLTextBlock
获取Visual
,并使用Composition API表达式+XAML彩色故事板对其进行动画制作
X-answer:您可以从文本CompositionDrawingSurface
创建alpha遮罩,并将其应用于CompositionColorBrush
:
private void CreateColoredText(string text)
{
var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, CanvasDevice.GetSharedDevice());
var spriteTextVisual = compositor.CreateSpriteVisual();
spriteTextVisual.Size = new Vector2(512, 512);
var maskDrawingSurface = graphicsDevice.CreateDrawingSurface(new Size(512, 512), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
using (var ds = CanvasComposition.CreateDrawingSession(maskDrawingSurface))
{
ds.Clear(Colors.Transparent);
ds.DrawText(text, new Rect(0, 0, 512, 512), Colors.Lime, new CanvasTextFormat
{
FontSize = 32,
FontWeight = FontWeights.Bold,
VerticalAlignment = CanvasVerticalAlignment.Center,
HorizontalAlignment = CanvasHorizontalAlignment.Center,
LineSpacing = 32
});
}
var maskSurfaceBrush = compositor.CreateSurfaceBrush(maskDrawingSurface);
var surfaceTextBrush = compositor.CreateColorBrush(Colors.DeepPink);
var maskBrush = compositor.CreateMaskBrush();
maskBrush.Mask = maskSurfaceBrush;
maskBrush.Source = surfaceTextBrush;
var colorAnimation = compositor.CreateColorKeyFrameAnimation();
colorAnimation.InsertKeyFrame(0.5f, Colors.DeepSkyBlue);
colorAnimation.InsertKeyFrame(1, Colors.DeepPink);
colorAnimation.Duration = TimeSpan.FromMilliseconds(1500);
colorAnimation.IterationBehavior = AnimationIterationBehavior.Forever;
surfaceTextBrush.StartAnimation("Color", colorAnimation);
spriteTextVisual.Brush = maskBrush;
ElementCompositionPreview.SetElementChildVisual(Grid, spriteTextVisual);
}
现在,您可以为自己的目的设置颜色和透视动画。我需要对其进行处理,但一些可能的问题已经超出了我的想象。TextBlock是否需要添加到可视化树中才能使其可视化工作?VisualElement可以添加到ContainerVersion中吗?很显然,它不能。PlaneProjection动画通过将深度变换应用于ContainerVisual,然后设置子对象(嵌套容器或精灵)旋转的动画来工作。表达式也在容器上,因为有同级的视觉效果,比如文本的背景。新的RedirectVisual可能会有所帮助,但无法在其上找到任何文档。此外,关于合成MaskBrush,我已经提到了这一点,这正是我现在正在做的,但一旦你这样做,你就不能将其嵌套在另一个遮罩中或向其添加其他合成效果(例如饱和或色调旋转)好吧,我错了,编译器允许你向ContainerVisual添加一个元素,但是我从一个文本块中添加了一个元素,其中包含文本,它没有显示任何内容。我一直在尝试这个。TextBlock解决方案不起作用。重定向视觉可以工作,但文本块本身必须添加到XAML视觉树中,并且无论发生什么,它都必须绘制像素。折叠UIElement或设置0不透明度(或甚至0.01不透明度)将使重定向的视觉对象为空。因此,即使您可以将一个元素的视觉效果放在ContainerVisual中,出于所有实际目的,它也不会完成任何事情,而重定向视觉效果也不会工作,除非原始效果也被绘制在屏幕上,这将是一个非常不寻常的用例。
private void CreateColoredText(string text)
{
var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, CanvasDevice.GetSharedDevice());
var spriteTextVisual = compositor.CreateSpriteVisual();
spriteTextVisual.Size = new Vector2(512, 512);
var maskDrawingSurface = graphicsDevice.CreateDrawingSurface(new Size(512, 512), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
using (var ds = CanvasComposition.CreateDrawingSession(maskDrawingSurface))
{
ds.Clear(Colors.Transparent);
ds.DrawText(text, new Rect(0, 0, 512, 512), Colors.Lime, new CanvasTextFormat
{
FontSize = 32,
FontWeight = FontWeights.Bold,
VerticalAlignment = CanvasVerticalAlignment.Center,
HorizontalAlignment = CanvasHorizontalAlignment.Center,
LineSpacing = 32
});
}
var maskSurfaceBrush = compositor.CreateSurfaceBrush(maskDrawingSurface);
var surfaceTextBrush = compositor.CreateColorBrush(Colors.DeepPink);
var maskBrush = compositor.CreateMaskBrush();
maskBrush.Mask = maskSurfaceBrush;
maskBrush.Source = surfaceTextBrush;
var colorAnimation = compositor.CreateColorKeyFrameAnimation();
colorAnimation.InsertKeyFrame(0.5f, Colors.DeepSkyBlue);
colorAnimation.InsertKeyFrame(1, Colors.DeepPink);
colorAnimation.Duration = TimeSpan.FromMilliseconds(1500);
colorAnimation.IterationBehavior = AnimationIterationBehavior.Forever;
surfaceTextBrush.StartAnimation("Color", colorAnimation);
spriteTextVisual.Brush = maskBrush;
ElementCompositionPreview.SetElementChildVisual(Grid, spriteTextVisual);
}