将文本和图形集成
了解如何确定呈现的文本字符串的大小,以便将文本与 SkiaSharp 图形集成
本文演示如何测量文本、将文本缩放为特定大小并将文本与其他图形集成:
该图像还包括一个圆角矩形。 SkiaSharp Canvas
类包括用于绘制矩形的 DrawRect
方法,以及用于绘制带圆角的矩形的 DrawRoundRect
方法。 这些方法允许将矩形定义为 SKRect
值或以其他方式定义矩形。
“带框文本”页面会将一个短文本字符串在页面上居中显示,并使用一个由一对圆角矩形组成的框架将其包围。 FramedTextPage
类显示了这是如何实现的。
在 SkiaSharp 中,可以使用 SKPaint
类设置文本和字体属性,但也可以使用该类来获取呈现的文本大小。 以下 PaintSurface
事件处理程序的开头调用了两个不同的 MeasureText
方法。 第一个 MeasureText
调用具有简单的 string
参数,并将根据当前字体属性返回文本的像素宽度。 然后,程序将根据呈现的宽度、当前 TextSize
属性和显示区域的宽度来计算 SKPaint
对象的新 TextSize
属性。 此计算旨在设置 TextSize
,以便以屏幕宽度的 90% 呈现文本字符串:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
string str = "Hello SkiaSharp!";
// Create an SKPaint object to display the text
SKPaint textPaint = new SKPaint
{
Color = SKColors.Chocolate
};
// Adjust TextSize property so text is 90% of screen width
float textWidth = textPaint.MeasureText(str);
textPaint.TextSize = 0.9f * info.Width * textPaint.TextSize / textWidth;
// Find the text bounds
SKRect textBounds = new SKRect();
textPaint.MeasureText(str, ref textBounds);
...
}
第二个 MeasureText
调用具有 SKRect
参数,因此它将同时获取所呈现文本的宽度和高度。 此 SKRect
值的 Height
属性取决于文本字符串中是否存在大写字母、上标和下标。 例如,对于文本字符串“mom”、“cat”和“dog”将会报告不同的 Height
值。
如果文本通过 X 和 Y 位置为 0 的 DrawText
调用显示,SKRect
结构的 Left
和 Top
属性将指示所呈现文本左上角的坐标。 例如,当此程序在 iPhone 7 模拟器上运行时,将为 TextSize
分配值 90.6254,这是在首次调用 MeasureText
后的计算结果。 从对 MeasureText
的第二次调用中获取的 SKRect
值将具有以下属性值:
Left
= 6Top
= –68Width
= 664.8214Height
= 88
请记住,传递给 DrawText
方法的 X 和 Y 坐标指定的是基线处文本的左侧。 Top
值表示文本在该基线之上延伸了 68 个像素,并且在基线之下延伸了 20 个像素(88 减去 68)。 Left
值 6 表示文本从 DrawText
调用中的 X 值右侧六个像素开始。 这允许正常的字符间间距。 如果要在显示器的左上角紧密地显示文本,请将这些 Left
和 Top
值的负值作为 DrawText
的 X 和 Y 坐标传递,在本示例中为 –6 和 68。
SKRect
结构定义了多个方便的属性和方法,其中一些属性和方法将用于 PaintSurface
处理程序的其余部分。 MidX
和 MidY
值表示矩形中心的坐标。 (在 iPhone 7 示例中,这些值为 338.4107 和 –24。)以下代码使用这些值来通过最简单的方式计算将文本居中显示在显示器上的坐标:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
...
// Calculate offsets to center the text on the screen
float xText = info.Width / 2 - textBounds.MidX;
float yText = info.Height / 2 - textBounds.MidY;
// And draw the text
canvas.DrawText(str, xText, yText, textPaint);
...
}
SKImageInfo
信息结构还定义了 SKRect
类型的 Rect
属性,因此还可以按如下所示的方式计算 xText
和 yText
:
float xText = info.Rect.MidX - textBounds.MidX;
float yText = info.Rect.MidY - textBounds.MidY;
PaintSurface
处理程序以两个 DrawRoundRect
调用结束,这两个调用都需要 SKRect
参数。 此 SKRect
值基于从 MeasureText
方法获取的 SKRect
值,但不能与之相同。 首先,它需要稍大一点,这样圆角矩形就不会在文本的边缘上绘制。 其次,它需要在空间中移动,以便 Left
和 Top
值对应于要放置矩形的位置的左上角。 这两个作业由 SKRect
定义的 Offset
和 Inflate
方法完成:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
...
// Create a new SKRect object for the frame around the text
SKRect frameRect = textBounds;
frameRect.Offset(xText, yText);
frameRect.Inflate(10, 10);
// Create an SKPaint object to display the frame
SKPaint framePaint = new SKPaint
{
Style = SKPaintStyle.Stroke,
StrokeWidth = 5,
Color = SKColors.Blue
};
// Draw one frame
canvas.DrawRoundRect(frameRect, 20, 20, framePaint);
// Inflate the frameRect and draw another
frameRect.Inflate(10, 10);
framePaint.Color = SKColors.DarkBlue;
canvas.DrawRoundRect(frameRect, 30, 30, framePaint);
}
接下来,该方法的其余部分是直截了当的。 它为边框创建了另一个 SKPaint
对象,并调用 DrawRoundRect
两次。 第二次调用使用了一个再扩大 10 个像素的矩形。 第一次调用指定了 20 个像素的圆角半径。 第二次指定的圆角半径为 30 个像素,因此两个矩形看起来是平行的:
你可以侧转手机或模拟器,以查看文本和框架的大小增加情况。
如果只需要在屏幕上居中显示一些文本,则可以约莫着执行此操作,而无需测量文本。 相对的,请将 SKPaint
的 TextAlign
属性设置为枚举成员 SKTextAlign.Center
。 然后,你在 DrawText
方法中指定的 X 坐标将指示文本的水平中心的位置。 如果将屏幕的中点传递到 DrawText
方法,文本将水平居中,并且几乎垂直居中,因为基线将垂直居中。
文本可以像任何其他图形对象一样进行处理。 一个简单的选项是显示文本字符的轮廓:
只需将 SKPaint
对象的普通 Style
属性从默认设置 SKPaintStyle.Fill
更改为 SKPaintStyle.Stroke
,并指定笔划宽度即可实现此目的。 “轮廓文本”页面的 PaintSurface
处理程序显示了这是如何实现的:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
string text = "OUTLINE";
// Create an SKPaint object to display the text
SKPaint textPaint = new SKPaint
{
Style = SKPaintStyle.Stroke,
StrokeWidth = 1,
FakeBoldText = true,
Color = SKColors.Blue
};
// Adjust TextSize property so text is 95% of screen width
float textWidth = textPaint.MeasureText(text);
textPaint.TextSize = 0.95f * info.Width * textPaint.TextSize / textWidth;
// Find the text bounds
SKRect textBounds = new SKRect();
textPaint.MeasureText(text, ref textBounds);
// Calculate offsets to center the text on the screen
float xText = info.Width / 2 - textBounds.MidX;
float yText = info.Height / 2 - textBounds.MidY;
// And draw the text
canvas.DrawText(text, xText, yText, textPaint);
}
另一个常见的图形对象是位图。 这个庞大的主题将在 SkiaSharp 位图部分进行深入介绍,但下一篇文章 SkiaSharp 中的位图基础知识对其作了简单介绍。