2012-07-24 12 views
22

Staram się śledzić ten tutorial na konwertowania d3.js SVG Vis do PNG stronie serwera (przy użyciu node.js) http://eng.wealthfront.com/2011/12/converting-dynamic-svg-to-png-with.htmlSVG do strony serwera PNG - używając node.js

Link do pełnego Kod:https://gist.github.com/1509145

jednak wciąż otrzymuję ten błąd ilekroć próbuję złożyć wniosek, aby załadować moja strona

/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. 

Czy ktoś wie dlaczego to może b mi? Zainstalowałem moduł jsdom dobrze, więc nie wiem, co powoduje te problemy ... z góry dzięki.

EDIT

Jest to kod używam wdrożyć serwer node.js. Moja ostatnia kwestia jest poniżej tego źródła ...

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'); 

najnowszym numerze

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

Może mógłbyś nam pokazać kod? :-) –

+1

Dosłownie skopiowałem i wkleiłem kod samouczka .... – Apollo

+0

@FlorianMargaine Dodałem link do merytorycznego samouczka. Chcesz zrobić cracka w tym Florianie? – Apollo

Odpowiedz

49

Może to okazać się użyteczne odpowiedzi na swoje pytanie, jeśli wziąć uwagę, że „przy użyciu node.js” zastrzeżenie. Jeśli to ci nie pomoże, może później goście uznają to za interesujące.

Pracowałem przez jakiś czas, aby rozwiązać ten sam problem (rasteryzacja po stronie serwera d3) i uznałem, że najlepszym rozwiązaniem jest PhantomJS.

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 powinien wyglądać mniej więcej tak:

<!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> 

Następnie można rozpocząć serwer z phantomjs server.js i POST d3 = [kod d3 renderujący do #Viewport], a serw er zareaguje png zakodowanym w base64.

(Wymaga PhantomJS 1.7 lub wyższej.)

+0

Nie można używać fantomu z powodu jego licencji BSD-2, ale wygląda to na świetny wpis, w którym poświęcasz dużo czasu. Mam nadzieję, że pomoże to innym ... – Apollo

+2

Czy możesz opublikować pełny przykład pracy? Nie jestem pewien, jak lub co powinienem "opublikować". – reubano

+0

Próbuję również użyć tej próbki, ale, jak @reubano, nie wiem, jak pisać, o czym wspomniałeś. Jestem nowy w PhantomJS. Dzięki – zed

Powiązane problemy