首页 > 解决方案 > 使用 wkhtmltopdf 将 D3 图表转换为 pdf

问题描述

我有几个 D3 图表,一个是基本的热图,另一个是甜甜圈图或条形图。使用 wkhtmltopdf 时,饼图、甜甜圈图和条形图都将以 PDF 格式显示,但我的热图不会。我不明白为什么不。

这是一个工作条形图(注意,我通过 Django 模板将数据传递给图表):

        <div id="duelChart"></div>
        <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
        <script>   
                var data = [
                    { "name": "Stat 5", "value": {{ stat.duel_defensive_won|default:0 }}, },
                    { "name": "Stat 4", "value": {{ stat.duel_offensive_won|default:0 }}, },
                    { "name": "Stat 3", "value": {{ stat.aerial_duels_won|default:0 }}, },
                    { "name": "Stat 2", "value": {{ stat.ground_duels_won|default:0 }}, },
                    { "name": "Stat 1", "value": {{ stat.duel_won|default:0 }}, },];

                var margin = { top: 15, right: 25, bottom: 15, left: 60 };           
                var width = 400 - margin.left - margin.right,
                    height = 250 ;
                var svg = d3.select("#duelChart").append("svg")
                    .attr("width", width + margin.left + margin.right)
                    .attr("height", height + margin.top + margin.bottom)
                    .append("g")
                    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

                var x = d3.scale.linear()
                    .range([0, width])
                    .domain([0, d3.max(data, function (d) {
                        return d.value;
                    })]);

                var y = d3.scale.ordinal()
                    .rangeRoundBands([height, 0], .1)
                    .domain(data.map(function (d) {
                        return d.name;
                    }));

                //make y axis to show bar names
                var yAxis = d3.svg.axis()
                    .scale(y)
                    //no tick marks
                    .tickSize(0)
                    .orient("left");

                var gy = svg.append("g")
                    //.attr("class", "y axis")
                    //.call(yAxis)

                var bars = svg.selectAll(".bar")
                    .data(data)
                    .enter()
                    .append("g")

                //append rects
                bars.append("rect")
                    .attr("class", "bar")
                    .attr("y", function (d) {
                        return y(d.name);
                    })
                    .attr("height", y.rangeBand())
                    .attr("x", 0)
                    .attr("width", function (d) {
                        return x(d.value);
                    });

                //add a value label on the left of each bar
                bars.append("text")
                    .attr("class", "label")
                    //y position of the label is halfway down the bar
                    .attr("y", function (d) {
                        return y(d.name) + y.rangeBand() / 2 + 4;
                    })
                    //x position is 3 pixels to the right of the bar
                    //.attr("x", function (d) {
                    //    return x(d.value) + 3;
                    //})
                    .style('fill', 'white')
                    .text(function (d) {
                        return d.name;
                    });

            </script>

这是不工作(简单)的热图:

<div id="heatMap" style="margin-left:12px"></div>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
                    <script>
                        data = [];
                        {% for column in heatmap.gridData %}
                        {% for row in column %}
                        data.push({ "week": {{ forloop.counter0 }} , "day" : {{ forloop.parentloop.counter0 }}, "value": {{ row }} }, );
                        {% endfor %}
                        {% endfor %}
                        var colorDomain = d3.extent(data, function (d) {
                            return d.value;
                        });


                        var colorScale = d3.scale.linear()
                            .domain(colorDomain)
                            .range(["lightblue", "blue"]);

                        var svg = d3.select("#heatMap")
                            .append("svg")
                            .attr("width", 835)
                            .attr("height", 535)                                
                            .append("g")
                            .attr("transform", "translate(" + 0 + "," + 0 + ")");

                        var rectangles = svg.selectAll("rect")
                            .data(data)
                            .enter()
                            .append("g");

                        rectangles
                            .append('rect')
                            .attr("x", function (d) {
                                return d.day * 41;

                            })
                            .attr("y", function (d) {
                                return d.week * 41;
                            })
                            .attr("width", 42)
                            .attr("height", 41).
                            style("fill", function (d) {
                                return colorScale(d.value);
                            });    
                    </script>

此热图完全按照我在浏览器窗口中的预期呈现,但是当我尝试使用 django-wkhtmltopdf 将其发送到 PDF 时,图像不会出现。

请注意<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>实际上是在<head> ... </head>html 文件的顶部,但我包含在本地脚本中以显示我已包含它。这两个图表以及许多其他图表都在同一个 html 页面中。热图是唯一没有在 wkhtmltopdf 中呈现的。

任何帮助解释为什么它不呈现(以及如何修复)将不胜感激

标签: javascriptd3.jswkhtmltopdfdjango-wkhtmltopdf

解决方案


推荐阅读