2013-03-20 9 views
12

Ich habe ein d3 generiert Kraftlayout-Diagramm, ich muss es zu png mit der aktuellen (benutzerdefinierten) Skalierung intakt exportieren.Zeigen Sie voll SVG mit Skalierung intakt

Durch meine Argumentation dies wird dann wachsen die SVG Breite und Höhe, so dass, wenn die svg1920x1080 ist, und es ist ‚gezoomt‘ in die exportierte svg wahrscheinlich eine viel größere Breite und Höhe zur Aufnahme dieser haben sollte.

Ich habe alles versucht, und mir fehlt etwas, ich kann einfach nicht scheinen, dynamisch die korrekten Werte für den Ausgang zu berechnen, den ich benötige.

Hier ist ein example meiner exportierten SVG, beachten Sie, dass es viel mehr Informationen, es ist einfach nicht sichtbar in dieser Größenordnung.

EDIT

Hier ist mein Grund ausführenden Code, vor allem aus highcharts angepasst:

serializeSvg: function() { 
     /** 
     * serialize a xml object to string 
     * @param {type} xmlNode the node to use 
     * @returns {String|@exp;[email protected];xml|@exp;[email protected];[email protected];@call;serializeToString} 
     */ 
     function serializeXmlNode(xmlNode) { 
      if (typeof window.XMLSerializer !== 'undefined') { 
       return (new window.XMLSerializer()).serializeToString(xmlNode); 
      } else if (typeof xmlNode.xml !== 'undefined') { 
       return xmlNode.xml; 
      } 

      return ''; 
     } 

     var svg = serializeXmlNode(document.getElementsByTagName('svg')[0]), 
      factor = 2; 
     svg = '<svg' 
       + ' xmlns="http://www.w3.org/2000/svg"' // xml namespace 
       + ' version="1.1"' 
       + ' xmlns:xlink="http://www.w3.org/1999/xlink"' // for images 
       + ' ' + svg.substring(svg.indexOf('<svg ') + 5); 

     // highcharts svg sanitizer 
     svg = svg.replace(/width="([^"]+)"/, function(m, width) { 
       return 'width="' + (width * factor) + '"'; 
      }).replace(/height="([^"]+)"/, function(m, height) { 
       return 'height="' + (height * factor) + '"'; 
      }).replace(/<rect class="drag"[^<]+<\/rect>/, '') 

      // IE specific 
      .replace(/<IMG /g, '<image ') 
      .replace(/height=([^" ]+)/g, 'height="$1"') 
      .replace(/width=([^" ]+)/g, 'width="$1"') 
      .replace(/id=([^" >]+)/g, 'id="$1"') 
      .replace(/class=([^" ]+)/g, 'class="$1"') 
      .replace(/ transform /g, ' ') 
      .replace(/:(path|rect)/g, '$1') 
      .replace(/style="([^"]+)"/g, function(s) { 
        return s.toLowerCase(); 
      }); 

     return svg; 
    } 

und der Haupt Zoom/Skalierung Start für das d3 Layout:

var layout = d3.layout.force(); 
var DEFAULT_SIZE = 64; 
var GROWTH_SCALE = 1.15; 
var SHRINK_SCALE = 1.05; 

// creates a new force layout 
var force = layout 
    .size([w, h]) 
    .gravity(.06) 
    .distance(110) 
    //.friction(0.6) 
    //.linkStrength(0.4) 
    .charge(-((DEFAULT_SIZE * GROWTH_SCALE) * 10)) 
    .on('tick', tick); 

// creates the svg context 
var svg = d3.select('.la-container').append('svg:svg') 
    .attr('width', w) 
    .attr('height', h) 
    .attr('pointer-events', 'all') // set for the pan/zooming 
    .append('svg:g') // add a g element for capturing zoom and pan 
     .call(d3.behavior.zoom().scaleExtent([0.6, 6.0]).on('zoom', redraw)) 
    .append('svg:g'); 

svg.append('svg:rect') 
    .attr('class', 'drag') 
    .attr('width', w) 
    .attr('height', h) 
    .attr('fill', 'white'); 
+0

Verwenden Sie das Zoom-Verhalten in d3, um Ihr Bild zu skalieren? Sie sollten in der Lage sein, zoom.scale() zu verwenden, um die Zoomstufe zu erfassen und das Ausgabe-SVG entsprechend zu transformieren. Mehr Informationen (und Javascript-Code) wären hilfreich, um genau herauszufinden, was Sie versuchen zu tun? – RoryB

+0

Ja, ich benutze 'd3.behavior.zoom()' und 'd3.behavior.drag()', nehmen wir an, ein Benutzer wird auf einen Graphknoten mit 500 Knoten im Abstand von 100 Pixeln gezoomt, er muss ziehen Um andere Knoten zu sehen, was ich will ist, dass, wenn er auf den exportierten Zoom klickt, das komplette 500-Knoten-Diagramm in eine SVG-Datei exportiert werden soll, wo das Ganze bei dieser Zoom-Stufe sichtbar ist. – epoch

+0

Ist Ihr Problem mit der Erfassung der Zoomstufe oder mit dem eigentlichen Exportprozess? Es wird schwierig sein, Ihnen zu helfen, ohne eine Vorstellung davon zu haben, welches Javascript Sie tatsächlich verwenden und welche Fehlermeldungen usw. Ihr aktueller Code erzeugt. – RoryB

Antwort

0

Aus Ihre Kommentare, können Sie einige der hier besprochenen Optionen überprüfen: https://groups.google.com/forum/#!msg/d3-js/tHRV4uvvHFU/yjIAfdQN8WsJ

D3 sollte Attribute in das DOM schreiben, die allgemeine Erwartung ist, dass wenn Sie das SVG unverändert exportieren, sollten Sie genau die gleiche Ansicht erhalten. Es klingt wie das, was Sie möchten, ist ein Prozess, um die vorhandene Ansicht als PNG oder ähnliches zu rendern.

Hier ist eine interessante clientseitige nimmt nur http://html2canvas.hertzen.com/

+0

danke, ich habe durch. Ich habe kein Problem Rendering der Svg, ich muss nur im richtigen Maßstab und Position zu rendern, und dafür muss ich die anwenden Korrekte Transformationen und Größen – epoch

0

ich habe dies getestet, aber ich denke, wenn Sie Bild exportieren würden Sie zuerst wieder auf das Ausgangsniveau heran müssen aus. Dann serialisieren Sie den XMLNode. Erhöhen Sie dann die Größe, wie Sie es jetzt tun, entsprechend der Skalierungsstufe des Benutzers. Und dann gib es zurück.

Sie sollten in der Lage sein, die Transformationen des Benutzers zu erhalten zunächst mit:

zoom.scale()

Wenn nicht angegeben, gibt den aktuellen Zoomfaktor, der standardmäßig auf 1.

zoom.translate()

Wenn nicht angegeben, wird der aktuelle Übersetzungsvektor mit der Standardeinstellung [0, 0] zurückgegeben.

+0

Ich weiß das alles, aber leider beantwortet es immer noch nicht meine Frage – epoch

+0

Tut mir leid, ich glaube nicht, dass ich genau das Problem verstehe. Ist es, dass die Ausgabe auf die richtige Größe skaliert ist, aber es zeigt nur einen kleinen Teil von der Karte? Oder habe ich etwas vermisst? Wo rufst du 'serializeSvg()' an und was machst du direkt davor? –

+0

Ihre erste Annahme ist korrekt sir :) serializeSvg kommt von einem Klickereignis – epoch

1

Also, in Ihrem d3-Startup-Code rufen Sie d3.behaviour.zoom.on() an, um die "Neuzeichnen" -Funktion an die "Zoom" -Aktion zu binden.Um den Maßstab und Übersetzungsstufe zu erhalten, sollten Sie die d3.scale und d3.translate Werte in dieser Funktion, so etwas erfassen (wie Sie nicht den Code für die Neuzeichnung Funktion gebucht haben):

var scale = 1; 
var xtranslate=0; 
var ytranslate=0; 

var redraw = function(){ 
    scale= d3.event.scale; 
    xtranslate=d3.event.translate[0]; 
    ytranslate=d3.event.translate[1]; 

    //your actual code to redraw stufff 
} 

Das wird Sie erhalten die Skalierungs- und Übersetzungswerte von d3: dann müssen Sie die entsprechenden Änderungen an der exportierten SVG anwenden: Ich habe das nicht wirklich getan, aber vermutlich skalieren Sie die Attribute "Höhe" und "Breite" entsprechend (ich denke, das wäre es) nur durch Multiplizieren der Attributwerte mit dem Skalenwert, aber ich kann nicht sicher sein).

1

einen Blick Feld Übernehmen und multiplizieren sie mit Skalenwert,

zum Beispiel 1920x1080, wenn ungezoomten dann Sichtbox = 0 0 1920 1080

bei scale = 0,5 1920 * 0,5 1080 * 0,5 Sichtbox = 0 0 960 540

+0

das half mir immer das exportierte Bild im Export zu beschränken, aber die Größe wächst immer noch nicht mit dem Zoom, und der Zoom wird jetzt auch ignoriert – epoch

Verwandte Themen