0

我目前正在做一个项目,我们需要根据一些输入数据生成一些 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\") 导致异常。

我有点卡住了,所以我希望有人可能有一个想法,可以为我指明正确的方向。

4

1 回答 1

0

我已经弄清楚了问题所在。

1) parser.Parse(source) 返回的文档;没有实现 d3 使用的函数 createElementNS。我通过使用委托调用的包装器解决了这个问题。

2) d3 使用我没有设置的变量 ownerDocument。所以我还必须添加以下内容

jintEngine.SetValue("ownerDocument", new MyDocumentWrapper(document));

请注意,这不会使整个 d3 库正常工作。我还注意到 d3.geopath() 的一些问题,但是通过这些修复,我能够执行我的初始示例。

于 2017-01-31T10:25:02.430 回答