如何在django网站上将D3图表保存为图像?

时间:2016-05-10 08:03:15

标签: javascript html django d3.js svg

我是Django和D3的新手。我创建了一个可以创建多个动态d3图形的Django网站。我想添加一个功能,用户可以将图形保存为图像,以便他们可以将其用于报告目的。

我使用以下链接tutorials 还可以找到我的参考代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>D3: A starting point for interactivity</title>
    <script type="text/javascript" src="../d3/d3.v3.js"></script>
<style type="text/css">

    .graph1 {
          float : left ; 
          height : 400px; 
          width : 600px; 
          font: 20px sans-serif;
          text-align: left;
          margin-left  : 20px; 
         border : 1px solid black;
}


.graph2 {
     float : right ; 
     margin-right : 20px ;
    width : 600px;
    height : 400px;
    border : 1px solid black;
    overflow: scroll;
    border : 1px solid black;
    }


.button1{
    float :left ; 
 }

.button2{
    float :right  ; 
}       
</style>
</head>
<body>

<div id="area1" class="graph1"></div>
<div id="area2" class="graph2"></div>
<button id="save" class="button1">Save as Image</button>
<canvas id="canvas1" width="960" height="500" style="display:none">   </canvas>
<button id="save1" class="button2">Save as Image</button>
<canvas id="canvas2" width="960" height="500" style="display:none"></canvas>
<script type="text/javascript">

        //Width and height
        var w = 600;
        var h = 400;

        var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
                        11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];

        var xScale = d3.scale.ordinal()
                        .domain(d3.range(dataset.length))
                        .rangeRoundBands([0, w], 0.05);

        var yScale = d3.scale.linear()
                        .domain([0, d3.max(dataset)])
                        .range([0, h]);

        //Create SVG element
        var svg1 = d3.select("#area1")
                    .append("svg")
                    .attr("width", w)
                    .attr("height", h);

        //Create bars
        svg1.selectAll("rect")
           .data(dataset)
           .enter()
           .append("rect")
           .attr("x", function(d, i) {
                return xScale(i);
           })
           .attr("y", function(d) {
                return h - yScale(d);
           })
           .attr("width", xScale.rangeBand())
           .attr("height", function(d) {
                return yScale(d);
           })
           .attr("fill", function(d) {
                return "rgb(0, 0, " + (d * 10) + ")";
           });

        //Create labels
        svg1.selectAll("text")
           .data(dataset)
           .enter()
           .append("text")
           .text(function(d) {
                return d;
           })
           .attr("text-anchor", "middle")
           .attr("x", function(d, i) {
                return xScale(i) + xScale.rangeBand() / 2;
           })
           .attr("y", function(d) {
                return h - yScale(d) + 14;
           })
           .attr("font-family", "sans-serif")
           .attr("font-size", "11px")
           .attr("fill", "white");

d3.select("#save").on("click", function(){
    var html = d3.select("svg")
        .attr("version", 1.1)
        .attr("xmlns", "http://www.w3.org/2000/svg")
        .node().parentNode.innerHTML;

 //console.log(html);
var imgsrc = 'data:image/svg+xml;base64,'+ btoa(html);
var img = '<img src="'+imgsrc+'">'; 

//d3.select("#svgdataurl").html(img);
var canvas = document.getElementById("canvas1"),
context = canvas.getContext("2d");

var image = new Image;
image.src = imgsrc;
image.onload = function() {
    context.drawImage(image, 0, 0);

    var canvasdata = canvas.toDataURL("image/png");

    var pngimg = '<img src="'+canvasdata+'">'; 
    //d3.select("#pngdataurl").html(pngimg);

    var a = document.createElement("a");
    a.download = "sample1.png";
    a.href = canvasdata;
        document.body.appendChild(a);
    a.click();
};

});
//pie chart 

        //Width and height
        var w = 380;
        var h = 380;

        var dataset = [ 5, 10, 20, 45, 6, 25 ];

        var outerRadius = w / 2;
        var innerRadius = 0;
        var arc = d3.svg.arc()
                        .innerRadius(innerRadius)
                        .outerRadius(outerRadius);

        var pie = d3.layout.pie();

        //Easy colors accessible via a 10-step ordinal scale
        var color = d3.scale.category10();

        //Create SVG element
        var svg = d3.select("#area2")
                    .append("svg")
                    .attr("width", w)
                    .attr("height", h);

        //Set up groups
        var arcs = svg.selectAll("g.arc")
                      .data(pie(dataset))
                      .enter()
                      .append("g")
                      .attr("class", "arc")
                      .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");

        //Draw arc paths
        arcs.append("path")
            .attr("fill", function(d, i) {
                return color(i);
            })
            .attr("d", arc);

        //Labels
        arcs.append("text")
            .attr("transform", function(d) {
                return "translate(" + arc.centroid(d) + ")";
            })
            .attr("text-anchor", "middle")
            .text(function(d) {
                return d.value;
            });

d3.select("#save1").on("click", function(){
var html = d3.select("svg")
    .attr("version", 1.1)
    .attr("xmlns", "http://www.w3.org/2000/svg")
    .node().parentNode.innerHTML;

//console.log(html);
var imgsrc = 'data:image/svg+xml;base64,'+ btoa(html);
var img = '<img src="'+imgsrc+'">'; 

//d3.select("#svgdataurl").html(img);
var canvas = document.getElementById("canvas2"),
context = canvas.getContext("2d");

var image = new Image;
image.src = imgsrc;
image.onload = function() {
    context.drawImage(image, 0, 0);

    var canvasdata = canvas.toDataURL("image/png");

    var pngimg = '<img src="'+canvasdata+'">'; 
    //d3.select("#pngdataurl").html(pngimg);

    var a = document.createElement("a");
    a.download = "sample2.png";
    a.href = canvasdata;
        document.body.appendChild(a);
    a.click();
};

});


    </script>
</body>

从保存为按钮,我只能保存第一张图像。我想我无法正确选择d3 / svg元素。

谢谢

1 个答案:

答案 0 :(得分:2)

在你的d3.select("#save1").on("click"中,你的svg选择器是错误的。这样:

 var html = d3.select("svg")
   ...

将始终在页面上选择第一个 svg元素。你需要这样的东西:

var html = d3.select("#area2>svg")
  ...

这将选择svg的{​​{1}},其div的孩子为id2。

完整代码:

<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="utf-8" />
    <title>D3: A starting point for interactivity</title>
    <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>

    <style type="text/css">

    .graph1 {
          float : left ; 
          height : 400px; 
          width : 600px; 
          font: 20px sans-serif;
          text-align: left;
          margin-left  : 20px; 
         border : 1px solid black;
}


.graph2 {
     float : right ; 
     margin-right : 20px ;
    width : 600px;
    height : 400px;
    border : 1px solid black;
    overflow: scroll;
    border : 1px solid black;
    }


.button1{
    float :left ; 
 }

.button2{
    float :right  ; 
}       
    </style>
  </head>

  <body>
    <div id="area1" class="graph1"></div>
    <div id="area2" class="graph2"></div>
    <button id="save" class="button1">Save as Image</button>
    <canvas id="canvas1" width="960" height="500" style="display:none"></canvas>
    <button id="save1" class="button2">Save as Image</button>
    <canvas id="canvas2" width="960" height="500" style="display:none"></canvas>
    <script type="text/javascript">

        //Width and height
        var w = 600;
        var h = 400;

        var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
                        11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];

        var xScale = d3.scale.ordinal()
                        .domain(d3.range(dataset.length))
                        .rangeRoundBands([0, w], 0.05);

        var yScale = d3.scale.linear()
                        .domain([0, d3.max(dataset)])
                        .range([0, h]);

        //Create SVG element
        var svg1 = d3.select("#area1")
                    .append("svg")
                    .attr("width", w)
                    .attr("height", h);

        //Create bars
        svg1.selectAll("rect")
           .data(dataset)
           .enter()
           .append("rect")
           .attr("x", function(d, i) {
                return xScale(i);
           })
           .attr("y", function(d) {
                return h - yScale(d);
           })
           .attr("width", xScale.rangeBand())
           .attr("height", function(d) {
                return yScale(d);
           })
           .attr("fill", function(d) {
                return "rgb(0, 0, " + (d * 10) + ")";
           });

        //Create labels
        svg1.selectAll("text")
           .data(dataset)
           .enter()
           .append("text")
           .text(function(d) {
                return d;
           })
           .attr("text-anchor", "middle")
           .attr("x", function(d, i) {
                return xScale(i) + xScale.rangeBand() / 2;
           })
           .attr("y", function(d) {
                return h - yScale(d) + 14;
           })
           .attr("font-family", "sans-serif")
           .attr("font-size", "11px")
           .attr("fill", "white");

d3.select("#save").on("click", function(){
    var html = d3.select("svg")
        .attr("version", 1.1)
        .attr("xmlns", "http://www.w3.org/2000/svg")
        .node().parentNode.innerHTML;

 //console.log(html);
var imgsrc = 'data:image/svg+xml;base64,'+ btoa(html);
var img = '<img src="'+imgsrc+'">'; 

//d3.select("#svgdataurl").html(img);
var canvas = document.getElementById("canvas1"),
context = canvas.getContext("2d");
context.strokeStyle = "black";
context.rect(0,0,w,h);
context.fill();

var image = new Image;
image.src = imgsrc;
image.onload = function() {
    context.drawImage(image, 0, 0);

    var canvasdata = canvas.toDataURL("image/png");

    var pngimg = '<img src="'+canvasdata+'">'; 
    //d3.select("#pngdataurl").html(pngimg);

    var a = document.createElement("a");
    a.download = "sample1.png";
    a.href = canvasdata;
        document.body.appendChild(a);
    a.click();
};

});
//pie chart 

        //Width and height
        var w = 380;
        var h = 380;

        var dataset = [ 5, 10, 20, 45, 6, 25 ];

        var outerRadius = w / 2;
        var innerRadius = 0;
        var arc = d3.svg.arc()
                        .innerRadius(innerRadius)
                        .outerRadius(outerRadius);

        var pie = d3.layout.pie();

        //Easy colors accessible via a 10-step ordinal scale
        var color = d3.scale.category10();

        //Create SVG element
        var svg = d3.select("#area2")
                    .append("svg")
                    .attr("width", w)
                    .attr("height", h);

        //Set up groups
        var arcs = svg.selectAll("g.arc")
                      .data(pie(dataset))
                      .enter()
                      .append("g")
                      .attr("class", "arc")
                      .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");

        //Draw arc paths
        arcs.append("path")
            .attr("fill", function(d, i) {
                return color(i);
            })
            .attr("d", arc);

        //Labels
        arcs.append("text")
            .attr("transform", function(d) {
                return "translate(" + arc.centroid(d) + ")";
            })
            .attr("text-anchor", "middle")
            .text(function(d) {
                return d.value;
            });

d3.select("#save1").on("click", function(){
var html = d3.select("#area2>svg")
    .attr("version", 1.1)
    .attr("xmlns", "http://www.w3.org/2000/svg")
    .node().parentNode.innerHTML;

//console.log(html);
var imgsrc = 'data:image/svg+xml;base64,'+ btoa(html);
var img = '<img src="'+imgsrc+'">'; 

//d3.select("#svgdataurl").html(img);
var canvas = document.getElementById("canvas2"),
context = canvas.getContext("2d");
context.strokeStyle = "black";
context.rect(0,0,w,h);
context.fill();

var image = new Image;
image.src = imgsrc;
image.onload = function() {
    context.drawImage(image, 0, 0);

    var canvasdata = canvas.toDataURL("image/png");

    var pngimg = '<img src="'+canvasdata+'">'; 
    //d3.select("#pngdataurl").html(pngimg);

    var a = document.createElement("a");
    a.download = "sample2.png";
    a.href = canvasdata;
        document.body.appendChild(a);
    a.click();
};

});


    </script>
  </body>

</html>

评论的编辑

要设置背景,您需要将其“绘制”到画布上:

var canvas = document.getElementById("canvas2"),
  context.strokeStyle = "black";
context.rect(0,0,w,h);
context.fill();

运行上面的代码段,我已将其添加到其中。