SVG 到 PDF 在 Rails 5.0 中无法正常工作

Posted

技术标签:

【中文标题】SVG 到 PDF 在 Rails 5.0 中无法正常工作【英文标题】:SVG to PDF not working properly in Rails 5.0 【发布时间】:2017-02-11 05:02:35 【问题描述】:

下面的第一张图片是“浏览器视图”,第二张是“PDF 视图”。

SVG 转 PDF 不能正常工作,我正在动态设置 stroke-dashoffset 值并且在浏览器上工作正常,但是当我生成 PDF 时它就不能正常工作。

浏览器视图

PDF 视图

这是我使用的代码:

CSS

.svg circle 
  stroke-dashoffset: 0;
  //transition: stroke-dashoffset 1s linear;
  stroke: #666;
  stroke-width: 1em;

.svg .bar 
  stroke: #33aaa3;

.cont 
  display: block;
  height: 200px;
  width: 200px;
  margin: 2em auto;
  border-radius: 100%;
  position: relative;

.cont:after 
    border-radius: 100%;
    content: attr(data-pct) "%";
    display: block;
    font-size: 2em;
    height: 160px;
    left: 50%;
    line-height: 160px;
    margin-left: -80px;
    margin-top: -80px;
    position: absolute;
    text-align: center;
    top: 50%;
    width: 160px;

.col-xs-3 > p 
    text-align: center;

HTML

<% if @skills.present? %>
            <div class="filter_group skills_area">
                <h2 class="filter_title">SKILLS</h2>
                <div class="panel-body">
                    <div class="row">
                        <% @count = 1 %>
                        <% @skills.each do |skill| %>
                            <div class="col-xs-3 ">
                                <div class="cont" id="cont-<%= @count %>" data-pct="100">
                                    <svg class="svg"    viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
                                      <circle r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0" stroke="#33aaa3"></circle>
                                      <circle class="bar"  r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
                                    </svg>
                                </div>
                                <p><%= skill.title %></p>
                            </div>
                        <% @count += 1 %>
                        <% end %>   
                    </div>
                </div>
            </div>
        <% end %>

jQuery

<% @count = 1 %>
    <% @skills.each do |skill| %>
    <script>
        $(document).ready(function() 
            var val = <%= current_user.profile ? rating_by_skill(current_user.profile.id, skill.id) ?  number_with_precision(rating_by_skill(current_user.profile.id, skill.id), :precision => 2) : 0 : 0 %> * 20;
            var $circle = $('#cont-'+<%= @count %>).find('.svg .bar');

            if (isNaN(val)) 
            val = 0; 
            
            else
            var r = $circle.attr('r');
            var c = Math.PI*(r*2);

            if (val < 0)  val = 0;
            if (val > 100)  val = 100;

            var pct = ((100-val)/100)*c;
            //alert(pct);
            $circle.css( strokeDashoffset: pct);

            $('#cont-'+<%= @count %>).attr('data-pct',val);
            
        );
    </script>
    <% @count += 1 %>
    <% end %>

我正在使用 Rails 5。

【问题讨论】:

如何渲染 PDF? javascript 不会被您用来呈现 PDF 的任何方法执行。 @JasonYost 我正在使用这个 --> pdf = PDFKit.new("#WEBSITE_URL/employee/resume/download?id=#current_user.id", :page_size => ' A3') send_data(pdf.to_pdf) PDFKit 是基于 ruby​​ gem 的 wkhtmltopdf。首先,尝试安装 wkhtmltox 的最新版本 sable。看这里:wkhtmltopdf.org/downloads.html 你试过github.com/mileszs/wicked_pdf 吗?我已将它用于与您的功能几乎相同的功能,但它是浏览器中的画布而不是 SVG。 @JasonYost 嗨,如果 javascript 无法正常工作,那么所有四个圆圈中的值如何正确显示,即 90%、0%、0% 和 0%,它会用 javascript 显示。 【参考方案1】:

也许这可以帮助你https://groups.google.com/forum/#!topic/prawn-ruby/kiiUAV_IFpE

Prawn pdf 对于任何类型的自定义 pdf 生成都非常方便

http://prawnpdf.org/manual.pdf

http://prawnpdf.org/docs/0.11.1/Prawn/Graphics.html

【讨论】:

【参考方案2】:

正如 Jason Yost 已经提到的,PDF 转换器不会执行 JavaScript。我不知道任何执行 JavaScript 的 PDF 转换器,所以我会尝试用已经生成正确 SVG 的服务器端代码替换 JavaScript。

更新:

因此,您的 javascript 的目标是更新第二个圆圈的 strokeDashoffset。 javascript 似乎是通过内联样式来实现的,但它似乎也有一个属性......

<svg class="svg"    viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <circle r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0" stroke="#33aaa3"></circle>
  <circle class="bar"  r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
</svg>

您在&lt;%%&gt; 之间所做的一切都由服务器处理,对于PDF 应该没问题。因此,您需要丢弃 JavaScript 并将您的 SVG 更改为以下内容:

(对不起,我对ruby一无所知,所以把它当作伪代码)

                    <% @count = 1 %>
                    <% @skills.each do |skill| %>
<%
val = current_user.profile ? rating_by_skill(current_user.profile.id, skill.id) ?  number_with_precision(rating_by_skill(current_user.profile.id, skill.id), :precision => 2) : 0 : 0 ;
val = val * 20;

// calculate the percentage the same way as in the javascript...
// and store it in a variable

pct = ((100-val)/100)*c;
%>
                        <div class="col-xs-3 ">
                            <div class="cont" id="cont-<%= @count %>" data-pct="100">
                                <svg class="svg"    viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
                                  <circle r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0" stroke="#33aaa3"></circle>
                                  <circle class="bar"  r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="<%= pct %>"></circle>
                                </svg>
                            </div>
                            <p><%= skill.title %></p>
                        </div>
                    <% @count += 1 %>
                    <% end %>   

如您所见,我添加了一个“ruby”代码块来计算值,然后用计算值替换原来的stroke-dashoffset

由于这只是伪代码,请不要指望它会起作用,但它应该使概念更清晰。随时提出其他问题。

【讨论】:

我的 javascript 无法正常工作,那么所有四个圈子中的值如何正确显示,即 90%、0%、0% 和 0%,它与 javascript 一起显示,我完全糊涂了:(

以上是关于SVG 到 PDF 在 Rails 5.0 中无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3 - 从视图中渲染 PDF 并附加到电子邮件

Rails 5.0 到 5.1 - 一对多关联上的“Cant cast Hash”

使用 SVG 渲染 Pdf 后,文本内容副本无法正常工作

从 Rails 生成 PDF

Rails wikedPDF错误。无法生成PDF

如何在角度2中使用canvg和svg到pdf?