2012-07-24 23 views
22

estoy tratando de seguir este tutorial sobre cómo convertir un d3.js SVG Vis a un servidor del lado del PNG (usando Node.js) http://eng.wealthfront.com/2011/12/converting-dynamic-svg-to-png-with.htmlSVG a PNG lado del servidor - usando Node.js

Enlace a la plena código:https://gist.github.com/1509145

Sin embargo, me siguen dando este error siempre que intente hacer una petición para cargar mi página de

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

¿alguien sabe por qué esto podría b ¿mi? He instalado el módulo jsdom muy bien, así que no sé realmente qué está causando estos problemas ... gracias de antemano.

EDITAR

Este es el código que estoy usando para implementar el servidor Node.js. Mi último número está por debajo de esta fuente ...

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

de última emisión

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

¿Tal vez podría mostrarnos algún código? :-) –

+1

He copiado y pegado literalmente el código del tutorial ... – Apollo

+0

@FlorianMargaine Agregué un enlace a la esencia del tutorial. ¿Te importa untar a este Florian? – Apollo

Respuesta

49

Esto puede llegar a ser una respuesta útil a su pregunta si usted toma que "usar Node.js" estipulación. Si no lo ayuda, tal vez los visitantes posteriores lo encuentren interesante.

He estado trabajando durante algún tiempo para resolver este mismo problema (rasterización d3 del lado del servidor), y he encontrado que PhantomJS es la mejor solución.

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 debería ser algo como:

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

, entonces puede comenzar el servidor con phantomjs server.js y POST d3 = [d3 code que representa #Viewport], y el servidor er responderá con un png codificado en base64.

(Requiere PhantomJS 1.7 o superior)

+0

No se puede usar el fantasma por su licencia BSD-2, pero parece una gran publicación en la que dedica mucho tiempo. Espero que ayude a los demás ... – Apollo

+2

¿Puedes por favor publicar un ejemplo completo de trabajo? No estoy seguro de cómo o qué debería "publicar". – reubano

+0

También estoy tratando de usar esta muestra, pero, como @reubano, no me doy cuenta de cómo publicar como mencionas. Soy nuevo en phantomJS. Gracias – zed

Cuestiones relacionadas