2012-07-24 4 views
22

Ich versuche, dieses Tutorial zu folgen, auf einen d3.js SVG Vis zu einem PNG serverseitige Konvertierung (mit Node.js) http://eng.wealthfront.com/2011/12/converting-dynamic-svg-to-png-with.htmlSVG Server-Seite PNG - mit node.js

Link zum vollständigen Code:https://gist.github.com/1509145

aber ich erhalte immer diese Fehler wenn ich eine Anfrage zu machen versuchen, wissen meine Seite

/Users/me/Node/node_modules/jsdom/lib/jsdom.js:171 
     features = JSON.parse(JSON.stringify(window.document.implementation._fea 
                  ^
    TypeError: Cannot read property 'implementation' of undefined 
     at exports.env.exports.jsdom.env.processHTML (/Users/dereklo/Node/node_modules/jsdom/lib/jsdom.js:171:59) 
     at Object.exports.env.exports.jsdom.env (/Users/dereklo/Node/node_modules/jsdom/lib/jsdom.js:262:5) 
     at Server.<anonymous> (/Users/dereklo/Node/Pie/pie_serv.js:26:9) 
     at Server.EventEmitter.emit (events.js:91:17) 
     at HTTPParser.parser.onIncoming (http.js:1785:12) 
     at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:111:23) 
     at Socket.socket.ondata (http. 

Hat jemand zu laden, warum dieses b könnte e? Ich habe das jsdom-Modul in Ordnung installiert, also weiß ich nicht genau, was diese Probleme verursacht. Vielen Dank im Voraus.

EDIT

Dies ist der Code, den ich den node.js Server implementieren bin mit. Meine neueste Ausgabe ist unter dieser Quelle ...

var http = require('http'), 
    url = require('url'), 
    jsdom = require('jsdom'), 
    child_proc = require('child_process'), 
    w = 400, 
    h = 400, 
    __dirname = "Users/dereklo/Node/pie/" 

    scripts = ["/Users/dereklo/Node/pie/d3.min.js", 
       "/Users/dereklo/Node/pie/d3.layout.min.js", 
       "/Users/dereklo/Node/pie/pie.js"], 
     //scripts = ["./d3.v2.js", 
     //   "./d3.layout.min.js", 
      //  "./pie.js"] 

    htmlStub = '<!DOCTYPE html><div id="pie" style="width:'+w+'px;height:'+h+'px;"></div>'; 

http.createServer(function (req, res) { 

    res.writeHead(200, {'Content-Type': 'image/png'}); 
    var convert = child_proc.spawn("convert", ["svg:", "png:-"]), 
     values = (url.parse(req.url, true).query['values'] || ".5,.5") 
     .split(",") 
     .map(function(v){return parseFloat(v)}); 

    convert.stdout.on('data', function (data) { 
    res.write(data); 
    }); 
    convert.on('exit', function(code) { 
    res.end(); 
    }); 

    jsdom.env({features:{QuerySelector:true}, html:htmlStub, scripts:scripts, done:function(errors, window) { 
    var svgsrc = window.insertPie("#pie", w, h, values).innerHTML; 

    console.log("svgsrc",svgsrc); 

    //jsdom's domToHTML will lowercase element names 
    svgsrc = svgsrc.replace(/radialgradient/g,'radialGradient'); 
    convert.stdin.write(svgsrc); 
    convert.stdin.end(); 
    }}); 
}).listen(8888, "127.0.0.1"); 

console.log('Pie SVG server running at http://127.0.0.1:8888/'); 
console.log('ex. http://127.0.0.1:8888/?values=.4,.3,.2,.1'); 

Letzte Ausgabe

events.js:66 
     throw arguments[1]; // Unhandled 'error' event 
        ^
Error: This socket is closed. 
    at Socket._write (net.js:519:19) 
    at Socket.write (net.js:511:15) 
    at http.createServer.jsdom.env.done (/Users/dereklo/Node/Pie/pie_serv.js:38:19) 
    at exports.env.exports.jsdom.env.scriptComplete (/Users/dereklo/Node/node_modules/jsdom/lib/jsdom.js:199:39) 
+0

Vielleicht könnten Sie uns etwas Code zeigen? :-) –

+1

Ich habe den Tutorial-Code buchstäblich kopiert und eingefügt .... – Apollo

+0

@FlorianMargaine Ich habe einen Link zum Tutorial-Text hinzugefügt. Würdest du dich bei diesem Florian etwas anstrengen? – Apollo

Antwort

49

Dies kann sich als eine nützliche Antwort auf Ihre Frage sein, wenn Sie nehmen, dass „mit node.js“ Bestimmung. Wenn es Ihnen nicht hilft, finden vielleicht spätere Besucher es interessant.

Ich habe seit einiger Zeit gearbeitet, um das gleiche Problem zu lösen (serverseitige d3-Rasterung), und ich habe PhantomJS als die beste Lösung gefunden.

server.js:

var page = require('webpage').create(), 
    renderElement = require('./renderElement.js'), 
    Routes = require('./Routes.js'), 
    app = new Routes(); 

page.viewportSize = {width: 1000, height: 1000}; 
page.open('./d3shell.html'); 

app.post('/', function(req, res) { 
    page.evaluate(new Function(req.post.d3)); 
    var pic = renderElement(page, '#Viewport'); 
    res.send(pic); 
}); 

app.listen(8000); 

console.log('Listening on port 8000.'); 

Routes.js: https://gist.github.com/3061477
renderElement.js: https://gist.github.com/3176500

d3shell.html sollte wie etwas aussehen:

<!DOCTYPE HTML> 
<html> 
<head> 
    <title>Shell</title> 
</head> 
<body> 
    <div id="Viewport" style="display: inline-block"></div> 
    <script src="http://cdnjs.cloudflare.com/ajax/libs/d3/2.8.1/d3.v2.min.js" type="text/javascript"></script> 
</body> 
</html> 

können Sie dann starten der Server mit phantomjs server.js und POST d3 = [d3-Code, der zu #Viewport rendert], und der Serv Er antwortet mit einem Base64-kodierten Png.

(Benötigt PhantomJS 1.7 oder höher.)

+0

Phantom kann wegen seiner BSD-2-Lizenz nicht verwendet werden, aber das sieht nach einem tollen Post aus, in den Sie viel Zeit investieren. Ich hoffe es hilft anderen ... – Apollo

+2

Kannst du bitte ein vollständiges Arbeitsbeispiel posten? Ich bin mir nicht sicher, wie oder was ich "posten" soll. – reubano

+0

Ich versuche auch, dieses Beispiel zu verwenden, aber, wie @reubano, weiß ich nicht, wie man schreibt, wie Sie erwähnen. Ich bin neu bei phantomJS. Danke – zed