我目前正在进行一个项目,需要根据一些输入数据生成一些SVG。目前,所有这些SVG生成都是使用d3库在javascript中实现的。请注意,我的目标是能够重用这个逻辑,而不是全部实现它。
我的问题是,我希望能够从C#调用这个javascript。
我尝试过使用PhantomJS,我能够生成SVG,但我不满意,因为
- 每次我想调用javascript时,它都会启动一个新的进程注意到它占用了大量内存(在我的情况下,我看到了100 mb这对我来说太过分了)
- 它看起来有点不稳定。我有在某些情况下,流程会挂起
- 开发(在javascript方面)非常令人沮丧,因为它很难调试
因为我对PhantomJS不满意,我也尝试过使用jint,这似乎真的很好用。不幸的是,我还没有完全建立并运行一个工作示例。目前,我正在使用AngleSharp来提供DOM,这样D3就有地方写数据了。这给了我以下例子:
static void TestJint()
{
//We require a custom configuration with JavaScript and CSS
var config = Configuration.Default.WithJavaScript().WithCss();
//Let's create a new parser using this configuration
var parser = new HtmlParser(config);
//This is our sample source, we will do some DOM manipulation
var source = "<!doctype html> <html><head></head> <body> </body></html>";
var document = parser.Parse(source);
var jintEngine = new Engine();
jintEngine.SetValue("document", document.Implementation);
jintEngine = jintEngine.Execute(File.ReadAllText("d3.min.js"));
jintEngine = jintEngine.Execute("function testFunc() { d3.select("body").append("span").text("Hello, world!"); return 42;}");
var res = jintEngine.Invoke("testFunc").ToObject();
}
问题是行var res=jintEngine.Invoke("testFunc").ToObject();引发异常。
异常截图
如果我尝试更换线路
jintEngine = jintEngine.Execute("function testFunc() { d3.select("body").append("span").text("Hello, world!"); return 42;}");
带有
jintEngine = jintEngine.Execute("function testFunc() { d3.select("body"); return 42;}");
则该函数能够在没有任何异常的情况下运行。通过对逻辑进行一点处理,我得出结论,是.append(\"span\")导致了异常。
我有点困了,所以我希望有人能给我一个正确的方向。
我已经解决了问题。
1) 解析程序返回的文档。解析(来源);没有实现d3使用的函数createElementNS。我通过使用委托调用的包装器解决了这个问题。
2) d3使用了我尚未设置的变量ownerDocument。所以我还必须添加以下
jintEngine.SetValue("ownerDocument", new MyDocumentWrapper(document));
请注意,这并不能使整个d3库正常工作。我也注意到了d3.geopath()的一些问题,但通过这些修复,我可以执行我的初始示例。