2012-07-19 20 views
11

Czy ktoś próbował użyć biblioteki svg do canvas podczas tworzenia wizualizacji d3.js? Próbowałem użyć canvg.js i d3.js przekształcić SVG do płótnie z poziomu aplikacji Android WebView 2.3, ale gdy zgłoszę:SVG na płótno z d3.js

svg.selectAll(".axis") 
     .data(d3.range(angle.domain()[1])) 
    .enter().append("g") 
     .attr("class", "axis") 
     .attr("transform", function(d) { return "rotate(" + angle(d) * 180/Math.PI + ")"; }) 
    .call(d3.svg.axis() 
     .scale(radius.copy().range([-5, -outerRadius])) 
     .ticks(5) 
     .orient("left")) 
    .append("text") 
     .attr("y", 
     function (d) { 
      if (window.innerWidth < 455){ 
      console.log("innerWidth less than 455: ",window.innerWidth); 
      return -(window.innerHeight * .33); 
      } 
      else{ 
      console.log("innerWidth greater than 455: ",window.innerWidth); 
      return -(window.innerHeight * .33); 
      } 
     }) 
     .attr("dy", ".71em") 
     .attr("text-anchor", "middle") 
     .text(function(d, i) { return capitalMeta[i]; }) 
     .attr("style","font-size:12px;"); 

pojawia się błąd: Uncaught TypeError: nie można wywołać metody " setProperty 'o wartości zerowej http://mbostock.github.com/d3/d3.js?2.5.0:1707

Czy mogłaby się pojawić jakaś przeglądarka bez nagłówków lub serwer po stronie serwera? Czy ktoś już to wcześniej napotkał?

+0

To taka wielka sprawa, życzę ktoś go odebrać. – Apollo

Odpowiedz

0

Czy wypróbowałeś ten sam kod w przeglądarce obsługującej SVG, aby sprawdzić, czy jest to problem z widokiem na WWW? Następnie spróbuj this example używając canvg lub this one używając serializacji DOM. W przypadku renderowania po stronie serwera można rozpocząć od wersji this example, aby uzyskać informacje na temat renderowania jej na kanale po stronie serwera przy użyciu pliku Node.js.

1

Nie próbowałem biblioteki, ale renderowałem SVG wyprodukowany przez d3 do płótna po wpisie this na MDN.

Ten kod jest szybkim mash-mash z MDN i jQuery, które będziesz musiał posprzątać, i nie ma żadnych błędów lub sprawdzania platfromu, ale działa i mam nadzieję, że pomaga .

$(document.body).append(
    '<canvas id="canvas" width="'+diameter+'" height="'+diameter+'"></canvas>' 
); 

// https://developer.mozilla.org/en/docs/HTML/Canvas/Drawing_DOM_objects_into_a_canvas 
var el = $($('svg')[0]); 
var svgMarkup = '<svg xmlns="http://www.w3.org/2000/svg"' 
+ ' class="' + el.attr('class') +'"' 
+ ' width="' + el.attr('width') +'"' 
+ ' height="' + el.attr('height') +'"' 
+ '>' 
+ $('svg')[0].innerHTML.toString()+'</svg>'; 
var canvas = document.getElementById("canvas"); 
var ctx = canvas.getContext("2d"); 
var DOMURL = this.URL || this.webkitURL || this; 
var img = new Image(); 
var svg = new Blob([svgMarkup], {type: "image/svg+xml;charset=utf-8"}); 
var url = DOMURL.createObjectURL(svg); 
img.onload = function() { 
    ctx.drawImage(img, 0, 0); 
    alert('ok'); 
    DOMURL.revokeObjectURL(url); 
}; 
img.src = url; 
11

Oto jeden sposób można napisać swoją SVG do płótnie (i następnie zapisać wynik jako PNG lub cokolwiek):

// 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 
}; 
+0

Świetna odpowiedź! Dodałem także rozwiązanie poniżej (na podstawie twojego), które ściąga style z zewnętrznych arkuszy stylów CSS. – Constantino

+0

@ace mogę mieć pełny kod, proszę bardzo go potrzebuję – sg28

+0

@ace, może pnkr/fiddle – sg28

4

Odpowiedź przez @ace jest bardzo dobra, jednak nie robi” t obsługuje przypadek zewnętrznych arkuszy stylów CSS. Poniższy przykład automatycznie nadpisuje wygenerowany obraz dokładnie tak, jak wygląda oryginalny SVG, nawet jeśli pociąga style z osobnych arkuszy stylów.

// when called, will open a new tab with the SVG 
// which can then be right-clicked and 'save as...' 
function saveSVG(){ 

    // get styles from all required stylesheets 
    // http://www.coffeegnome.net/converting-svg-to-png-with-canvg/ 
    var style = "\n"; 
    var requiredSheets = ['phylogram_d3.css', 'open_sans.css']; // list of required CSS 
    for (var i=0; i<document.styleSheets.length; i++) { 
     var sheet = document.styleSheets[i]; 
     if (sheet.href) { 
      var sheetName = sheet.href.split('/').pop(); 
      if (requiredSheets.indexOf(sheetName) != -1) { 
       var rules = sheet.rules; 
       if (rules) { 
        for (var j=0; j<rules.length; j++) { 
         style += (rules[j].cssText + '\n'); 
        } 
       } 
      } 
     } 
    } 

    var svg = d3.select("svg"), 
     img = new Image(), 
     serializer = new XMLSerializer(), 

    // prepend style to svg 
    svg.insert('defs',":first-child") 
    d3.select("svg defs") 
     .append('style') 
     .attr('type','text/css') 
     .html(style); 


    // generate IMG in new tab 
    var svgStr = serializer.serializeToString(svg.node()); 
    img.src = 'data:image/svg+xml;base64,'+window.btoa(unescape(encodeURIComponent(svgStr))); 
    window.open().document.write('<img src="' + img.src + '"/>'); 
}; 

I, być kompletny, przycisk, który wywołuje funkcję:

// save button 
d3.select('body') 
    .append("button") 
    .on("click",saveSVG) 
    .attr('class', 'btn btn-success') 
+0

Jest to bardzo pomocne, ale twój przykład jest zdezorientowany about requiredSheets vs document.styleSheets, co doprowadziło do błędów dla mnie. Naprawiłem je, usuwając 'var requiredSheets ...' i 'if (requiredSheets.indexOf ...' (co oznacza, że ​​mogę usunąć 'var SheetName ...'). Oznacza to, że requiredSheets jest niepotrzebne, powoduje błędy i może być bezpiecznie usunięte –

+0

@Constantino: 'height' i' width' nigdy nie są używane - dlaczego przypisano im wartości? –

+0

Ups, to stary kod do kopiowania i wklejania ... – Constantino

Powiązane problemy