Rails 页面底部的大虾图表没有完全呈现

Rails prawn chart not rendered completely at the bottom of the page

我正在创建一个 pdf 报告,以便使用 "squid" gem 显示一些数据。这将允许我在我的 pdf 中显示图表。 我发现的唯一问题是,当图表不适合页面底部时,它看起来部分呈现,看起来一点也不好。知道我该如何解决这个问题吗?

这是我用来呈现图表的代码

require 'squid'

class SurveyPdf < Prawn::Document
  def initialize(survey, view)
    super()
    font "#{Rails.root}/app/assets/fonts/roboto-condensed.ttf"

    @survey = survey
    @view = view
    questions
  end

  def questions
    @survey.questions.each do |question|
      text "#{question.title}", size: 20
      text "Answers #{question.answers.size}", size: 15
      if ["single", "select"].include? question.question_type.prefix
        if question.answers.choice_counter.any?
          chart choices: question.answers.choice_counter
        end
      end
      if question.question_type.prefix == "image"
        if question.answers.image_counter.any?
          chart images: question.answers.image_counter
        end
      end
      if question.question_type.prefix == "multiple"
        if question.answers.multiple_choice_counter.any?
          chart choices: question.answers.multiple_choice_counter
        end
      end
      if question.question_type.prefix == "raiting"
        move_down 5
        if question.answers.any?
          text_box "Average rating", size: 12, width: 120, :at => [0,  cursor - 2]
          text_box "#{average_rating(question.answers.rating_average)}", size: 12, width: 120, :at => [4 * 30,  cursor - 2]
        else
          text_box "Average rating", size: 12, width: 120, :at => [0,  cursor - 2]
          text_box "0", size: 12, width: 120, :at => [4 * 30,  cursor - 2]
        end
      end
    end
  end
end

对于类似的问题,我使用了 prawn-grouping gem

它会预呈现您放置在 group 块中的任何内容,以测试它是否适合当前页面。如果没有,它会跳到下一页并呈现。

在你的情况下你会做这样的事情:

def questions
  @survey.questions.each do |question|
    group :too_tall => lambda { start_new_page } do |g|
      g.text "#{question.title}", size: 20
      g.text "Answers #{question.answers.size}", size: 15
      if ["single", "select"].include? question.question_type.prefix
        if question.answers.choice_counter.any?
          g.chart choices: question.answers.choice_counter
        end
      end
      if question.question_type.prefix == "image"
        if question.answers.image_counter.any?
          g.chart images: question.answers.image_counter
        end
      end
      if question.question_type.prefix == "multiple"
        if question.answers.multiple_choice_counter.any?
          g.chart choices: question.answers.multiple_choice_counter
        end
      end
      if question.question_type.prefix == "raiting"
        move_down 5
        if question.answers.any?
          g.text_box "Average rating", size: 12, width: 120, :at => [0,  cursor - 2]
          g.text_box "#{average_rating(question.answers.rating_average)}", size: 12, width: 120, :at => [4 * 30,  cursor - 2]
        else
          g.text_box "Average rating", size: 12, width: 120, :at => [0,  cursor - 2]
          g.text_box "0", size: 12, width: 120, :at => [4 * 30,  cursor - 2]
        end
      end
    end
  end
end

免责声明: 我从未使用过 squid 所以我唯一不确定的是 g.chart 让我知道你是否有问题,我会尽力解决。

鱿鱼更新

prawn-grouping gem 不知道 squid 方法(如 chart)。所以我们可以从 prawn-grouping gem 中提取逻辑并将其直接添加到您的 survey_pdf.rb 中。复制 this file 中的第 7-63 行,并从您的应用中删除 prawn-grouping gem。

如果你好奇为什么会这样...

Squid使用Prawn::Document.extensions方法强制Prawn::Document继承squid方法。你可以看到在鱿鱼 gem 代码 here on line 37.

为了使 prawn-grouping 正常工作,它创建了一个新的 Prawn::Document 作为 group 方法的一部分。你可以看到 here on line 55。问题是通过 prawn-grouping gem 实例化的 Prawn::Document 没有继承 squid 方法......但是你的 SurveyPdf 实例 Prawn::Document 确实继承了 squid 方法,因此通过将 grouping 逻辑添加到您的 SurveyPdf class,现在 Prawn::Document 在您的 group 方法中实例化会工作。

为了回答您评论中关于确定页面大小的问题,我将 运行 通过一些有用的方法来回答太长的评论:

d = Prawn::Document.new
d.y #full page height
d.margin_box.bottom #actually top since prawn starts at the bottom
d.margin_box.absolute_bottom #actual top with margins included
d.margin_box.top #usable page height
d.margin_box.absolute_top #same as #y 
d.cursor #where you are vertically on the page

因此您可以使用一些基本数学来确定适合度:

#this is all chart does excepting chart calls #draw 
#which we don't want to do until we determine if it fits 
c = Squid::Graph.new(d, choices: question.answers.choice_counter) 

#determine if the chart will fit vertically 
#if not start a new page and move to the top
unless d.cursor + c.height < d.margin_box.top
   d.start_new_page
   d.move_cursor_to(0)
end

#draw the chart onto the appropriate page
c.draw

希望这在某种程度上有所帮助