Управление потоком контента с помощью креветки

Предположим, мы хотим отобразить заголовок на первой странице, которая занимает верхнюю половину страницы. Нижняя половина страницы должна заполнить нашим текстом статьи, и текст должен продолжать перетекать на последующие страницы до тех пор, пока не закончится:

enter image description here

Это довольно простой сценарий макета, но я не понимаю, как его реализовать в 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

но это будет просто показывать пространство заголовков для каждой страницы:

enter image description here

Каков правильный способ сделать это?

Ответ 1

Я боролся с этой же проблемой. Я закончил подклассификацию 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

Затем он вызывается точно так же, как и в поле нормального столбца, но при следующем перерыве страницы будет переходить в ограничивающий прямоугольник родителей. Измените свою линию:

  column_box([0, cursor], :columns => 3, :width => bounds.width) do

к

  reflow_column_box([0, cursor], :columns => 3, :width => bounds.width) do

Надеюсь, это поможет вам. Креветка довольно низкий, это обоюдоострый меч, иногда он не выполняет то, что вам нужно, но инструменты там расширяют и строят более сложные структуры.

Ответ 2

Я знаю, что это старо, но я думал, что поделился бы тем, что добавлен новый параметр, чтобы исправить это в v0.14.0.

:reflow_margins - это опция, которая устанавливает поля столбцов для заполнения своих родительских полей при создании новой страницы.

column_box(reflow_margins: true, columns: 3)

Ответ 3

Таким образом, метод column_box создает ограничивающий прямоугольник. Документированное поведение ограничивающей рамки заключается в том, что она начинается в том же положении, что и на предыдущей странице, если она переходит на следующую страницу. Таким образом, поведение, которое вы видите, в основном правильное, также не то, что вы хотите. Предлагаемое обходное решение, которое я нашел в googling, заключается в том, чтобы вместо этого использовать span, потому что пролеты не имеют такого поведения.

Теперь проблема заключается в том, как создавать текстовые столбцы с пробелами? Похоже, что они не поддерживаются. Я попытался создать небольшой script, который имитирует столбцы с пробелами. Он создает один диапазон для каждого столбца и соответствующим образом выравнивает их. Затем текст записывается с помощью text_box, который имеет параметр overflow: :truncate. Это заставляет метод возвращать текст, который не помещается в текстовое поле, так что этот текст может быть отображен в следующем столбце. Код, вероятно, нуждается в некоторой настройке, но этого должно быть достаточно, чтобы продемонстрировать, как это сделать.

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

Я знаю, что это не идеальное решение. Однако, это было лучшее, что я мог придумать.

Ответ 4

Использовать поплавки.

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

Ответ 5

Вместо этого используйте схему сетки Prawns. Это очень хорошо документировано... и легче контролировать ваш макет.