如何拆分一个长字符串,使其与给定的矩形匹配?

How can I split a long string so that it matches with a given rectangle?

我有一个长字符串,我想将它分成几段,以便文本的每一行始终位于给定的矩形中。文本不应超出矩形的边界。

矩形的高度不是问题。文本永远不会触及矩形的底部,因为矩形非常高。但是矩形不是很宽。

如何计算每行应绘制字符串的哪些部分?我不想分开一个字。如果一个单词超出了矩形的边界,那么这个单词应该被绘制在下一行。

例如,绘制字符串应该是这样的:

Cyberpunk 2077 is an upcoming role-playing video game
developed and published by CD Projekt, releasing for
Google Stadia, Microsoft Windows, PlayStation 4, and
...

不是这样的:

Cyberpunk 2077 is an upcoming role-playing video game devel
oped and published by CD Projekt, releasing for Google Stad
ia, Microsoft Windows, PlayStation 4, and Xbox One on 16
...

现在,spriteBatch 正在一行中绘制完整的长字符串,文本超出了矩形的边界。我怎样才能把它正确地分成几行?

Cyberpunk 2077 is an upcoming role-playing video game developed and published by CD Projekt, releasing for Google Stadia, Microsoft Windows, PlayStation 4, and Xbox One on 16 April 2020. Adapted from the 1988 tabletop game Cyberpunk 2020, it is set fifty-seven years later in dystopian Night City, an open world with six distinct regions. In a first-person perspective, players assume the role of the customisable mercenary V, who can reach prominence in hacking, machinery, and combat. V has an arsenal of ranged weapons and options for melee combat.

我用spriteBatch.DrawString画字符串:

string Text = "Cyberpunk 2077 is an upcoming role-playing video game developed and published by CD Projekt, releasing for Google Stadia, Microsoft Windows, PlayStation 4, and Xbox One on 16 April 2020. Adapted from the 1988 tabletop game Cyberpunk 2020, it is set fifty-seven years later in dystopian Night City, an open world with six distinct regions. In a first-person perspective, players assume the role of the customisable mercenary V, who can reach prominence in hacking, machinery, and combat. V has an arsenal of ranged weapons and options for melee combat.";

protected override void Draw(GameTime gameTime)
{                
    graphics.GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.CornflowerBlue);
    spriteBatch.Begin();
    spriteBatch.DrawString(Font, Text, new Vector2(200, 300), Microsoft.Xna.Framework.Color.White, 0, Vector2.Zero, 1f, SpriteEffects.None, 0f);
    spriteBatch.End();

    base.Draw(gameTime);
}

更新: 您需要在最后添加这行代码:

yield return buffer;

    string[] lines = Split(Text, 400, Font).ToArray();

    public static IEnumerable<string> Split(string text, double rectangleWidth, SpriteFont font)
    {
        var words = text.Split(' ');
        string buffer = string.Empty;

        foreach (var word in words)
        {
            var newBuffer = buffer + " " + word;
            if (word == words[0])
              newBuffer = word;
            else
              newBuffer = buffer + " " + word;

            Vector2 FontMeasurements = font.MeasureString(newBuffer);

            if (FontMeasurements.X >= rectangleWidth)
            {
                yield return buffer;
                buffer = word;
            }
            else
            {
                buffer = newBuffer;
            }
        }
        yield return buffer;
    }

绘图:

 for (int i = 0; i <= lines.Count() - 1; i++)
   spriteBatch.DrawString(Font, lines[i], new Vector2(300, 500 + i * 30), Microsoft.Xna.Framework.Color.White, 0, Vector2.Zero, 1f, SpriteEffects.None, 0f);

或:

string boxedText = string.Join('\n', Split(Text, 400, Font));
spriteBatch.DrawString(Font, boxedText, new Vector2(300, 500), Microsoft.Xna.Framework.Color.White, 0, Vector2.Zero, 1f, SpriteEffects.None, 0f);

假设您有一个方法 Measure(string text),其中 returns 文本的实际视觉宽度(如果您使用等宽字体则不需要),您可以使用此方法将文本拆分为多行:

public static IEnumerable<string> Split(string text, double rectangleWidth)
{
    var words = text.Split(' ');
    string buffer = string.Empty;

    foreach (var word in words)
    {
       var newBuffer = buffer + " " + word;

       if (Measure(newBuffer) >= rectangleWidth)
       {
           yield return buffer;
           buffer = word;
       }
       else
       {
           buffer = newBuffer;
       }
    }

    yield return buffer;
}

要将行作为数组获取,请使用 string[] lines = Split(text, Rectangle.Width).ToArray()

如果您想要一个由换行符分隔的字符串,请使用 string boxedText = string.Join('\n', Split(text, Rectangle.Width))

在你的情况下,你会像这样使用它:

string Text = "Cyberpunk 2077 is an upcoming role-playing video game developed and published by CD Projekt, releasing for Google Stadia, Microsoft Windows, PlayStation 4, and Xbox One on 16 April 2020. Adapted from the 1988 tabletop game Cyberpunk 2020, it is set fifty-seven years later in dystopian Night City, an open world with six distinct regions. In a first-person perspective, players assume the role of the customisable mercenary V, who can reach prominence in hacking, machinery, and combat. V has an arsenal of ranged weapons and options for melee combat.";

protected override void Draw(GameTime gameTime)
{                
    graphics.GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.CornflowerBlue);
    spriteBatch.Begin();
    spriteBatch.DrawString(
        Font, 
        string.Join(' ', Split(Text, Rectangle.Width)), 
        new Vector2(200, 300), 
        Microsoft.Xna.Framework.Color.White, 
        0, 
        Vector2.Zero,
        1f,
        SpriteEffects.None,
        0f);
    spriteBatch.End();

    base.Draw(gameTime);
}