2017-08-24 96 views
1

我已經使用d3創建了一個儀表板(一組3個圖形),現在我想將三組圖形導出到瀏覽器中的任何可下載格式。 我引用下面的帖子,並試圖下載ATLEAST一個圖表: SVG to Canvas with d3.jsD3,js圖形儀表板轉換爲png/jpg/pdf

var \t formatAsPercentage = d3.format("%"), 
 
\t \t formatAsPercentage1Dec = d3.format(".1%"), 
 
\t \t formatAsInteger = d3.format(","), 
 
\t \t fsec = d3.time.format("%S s"), 
 
\t \t fmin = d3.time.format("%M m"), 
 
\t \t fhou = d3.time.format("%H h"), 
 
\t \t fwee = d3.time.format("%a"), 
 
\t \t fdat = d3.time.format("%d d"), 
 
\t \t fmon = d3.time.format("%b") 
 
\t \t ; 
 
// Let's create a mock visualization 
 

 
function dsPieChart(){ 
 

 
\t var dataset = [ 
 
\t \t \t {category: "apple", measure: 0.30}, 
 
\t  {category: "mango", measure: 0.25}, 
 
\t  {category: "pineapple", measure: 0.18}, 
 
\t  {category: "orange", measure: 0.0}, 
 
\t  {category: "peach", measure: 0.18} 
 
\t  ] 
 
\t  ; 
 

 
\t var \t width = 400, 
 
\t \t height = 400, 
 
\t \t outerRadius = Math.min(width, height)/2, 
 
\t \t innerRadius = outerRadius * .999, 
 
\t \t // for animation 
 
\t \t innerRadiusFinal = outerRadius * .5, 
 
\t \t innerRadiusFinal3 = outerRadius* .45, 
 
\t \t color = d3.scale.category20() //builtin range of colors 
 
\t \t  
 
\t \t ; 
 
var svg = d3.select("#pie") 
 
\t  .append("svg:svg")    //create the SVG element inside the <body> 
 
\t  .data([dataset])     //associate our data with the document 
 
\t   .attr("width", width)   //set the width and height of our visualization (these will be attributes of the <svg> tag 
 
\t   .attr("height", height) 
 
\t  \t \t .append("svg:g")    //make a group to hold our pie chart 
 
\t   .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")") //move the center of the pie chart from 0, 0 to radius, radius 
 
\t \t \t \t ; 
 

 
var arc = d3.svg.arc()    //this will create <path> elements for us using arc data 
 
     \t .outerRadius(outerRadius).innerRadius(innerRadius); 
 
    
 
    // for animation 
 
    var arcFinal = d3.svg.arc().innerRadius(innerRadiusFinal).outerRadius(outerRadius); 
 
\t var arcFinal3 = d3.svg.arc().innerRadius(innerRadiusFinal3).outerRadius(outerRadius); 
 

 
    var pie = d3.layout.pie()   //this will create arc data for us given a list of values 
 
     .value(function(d) { return d.measure; }); //we must tell it out to access the value of each element in our data array 
 

 
    var arcs = svg.selectAll("g.slice")  //this selects all <g> elements with class slice (there aren't any yet) 
 
     .data(pie)       //associate the generated pie data (an array of arcs, each having startAngle, endAngle and value properties) 
 
     .enter()       //this will create <g> elements for every "extra" data element that should be associated with a selection. The result is creating a <g> for every object in the data array 
 
      .append("svg:g")    //create a group to hold each slice (we will have a <path> and a <text> element associated with each slice) 
 
       .attr("class", "slice") //allow us to style things in the slices (like text) 
 
       .on("mouseover", mouseover) 
 
    \t \t \t \t .on("mouseout", mouseout) 
 
    \t \t \t \t .on("click", up) 
 
    \t \t \t \t ; 
 
    \t \t \t \t 
 
     arcs.append("svg:path") 
 
       .attr("fill", function(d, i) { return color(i); }) //set the color for each slice to be chosen from the color function defined above 
 
       .attr("d", arc)  //this creates the actual SVG path using the associated data (pie) with the arc drawing function 
 
\t \t \t \t \t .append("svg:title") //mouseover title showing the figures 
 
\t \t \t \t .text(function(d) { return d.data.category + ": " + formatAsPercentage(d.data.measure); }); \t \t \t 
 

 
     d3.selectAll("g.slice").selectAll("path").transition() 
 
\t \t \t  .duration(750) 
 
\t \t \t  .delay(10) 
 
\t \t \t  .attr("d", arcFinal) 
 
\t \t \t  ; 
 
\t 
 
\t // Add a label to the larger arcs, translated to the arc centroid and rotated. 
 
\t // source: http://bl.ocks.org/1305337#index.html 
 
\t arcs.filter(function(d) { return d.endAngle - d.startAngle > .2; }) 
 
\t \t \t .append("svg:text") 
 
\t  .attr("dy", ".35em") 
 
\t  .attr("text-anchor", "middle") 
 
\t  .attr("transform", function(d) { return "translate(" + arcFinal.centroid(d) + ")rotate(" + angle(d) + ")"; }) 
 
\t  //.text(function(d) { return formatAsPercentage(d.value); }) 
 
\t  .text(function(d) { return d.data.category; }) 
 
\t  ; 
 
\t  
 
\t // Computes the label angle of an arc, converting from radians to degrees. 
 
\t \t function angle(d) { 
 
\t \t  var a = (d.startAngle + d.endAngle) * 90/Math.PI - 90; 
 
\t \t  return a > 90 ? a - 180 : a; 
 
\t \t } 
 
\t \t  
 
\t \t 
 
\t \t // Pie chart title \t \t \t 
 
\t \t svg.append("svg:text") 
 
\t  \t .attr("dy", ".35em") 
 
\t  .attr("text-anchor", "middle") 
 
\t  .text("Usage Domainwise") 
 
\t  .attr("class","title") 
 
\t  ; \t \t  
 

 

 
\t \t 
 
\t function mouseover() { 
 
\t d3.select(this).select("path").transition() 
 
\t  .duration(750) 
 
\t   \t \t //.attr("stroke","red") 
 
\t   \t \t //.attr("stroke-width", 1.5) 
 
\t   \t \t .attr("d", arcFinal3) 
 
\t   \t \t ; 
 
\t } 
 
\t 
 
\t function mouseout() { 
 
\t d3.select(this).select("path").transition() 
 
\t  .duration(750) 
 
\t   \t \t //.attr("stroke","blue") 
 
\t   \t \t //.attr("stroke-width", 1.5) 
 
\t   \t \t .attr("d", arcFinal) 
 
\t   \t \t ; 
 
\t } 
 
\t 
 
\t function up(d, i) { 
 
\t 
 
\t \t \t \t /* update bar chart when user selects piece of the pie chart */ 
 
\t \t \t \t //updateBarChart(dataset[i].category); 
 
\t \t \t \t 
 
\t \t \t \t updateBarChart(d.data.category, color(i)); 
 
\t \t \t \t updateBarStatusChart(d.data.category, color(i)); 
 
\t \t \t 
 
\t } 
 
// Create an export button 
 
d3.select("body") 
 
    .append("button") 
 
    .html("Export") 
 
    .on("click",svgToCanvas); 
 

 
var w = 100, // or whatever your svg width is 
 
    h = 100; 
 

 
// Create the export function - this will just export 
 
// the first svg element it finds 
 
function svgToCanvas(){ 
 
    // Select the first svg element 
 
    var svg = d3.select("svg")[0][0], 
 
     img = new Image(), 
 
     serializer = new XMLSerializer(), 
 
     svgStr = serializer.serializeToString(svg); 
 

 
    img.src = 'data:image/svg+xml;base64,'+window.btoa(svgStr); 
 

 
    // You could also use the actual string without base64 encoding it: 
 
    //img.src = "data:image/svg+xml;utf8," + svgStr; 
 

 
    var canvas = document.createElement("canvas"); 
 
    document.body.appendChild(canvas); 
 

 
    canvas.width = w; 
 
    canvas.height = h; 
 
    canvas.getContext("2d").drawImage(img,0,0,w,h); 
 
    // Now save as png or whatever 
 
\t //var myCanvas = document.getElementsByTagName("canvas")[0]; 
 
\t document.write('<img src="'+canvas[0].toDataURL("image/png")+'"/>'); 
 
}; 
 

 
\t 
 
} 
 

 
dsPieChart();
\t 
 
\t \t #pie {  
 
\t position:absolute; 
 
\t top:50px; 
 
\t left:10px; 
 
\t width:400px; 
 
\t height: 400px; 
 
}
<head> 
 
<script src="https://d3js.org/d3.v3.min.js"></script> 
 
</head> 
 
<body> 
 
<div> 
 
<div id="pie"></div> 
 
</div> 
 
</body>

當我點擊導出選項它不能識別我的畫布elemt我試着在網上提供各種選項但沒有用。 Soebody請讓我知道如何做到這一點 當我出口cklick我要的是我希望它下載我的圖表作爲圖像

回答

0

你錯過image.onLoad功能

var \t formatAsPercentage = d3.format("%"), 
 
\t \t formatAsPercentage1Dec = d3.format(".1%"), 
 
\t \t formatAsInteger = d3.format(","), 
 
\t \t fsec = d3.time.format("%S s"), 
 
\t \t fmin = d3.time.format("%M m"), 
 
\t \t fhou = d3.time.format("%H h"), 
 
\t \t fwee = d3.time.format("%a"), 
 
\t \t fdat = d3.time.format("%d d"), 
 
\t \t fmon = d3.time.format("%b") 
 
\t \t ; 
 
// Let's create a mock visualization 
 

 
function dsPieChart(){ 
 

 
\t var dataset = [ 
 
\t \t \t {category: "apple", measure: 0.30}, 
 
\t  {category: "mango", measure: 0.25}, 
 
\t  {category: "pineapple", measure: 0.18}, 
 
\t  {category: "orange", measure: 0.0}, 
 
\t  {category: "peach", measure: 0.18} 
 
\t  ] 
 
\t  ; 
 

 
\t var \t width = 400, 
 
\t \t height = 400, 
 
\t \t outerRadius = Math.min(width, height)/2, 
 
\t \t innerRadius = outerRadius * .999, 
 
\t \t // for animation 
 
\t \t innerRadiusFinal = outerRadius * .5, 
 
\t \t innerRadiusFinal3 = outerRadius* .45, 
 
\t \t color = d3.scale.category20() //builtin range of colors 
 
\t \t  
 
\t \t ; 
 
var svg = d3.select("#pie") 
 
\t  .append("svg:svg")    //create the SVG element inside the <body> 
 
\t  .data([dataset])     //associate our data with the document 
 
\t   .attr("width", width)   //set the width and height of our visualization (these will be attributes of the <svg> tag 
 
\t   .attr("height", height) 
 
\t  \t \t .append("svg:g")    //make a group to hold our pie chart 
 
\t   .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")") //move the center of the pie chart from 0, 0 to radius, radius 
 
\t \t \t \t ; 
 

 
var arc = d3.svg.arc()    //this will create <path> elements for us using arc data 
 
     \t .outerRadius(outerRadius).innerRadius(innerRadius); 
 
    
 
    // for animation 
 
    var arcFinal = d3.svg.arc().innerRadius(innerRadiusFinal).outerRadius(outerRadius); 
 
\t var arcFinal3 = d3.svg.arc().innerRadius(innerRadiusFinal3).outerRadius(outerRadius); 
 

 
    var pie = d3.layout.pie()   //this will create arc data for us given a list of values 
 
     .value(function(d) { return d.measure; }); //we must tell it out to access the value of each element in our data array 
 

 
    var arcs = svg.selectAll("g.slice")  //this selects all <g> elements with class slice (there aren't any yet) 
 
     .data(pie)       //associate the generated pie data (an array of arcs, each having startAngle, endAngle and value properties) 
 
     .enter()       //this will create <g> elements for every "extra" data element that should be associated with a selection. The result is creating a <g> for every object in the data array 
 
      .append("svg:g")    //create a group to hold each slice (we will have a <path> and a <text> element associated with each slice) 
 
       .attr("class", "slice") //allow us to style things in the slices (like text) 
 
       .on("mouseover", mouseover) 
 
    \t \t \t \t .on("mouseout", mouseout) 
 
    \t \t \t \t .on("click", up) 
 
    \t \t \t \t ; 
 
    \t \t \t \t 
 
     arcs.append("svg:path") 
 
       .attr("fill", function(d, i) { return color(i); }) //set the color for each slice to be chosen from the color function defined above 
 
       .attr("d", arc)  //this creates the actual SVG path using the associated data (pie) with the arc drawing function 
 
\t \t \t \t \t .append("svg:title") //mouseover title showing the figures 
 
\t \t \t \t .text(function(d) { return d.data.category + ": " + formatAsPercentage(d.data.measure); }); \t \t \t 
 

 
     d3.selectAll("g.slice").selectAll("path").transition() 
 
\t \t \t  .duration(750) 
 
\t \t \t  .delay(10) 
 
\t \t \t  .attr("d", arcFinal) 
 
\t \t \t  ; 
 
\t 
 
\t // Add a label to the larger arcs, translated to the arc centroid and rotated. 
 
\t // source: http://bl.ocks.org/1305337#index.html 
 
\t arcs.filter(function(d) { return d.endAngle - d.startAngle > .2; }) 
 
\t \t \t .append("svg:text") 
 
\t  .attr("dy", ".35em") 
 
\t  .attr("text-anchor", "middle") 
 
\t  .attr("transform", function(d) { return "translate(" + arcFinal.centroid(d) + ")rotate(" + angle(d) + ")"; }) 
 
\t  //.text(function(d) { return formatAsPercentage(d.value); }) 
 
\t  .text(function(d) { return d.data.category; }) 
 
\t  ; 
 
\t  
 
\t // Computes the label angle of an arc, converting from radians to degrees. 
 
\t \t function angle(d) { 
 
\t \t  var a = (d.startAngle + d.endAngle) * 90/Math.PI - 90; 
 
\t \t  return a > 90 ? a - 180 : a; 
 
\t \t } 
 
\t \t  
 
\t \t 
 
\t \t // Pie chart title \t \t \t 
 
\t \t svg.append("svg:text") 
 
\t  \t .attr("dy", ".35em") 
 
\t  .attr("text-anchor", "middle") 
 
\t  .text("Usage Domainwise") 
 
\t  .attr("class","title") 
 
\t  ; \t \t  
 

 

 
\t \t 
 
\t function mouseover() { 
 
\t d3.select(this).select("path").transition() 
 
\t  .duration(750) 
 
\t   \t \t //.attr("stroke","red") 
 
\t   \t \t //.attr("stroke-width", 1.5) 
 
\t   \t \t .attr("d", arcFinal3) 
 
\t   \t \t ; 
 
\t } 
 
\t 
 
\t function mouseout() { 
 
\t d3.select(this).select("path").transition() 
 
\t  .duration(750) 
 
\t   \t \t //.attr("stroke","blue") 
 
\t   \t \t //.attr("stroke-width", 1.5) 
 
\t   \t \t .attr("d", arcFinal) 
 
\t   \t \t ; 
 
\t } 
 
\t 
 
\t function up(d, i) { 
 
\t 
 
\t \t \t \t /* update bar chart when user selects piece of the pie chart */ 
 
\t \t \t \t //updateBarChart(dataset[i].category); 
 
\t \t \t \t 
 
\t \t \t \t updateBarChart(d.data.category, color(i)); 
 
\t \t \t \t updateBarStatusChart(d.data.category, color(i)); 
 
\t \t \t 
 
\t } 
 
// Create an export button 
 
d3.select("body") 
 
    .append("button") 
 
    .html("Export") 
 
    .on("click",svgToCanvas); 
 

 
var w = 100, // or whatever your svg width is 
 
    h = 100; 
 

 
// Create the export function - this will just export 
 
// the first svg element it finds 
 
function svgToCanvas(){ 
 
    // Select the first svg element 
 
    debugger; 
 
    var svg = d3.select("svg")[0][0], 
 
     img = new Image(), 
 
     serializer = new XMLSerializer(), 
 
     svgStr = serializer.serializeToString(svg); 
 

 
    data = 'data:image/svg+xml;base64,'+window.btoa(svgStr); 
 
    
 
    var canvas = document.createElement("canvas"); 
 
    canvas.width = 400; 
 
    canvas.height = 400; 
 
    context = canvas.getContext("2d"); 
 
    img.src = data; 
 
    img.onload = function() { 
 
     context.drawImage(img, 0, 0); 
 
     var canvasdata = canvas.toDataURL("image/png"); 
 
     var pngimg = '<img src="'+canvasdata+'">'; 
 
     var a = document.createElement("a"); 
 
     a.download = "sample.png"; 
 
     a.href = canvasdata; 
 
     a.click(); 
 
    }; 
 
}; 
 

 
\t 
 
} 
 

 
dsPieChart();
#pie {  
 
\t position:absolute; 
 
\t top:50px; 
 
\t left:10px; 
 
\t width:400px; 
 
\t height: 400px; 
 
}
<script src="https://d3js.org/d3.v3.min.js"></script> 
 

 

 
<div> 
 
<div id="pie"></div> 
 
</div>

+0

:導出的圖像只是圖像的頂部,最初我認爲這是因爲寬度和高度的規格,但在指定正確的寬度和高度後仍然給出相同的值。我該如何糾正它? – Aarika

+0

其寬度和高度的問題只有在創建canvas元素後設置畫布的寬度和高度,像這樣..canvas.width = 400; canvas.height = 400; – subbu

+0

非常感謝您解決這個問題,並且它的工作原理完全不錯:) – Aarika