Ruby 用对虾控制内容流

Ruby 用对虾控制内容流,ruby,prawn,Ruby,Prawn,假设我们想在占据页面上半部分的第一页上显示一个标题。然后,页面的下半部分应填满我们的文章文本,文本应继续流入后续页面,直到用完: 这是一个非常基本的布局场景,但我不明白如何在对虾中实现它 以下是从他们的在线文档中派生的一些示例代码: pdf = Prawn::Document.new do text "The Prince", :align => :center, :size => 48 text "Niccolò Machiavelli", :align => :c

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

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

以下是从他们的在线文档中派生的一些示例代码:

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
pdf=Prawn::Document.new do
文本“王子”,:align=>:center,:size=>48
文本“NiccolòMachiavelli”,:align=>:center,:size=>20
下移42
列框([0,游标],:columns=>3,:width=>bounds.width)do

正文((因此,
column_box
方法创建了一个边界框。有文档记录的边界框行为是,如果它切换到下一页,它从上一页的相同位置开始。因此,您看到的行为基本上是正确的,也不是您想要的。我通过谷歌搜索找到的建议解决方法是使用
 span
,因为span没有这种行为

现在的问题是,如何构建带跨距的文本列?它们似乎不支持本机的跨距。我尝试构建一个模拟带跨距的列的小脚本。它为每列创建一个跨距,并相应地将它们对齐。然后,使用
text\u box
编写文本,该脚本具有
overflow::truncate
选项akes方法返回不适合文本框的文本,以便在下一列中呈现此文本。代码可能需要一些调整,但足以演示如何执行此操作

require 'prawn'

text_to_write = ((<<-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

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

  starting_y = cursor
  starting_page = page_number

  span(bounds.width / 3, position: :left) do
    text_to_write = text_box text_to_write, at: [bounds.left, 0], overflow: :truncate
  end

  go_to_page(starting_page)
  move_cursor_to(starting_y)

  span(bounds.width / 3, position: :center) do
    text_to_write = text_box text_to_write, at: [bounds.left, 0], overflow: :truncate
  end

  go_to_page(starting_page)
  move_cursor_to(starting_y)

  span(bounds.width / 3, position: :right) do
    text_box text_to_write, at: [bounds.left, 0]
  end
end
需要“对虾”
text_to_write=((48
文本“NiccolòMachiavelli”,:align=>:center,:size=>20
下移42
开始_y=光标
起始页=页码
span(bounds.width/3,位置::left)do
text_to_write=文本框text_to_write,位于:[bounds.left,0],溢出::截断
结束
转到页面(起始页面)
将光标移动到(开始)
跨度(bounds.width/3,位置::中心)do
text_to_write=文本框text_to_write,位于:[bounds.left,0],溢出::截断
结束
转到页面(起始页面)
将光标移动到(开始)
span(bounds.width/3,位置::right)do
文本框要写入的文本,位于:[bounds.left,0]
结束
结束

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

使用Prawns grid layout代替。它有很好的文档记录……并且更容易控制布局。

我一直在解决同样的问题。我最终对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

希望它能帮助你。对虾的等级很低,这是一把双刃剑,它有时不能满足你的需要,但有工具可以扩展和构建更复杂的结构。

使用浮体

float do
        span((bounds.width / 3) - 20, :position => :left) do
                # Row Table Code
        end
end

float do
        span((bounds.width / 3) - 20, :position => :center) do
                # Row Table Code
        end
end

float do
        span((bounds.width / 3) - 20, :position => :right) do
                # Row Table Code
        end
end

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

:回流_边距
是一个选项,用于设置列框以在创建新页面时填充其父框

column_box(reflow_margins: true, columns: 3)

我看不出网格对这个布局方案有什么帮助。你能演示一下吗?很抱歉耽搁了…暂时没有互联网。我喜欢使用网格布局,因为你有很好的控制能力。我还没有玩过你的布局,但是,我想在列之间放置“标题”(使用网格)您剩余的内容将在不重复标题区域的情况下流动。@hellion-仍然看不出这有什么帮助。请包含一些示例代码。我使用了网格和浮点数。如果可以,我将使用浮点数代替网格。@mario-我尝试了您的示例,但它只生成了一个页面。这是真的。如果上次调用
文本框
s直到返回剩余文本,我想你必须自己开始一个新页面。如果你打算使用这个解决方案,你可能应该将整个过程包装在一个方法中。正如我所说,这是一个解决方法,而不是解决方案,但我没有找到更好的方法。@mario-好的,谢谢你。我希望Prawn有更好的布局支持,我不会我还创建了一个向列框添加选项标志的请求,但由于他们(慢慢地)尝试发布,而且这是一个功能,而不是一个bug修复,我预计不会很快出现。请参阅以了解另一种方法(需要更多的猴子补丁)。我将不得不尝试一下,看看我是否能让它为我工作,但这似乎是一个正确的方向。感谢您分享您在这方面的经验。非常欢迎您。如果它对您不起作用,请告诉我,因为它可能表明一个潜在的bug最终会咬到我:-)这里有一个错误,如果你在第一页上指定回流列框的高度,它会在以后的页面上保持这个高度,尽管重置了y位置。我正在进行修复,但是欢迎你的建议。你怎么清除一个浮动?就像css中的清除一样:两者都清除
float do
        span((bounds.width / 3) - 20, :position => :left) do
                # Row Table Code
        end
end

float do
        span((bounds.width / 3) - 20, :position => :center) do
                # Row Table Code
        end
end

float do
        span((bounds.width / 3) - 20, :position => :right) do
                # Row Table Code
        end
end
column_box(reflow_margins: true, columns: 3)