如何为 blazor 应用程序以像素为单位查找 svg 文本大小?

Kes*_*iam 6 c# svg blazor

我在我们的 blazor 应用程序中使用 svg 元素。因为我在 Svg 中使用文本元素。同时我需要文本元素的高度和宽度(以像素为单位)。基于此,我正在对 SVG 元素进行一些尺寸更改。不幸的是,我不知道如何获取文本元素的大小。

在 ASP.Net 应用程序中,有如下方式,

using System.Drawing;
private float GetWidthOfString(string str)
{
    Bitmap objBitmap = default(Bitmap);
    Graphics objGraphics = default(Graphics);
    objBitmap = new Bitmap(500, 200);
    objGraphics = Graphics.FromImage(objBitmap);
    SizeF stringSize = objGraphics.MeasureString(str, new Font("Arial", 12));
    objBitmap.Dispose();
    objGraphics.Dispose();
    return stringSize.Width;
}
Run Code Online (Sandbox Code Playgroud)

但我不能在 blazor 应用程序中使用它。有没有办法以像素为单位找到文本元素的大小?

Tew*_*ewr 2

在 Blazor 中获取图形信息的最简单方法是使用 DOM。

通过创建临时 svg 元素,使用 javascript 测量文本。

在您的 JavaScript 中,创建以下函数:

window.measureString = function(textParams) {
    const svg = `
    <svg style="position:absolute">
            <text 
             font-family="${textParams.Font}" 
             font-size="${textParams.Size}">
                    ${textParams.Text}
            </text>
    </svg>`;
    const el = document.createElement("div");
    el.innerHTML = svg;
    document.body.appendChild(el);
    const svgText = el.querySelector('text').getBBox();
    el.remove();
    return { Height: svgText.height, Width: svgText.width };
}
Run Code Online (Sandbox Code Playgroud)

...以及与该功能的互操作。

在你的.blazor文件中:

@inject IJsInterop js;

@code {
   
   public class Measurement { public decimal Width { get;set; } public decimal Height { get;set; }}

   Task MeasureString(string text, string font, int size) {
      var measurement = await js.InvokeAsync<Measurement>("measureString", 
          new {
              Text = text,
              Font = font,
              Size = size
          });
      Console.WriteLine($"Width: {measurement.Width} Height: {measurement.Height}";
   }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码是2ms每次调用的平均值。

出于好奇,我还找到了一种使用库对本机 c# 进行(或多或少)相同测量的方法SixLabors.Fonts

以下代码可让您进行测量。字体本身必须首先作为 提供Stream,因此工作量很大。此外,测量不会产生与上面的 js 代码相同的结果,因此可能与 SVG 测量不兼容。我C:\Windows\Fonts\Arial.ttf用作MemoryStream.

using SixLabors.Fonts;

var fontStream = GetFontAsMemoryStream();
var fonts = new FontCollection();    
var font = fonts.Install(fontStream);
var renderOption = new RendererOptions(font.CreateFont(size));
var measurement = TextMeasurer.Measure(text, renderOption);
Run Code Online (Sandbox Code Playgroud)

上面的代码平均为2500ms,所以比 js interop 慢了 1000 多倍。也许可以以某种方式缓存结果fonts.Install(),但我没有立即成功地无例外地重新使用该font实例。