项目

QuestPDF 文本 (Text)

  • 使用默认或自定义样式绘制文本。
  • Text 元素总是尽可能少地占用空间。
  • 如果文本字符串很长,元素可能会占据整个宽度并换行。
  • 此元素支持分页。

对于大多数不需要复杂格式的情况,简化版的 Text 组件已经足够,如下所示:

.Text("样例文本") .Text("红色大文本").FontColor("#F00").FontSize(24)

当需要在文本字符串中间改变样式、插入页码或包含自定义组件时,可以使用 “文本块” 方法,如下所示:

.Text(text =>
{
    text.Span("这是正常文本,后面跟着一些");
    text.Span("下划线文本。").Underline();
});

演示文本块

基本字体样式

  • 可以使用以下链式 API 方法定义文本样式:
.FontColor("#F00") .FontFamily("Times New Roman")
// 也可以提供备选字体家族
.FontFamily("Times New Roman", "Calibri", "Noto Color Emoji")
.FontSize(24)
.LineHeight(1.5f)
.Italic()
.BackgroundColor(Colors.Grey.Lighten5)
.Strikethrough()
.Underline()
.Subscript()
.Superscript()

区块内的默认文本样式

  • 使用链式 API 方法调整文本位置:
.Text(text => {
    text.DefaultTextStyle(x => x.FontSize(20).BackgroundColor(Colors.Green.Lighten3));
    text.Line("遵循默认样式的文本");
    text.Line("样式更改后的文本").Underline();
});

字体粗细

  • 可以通过以下链式 API 方法轻松设置字体粗细:
.Weight(FontWeight.Normal)
.Thin()
.ExtraLight()
.Light()
.NormalWeight()
.Medium()
.SemiBold()
.Bold()
.ExtraBold()
.Black()
.ExtraBlack()

请注意,并非所有字体都支持所有粗细级别。QuestPDF 会匹配可用的最接近的粗细:

字体粗细

下标和上标

.Text(text => {
    text.DefaultTextStyle(x => x.FontSize(20));
    text.ParagraphSpacing(10);

    var highlight = TextStyle.Default.BackgroundColor(Colors.Green.Lighten3);

    text.Span("E=mc").Style(highlight);
    text.Span("2").Superscript().Style(highlight);
    text.Span("是质量能量等价方程。");

    text.EmptyLine();

    text.Span("H").Style(highlight);
    text.Span("2").Subscript().Style(highlight);
    text.Span("O").Style(highlight);
    text.Span("是水的化学公式。");
});

文本上标与下标

行高

  • 这个设置改变了文本行之间的间距。调整值可以使文本更紧凑或更容易阅读。
.Column(column => {
    var lineHeights = new[] { 0.8f, 1f, 1.5f };
    var paragraph = Placeholders.Paragraph();
    foreach (var lineHeight in lineHeights)
    {
        column
            .Item()
            .Border(1)
            .Padding(10)
            .Text(paragraph)
            .FontSize(16)
            .LineHeight(lineHeight);
    }
});

文本行高

字母间距

  • 字母间距允许您增加或减小字符间的间距。这个设置在想要使文本更紧凑(减小字母间距)或更易读(增大字母间距)时很有用。

  • 值 0 对应于字体定义的正常间距。

  • 正值创建额外的空间。

  • 负值减少字符间的间距。

  • 这个设置使用相对单位。例如,假设您的文本字体大小为 20。如果字母间距设置为 0.1,字符间将添加 2 点额外空间。

.Column(column =>
{
    var letterSpacing = new[] { -0.05f, 0f, 0.2f };
    var paragraph = Placeholders.Sentence();

    foreach (var spacing in letterSpacing)
    {
        column
            .Item()
            .Border(1)
            .Padding(10)
            .Column(nestedColumn =>
            {
                nestedColumn
                    .Item()
                    .Text(paragraph)
                    .FontSize(18)
                    .LetterSpacing(spacing);

                nestedColumn
                    .Item()
                    .Text($"Letter spacing of {spacing} em")
                    .FontSize(14)
                    .Italic()
                    .FontColor(Colors.Blue.Medium);
            });

    }
});

文本字母间距

词间距

  • 词间距允许您增加或减小单词间的间距。与字母间距类似,这个设置用于提高紧凑性或易读性。

  • 值 0 对应于字体定义的正常间距。

  • 正值创建额外的空间。

  • 负值减少字符间的间距。

  • 这个设置使用相对单位。同样,假设您的文本字体大小为 20。如果词间距设置为 0.1,字符间将添加 2 点额外空间。

.Column(column =>
{
    var wordSpacing = new[] { -0.2f, 0f, 0.2f };
    var paragraph = Placeholders.Sentence();

    foreach (var spacing in wordSpacing)
    {
        column
            .Item()
            .Border(1)
            .Padding(10)
            .Column(nestedColumn =>
            {
                nestedColumn.Item()
                    .Text(paragraph)
                    .FontSize(16)
                    .WordSpacing(spacing);

                nestedColumn.Item()
                    .Text($"Word spacing of {spacing} em")
                    .FontSize(10)
                    .Italic()
                    .FontColor(Colors.Blue.Medium);
            });

    }
});

文本词间距

字体样式模式

  • 请考虑以下示例,它描述了文档中所有文本的样式:
public static class Typography
{
    public static TextStyle Title => TextStyle
        .Default
        .FontType("Helvetica")
        .FontColor(Colors.Black)
        .FontSize(20)
        .Bold();

    public static TextStyle Headline => TextStyle
        .Default
        .FontType("Helvetica")
        .FontColor(Colors.Blue.Medium)
        .FontSize(14);

    public static TextStyle Normal => TextStyle
        .Default
        .FontType("Helvetica")
        .FontColor("#000000")
        .FontSize(10)
        .LineHeight(1.25f)
        .AlignLeft();
}

然后,您可以使用预定义的样式:

.Text("带有预定义样式的文本").Style(Typography.Headline);

文本对齐

  • 使用以下链式 API 方法调整文本位置:
.Text(text =>
{
    // pick alignment
    text.AlignLeft();
    text.AlignCenter();
    text.AlignRight();
    text.AlignStart();
    text.AlignEnd();
    text.Justify();

    text.Span("Sample text");
});

您也可以使用简写版本:

.Text("示例文本").Justify();

示例:

var text = Placeholders.Paragraph();
content.Padding(20).Column(column => {
    column.Spacing(20);
    IContainer BlockStyle(IContainer container) => container.Background(Colors.Grey.Lighten3).Padding(10);
    column.Item().Text("左对齐").Bold();
    column.Item().Element(BlockStyle).Text(text).AlignLeft();
    column.Item().Text("居中对齐").Bold();
    column.Item().Element(BlockStyle).Text(text).AlignCenter();
    column.Item().Text("右对齐").Bold();
    column.Item().Element(BlockStyle).Text(text).AlignRight();
    column.Item().Text("首行对齐").Bold();
    column.Item().Element(BlockStyle).Text(text).AlignStart();
    column.Item().Text("末行对齐").Bold();
    column.Item().Element(BlockStyle).Text(text).AlignEnd();
    column.Item().Text("两端对齐").Bold();
    column.Item().Element(BlockStyle).Text(text).Justify();
});

文本对齐

段落间距

  • 段落间距是在文档中添加的文本段落之间以改善可读性和结构的间距。它的目的是视觉上区分段落,使文本更易于导航,更具美感。
.Text(Placeholders.Paragraphs()).ParagraphSpacing(10);

文本段落间距

首行缩进

  • 段落首行缩进是指在段落的第一行缩进指定数量。其目的是视觉上区分新段落的开始,增强文档的可读性和结构。
.Text(Placeholders.Paragraphs()).ParagraphFirstLineIndentation(20);

文本首行缩进

使用省略号限制行数

文本截断与省略号 是一种用于限制块内文本显示行数的技术,通常会删除内容并在末尾添加省略号("..."),以表明当前未显示的更多文本。其目的是管理文本溢出,并保持用户界面布局整洁。\

// 使用简洁Fluent API
.Text(Placeholders.Paragraph())
.ClampLines(3);

// 或使用功能丰富的Fluent API
.Text(text => {
  text.ClampLines(3);
  text.Span("段落:").Bold;
  text.Span(Placeholders.Paragraph());
});

文本截断与省略号

还可以自定义省略号:

.Text(Placeholders.Paragraph())
.ClampLines(3, " [...]");

注入自定义内容

在文本跨度间插入自定义元素 有时需要在文本中插入自定义组件。插入的每个元素都对齐到基线。

.Text(text => {
  text.Span("这是一个对齐到基线的随机图片:");
  text.Element().Height(24).Width(48).Image(Placeholders.Image);
  text.Span(".");
});

对齐到基线的随机图片

通过负填充调整元素位置:

.Text(text => {
  text.DefaultTextStyle(x => x.FontSize(20));
  text.Span("这是一个对齐到基线的随机图片:");
  text.Element()
    .PaddingBottom(-6)
    .Height(24)
    .Width(48)
    .Image(Placeholders.Image);
  text.Span(".");
});

对齐到基线的随机图片

注意:当在文本块中注入自定义元素时,请确保始终限制其大小,否则元素将占用所有可用空间。

页码

文档

使用新的文本元素插入页码数据,如当前页码、文档中的总页数等。

.Text(text => {
  text.CurrentPageNumber();
  text.TotalPages();

  // 可以自定义样式
  text.CurrentPageNumber().Underline();
});

可以获取文档中命名部分的页码数据。

// 在文档中定义节
.Section("customSection")

// 在目录中引用该位置
.Text(text => {
  // 节开始的页码
  text.BeginPageNumberOfSection("customSection");

  // 节结束的页码
  text.EndPageNumberOfSection("customSection");

  // 相对于节开始的页码
  text.PageNumberWithinSection("customSection");

  // 节占用的页数
  text.TotalPagesWithinSection("customSection");
});

格式化

可以使用 Format 方法格式化页码。

.Text(text => {
  // 假设使用罗马数字格式
  text.CurrentPageNumber().Format(FormatAsRomanNumeral);

  static string FormatAsRomanNumeral(int? pageNumber) {
    if (pageNumber == null)
      return "-------";
    // 正确实现
    return "MMXXII";
  }
});

请注意,格式化函数接收 int? 类型。QuestPDF 使用两阶段渲染算法,只有在第二阶段才会知道页码,所以在第一阶段,您的格式化方法会接收到 null 表示页码尚未确定。请返回长度匹配预期输出的任何文本。

节链接

// 在文档中定义节的位置
.Section("customLocationName")

// 创建指向该位置的超链接
.Text(text => {
  text.SectionLink("自定义位置链接", "customLocationName");
});

超链接

.Text(text => {
  text.Hyperlink("请访问 QuestPDF 网站", "https://www.questpdf.com");
});

Unicode 支持

库支持文本造型能力,这对于生成具有高级 Unicode 功能的文本非常有用:

.Padding(35)
.MinimalBox()
.BackgroundImage(Colors.Grey.Lighten2)
.Text(text => {
  text.DefaultTextStyle(TextStyle.Default.FontSize(20));

  text.Span("复杂的Unicode结构:");
  text.Span("T̶̖̔͆͆̽̔ḩ̷̼̫̐̈́̀͜͝͝ì̶͇̤͓̱̣͇͓͉̎s̵̡̟̹͍̜͉̗̾͛̈̐́͋͂͝͠ͅ ̴̨͙͍͇̭̒͗̀́͝ì̷̡̺͉̼̏̏̉̌͝s̷͍͙̗̰̖͙̈̑̂̔͑͊̌̓̊̇͜ ̶̛̼͚͊̅͘ṭ̷̨̘̣̙̖͉͌̏̂̅͑̄̽̕͝ȅ̶̲̲̙̭͈̬̣͔̝͔̈́͝s̸̢̯̪̫͓̭̮̓̀͆͜ț̸̢͉̞̥̤̏̌̓͝")
  .FontFamily(Fonts.Calibri)
  .FontColor(Colors.Red.Medium);

  text.Span(".");
});

unicode 文本支持

高级语言支持

文本造型能力还为以下更高级别的语言提供了基础支持:

  1. 多个文本字符作为单个 glyph 显示。
  2. 使用从右到左脚本显示。
var text = "في المعلوماتية أو الرياضيات، خوارزمية الترتيب هي خوارزمية تمكن من تنظيم مجموعة عناصر حسب ترتيب محدد.";
.Column(column => {
  column.Spacing(10);
  column.Text(text, Fonts.Calibri, 22);
  column.ContentFromRightToLeft();
});

高级语言支持

字体替代

每个字体文件包含一套明确指定的 glyph。有时为了减小字体文件大小,高级别的 glyph 可能不存在。例如,英文大约使用 100 个字符,而中文则需要数千个 glyph。因此,文档中的文本可能包含字体中没有的 glyph,此时会显示一个丑陋的字符(通常是带有问号的方框)。

您可以在 TextStyle 对象中定义字体替代:

TextStyle
  .Default
  .FontFamily(Fonts.Calibri, "Segoe UI Emoji");

字体替代

处理分页文本

Text 元素支持分页。这意味着如果当前页面空间不足,部分文本可能会移动到下一页。下面是一些简化文本处理流程的方法。

要确保文本永不分页,始终完全显示在单页上,请使用 ShowEntire 元素:

.ShowEntire()
.Text("这里有一个长文本,不会被分页。");

有时页面空间非常有限,只需显示几行,但如此短的文本块可能看起来不协调。在这种情况下,最好将文本块移到下一页,而不是尝试换行。请调整 EnsureSpace 元素的最小高度,使其符合页面末尾希望显示的最小空间。

.EnsureSpace(50)
.Text("这里是一个长文本。");

强制文本方向(从右到左)

QuestPDF 会自动检测文本方向并应用适当的文本对齐方式。但是,可以覆盖文本方向。

TextStyle.Default.DirectionAuto() // 默认
TextStyle.Default.DirectionFromLeftToRight()
TextStyle.Default.DirectionFromRightToLeft()

这在更复杂的情况下可能有用:

.DefaultTextStyle(x => x.FontSize(24).FontFamily("Calibri"))
.Column(column => {
  column.Spacing(10);

  var word = "الجوريتم";
  var definition = "阿拉伯语中的算法";

  var text = $"{word} - {definition}";

  // 使用第一个词自动检测文本方向
  column.Item().Text(text);

  // 强制特定内容方向
  column.Item().Text(text).DirectionFromLeftToRight();
  column.Item().Text(text).DirectionFromRightToLeft();

  // 结合不同内容方向的文本
  column.Item().Text(text => {
    text.Span(word);
    text.Span(" - ");
    text.Span(definition);
  });
});

强制文本方向(从右到左)

在本文档中