使用Prawn控制内容流

Yar*_*rin 13 ruby prawn

假设我们想要在占据页面上半部分的第一页上显示标题.然后页面的下半部分应填写我们的文章文本,文本应继续流入后续页面,直到它用完为止:

在此输入图像描述

这是一个非常基本的布局场景,但我不明白如何在Prawn中实现它.

以下是从在线文档中获取的一些示例代码:

pdf = Prawn::Document.new do
  text "The Prince", :align => :center, :size => 48
  text "Niccolò Machiavelli", :align => :center, :size => 20
  move_down 42

  column_box([0, cursor], :columns => 3, :width => bounds.width) do
  text((<<-END.gsub(/\s+/, ' ') + "\n\n") * 20)
   All the States and Governments by which men are or ever have been ruled,
   have been and are either Republics or Princedoms. Princedoms are either
   hereditary, in which the bla bla bla bla .....
   END
  end
end.render
Run Code Online (Sandbox Code Playgroud)

但这将继续显示每个页面的标题空间:

在此输入图像描述

这样做的正确方法是什么?

Pat*_*ley 10

我一直在与同样的问题作斗争.我最后继承了ColumnBox并添加了一个帮助器来调用它,如下所示:

module Prawn
  class Document

    def reflow_column_box(*args, &block)
      init_column_box(block) do |parent_box|
        map_to_absolute!(args[0])
        @bounding_box = ReflowColumnBox.new(self, parent_box, *args)
      end
    end

    private

    class ReflowColumnBox < ColumnBox 
      def move_past_bottom 
        @current_column = (@current_column + 1) % @columns
        @document.y = @y
        if 0 == @current_column
          @y = @parent.absolute_top
          @document.start_new_page
        end
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

然后它就像普通的列框一样被调用,但是在下一个页面中,break将重排为父项边界框.改变你的行:

  column_box([0, cursor], :columns => 3, :width => bounds.width) do
Run Code Online (Sandbox Code Playgroud)

  reflow_column_box([0, cursor], :columns => 3, :width => bounds.width) do
Run Code Online (Sandbox Code Playgroud)

希望它能帮到你.Prawn相当低级,这是一把双刃剑,它有时候无法满足您的需求,但是工具可以扩展和构建更复杂的结构.


Bay*_*ae' 8

我知道这是旧的,但我想我会分享一个新的选项已被添加来解决这个问题v0.14.0.

:reflow_margins 是一个选项,用于设置列框以在新页面创建时填充其父框.

column_box(reflow_margins: true, columns: 3)
Run Code Online (Sandbox Code Playgroud)


mar*_*rio 2

因此,该column_box方法创建了一个边界框。边界框的记录行为是,如果更改到下一页,它会从与上一页相同的位置开始。所以你看到的行为基本上是正确的,但也不是你想要的。我通过谷歌搜索找到的建议解决方法是使用 aspan代替,因为跨度没有这种行为。

\n\n

现在的问题是,如何构建带跨度的文本列?他们似乎本身并不支持跨度。我尝试构建一个小脚本来模仿具有跨度的列。它为每一列创建一个跨度并相应地对齐它们。然后,用 写入文本text_box,其中有overflow: :truncate选项。这使得该方法返回不适合文本框的文本,以便可以在下一列中呈现该文本。该代码可能需要一些调整,但它应该足以演示如何做到这一点。

\n\n
require \'prawn\'\n\ntext_to_write = ((<<-END.gsub(/\\s+/, \' \') + "\\n\\n") * 20)\n All the States and Governments by which men are or ever have been ruled,\n have been and are either Republics or Princedoms. Princedoms are either\n hereditary, in which the bla bla bla bla .....\n END\n\npdf = Prawn::Document.generate("test.pdf") do\n  text "The Prince", :align => :center, :size => 48\n  text "Niccol\xc3\xb2 Machiavelli", :align => :center, :size => 20\n  move_down 42\n\n  starting_y = cursor\n  starting_page = page_number\n\n  span(bounds.width / 3, position: :left) do\n    text_to_write = text_box text_to_write, at: [bounds.left, 0], overflow: :truncate\n  end\n\n  go_to_page(starting_page)\n  move_cursor_to(starting_y)\n\n  span(bounds.width / 3, position: :center) do\n    text_to_write = text_box text_to_write, at: [bounds.left, 0], overflow: :truncate\n  end\n\n  go_to_page(starting_page)\n  move_cursor_to(starting_y)\n\n  span(bounds.width / 3, position: :right) do\n    text_box text_to_write, at: [bounds.left, 0]\n  end\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

我知道这不是一个理想的解决方案。然而,这是我能想到的最好的办法。

\n