如何在 C# 应用程序中集成 d3.js 图表?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12134200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to integrate d3.js chart in C# application?
提问by bobby
I am a big fan of Mike Bostock's d3.js chart library: d3js.org.
我是 Mike Bostock 的 d3.js 图表库的忠实粉丝:d3js.org。
I would like to use it to display charts in a C# .Net application, but I don't know if it is possible.
我想用它在 C# .Net 应用程序中显示图表,但我不知道是否可行。
It may be possible by generating HTM+JS codes and rendering it in a webbrowser window. However, I understood d3.js library cannot be used locally without a webserver (However I did not understood what works without a webserver and what requires a webserver), therefore a simple solution does not work.
通过生成 HTM+JS 代码并在网络浏览器窗口中呈现它可能是可能的。但是,我知道 d3.js 库不能在没有网络服务器的情况下在本地使用(但是我不明白没有网络服务器什么工作以及什么需要网络服务器),因此一个简单的解决方案不起作用。
Has anybody tried to develop that kind of deployment of d3.js charts? Do you have an idea on where to start in order to have the most simple solution?
有没有人尝试开发这种 d3.js 图表部署?您是否知道从哪里开始以获得最简单的解决方案?
采纳答案by WiredPrairie
A web server definitely isn't required to use a client side JavaScript library like d3.js.
Web 服务器绝对不需要使用像 d3.js 这样的客户端 JavaScript 库。
For C#, you'll need to embed a web browser control (in either WindowsForms or WPF).
对于 C#,您需要嵌入 Web 浏览器控件(在 WindowsForms 或 WPF 中)。
You'll need to make sure that the browser is working in IE9 Standards mode as shown here.
你需要确保浏览器在IE9标准模式下工作,如图这里。
Create your web pages as you would normally. Navigate to them using webbrowser.navigate (as just files on the file system.)
像往常一样创建您的网页。使用 webbrowser.navigate 导航到它们(就像文件系统上的文件一样。)
This should work.
这应该有效。
回答by Stefan Steiger
Necromancing.
死灵法术。
You can do this with C# and .NET-Core on all operating systems using nodeJS.
Absolutely no browser-control required.
Just install JavaScript-Serviceswith nuget, then install d3, jsdom and svg2png in nodejs:
您可以在所有使用 nodeJS 的操作系统上使用 C# 和 .NET-Core 执行此操作。
绝对不需要浏览器控制。
只需使用 nuget安装JavaScript-Services,然后在 nodejs 中安装 d3、jsdom 和 svg2png:
npm install –save svg2png
npm install –save jsdom
npm install –save d3
then in Startup.cs, add NodeServices in ConfigureServices
然后在 Startup.cs 中,在 ConfigureServices 中添加 NodeServices
using Microsoft.AspNetCore.NodeServices;
public void ConfigureServices(IServiceCollection services)
{
// services.AddMvc();
// https://geeks.ms/clanderas/2016/10/18/asp-net-core-node-services-to-execute-your-nodejs-scripts/
// https://blogs.msdn.microsoft.com/webdev/2017/02/14/building-single-page-applications-on-asp-net-core-with-javascriptservices/
services.AddNodeServices( options => {
// options.DebuggingPort
});
}
Add an output handler:
添加输出处理程序:
public class AgeInfo
{
public string age;
public int population;
public AgeInfo(string prmAge, int prmPop)
{
this.age = prmAge;
this.population = prmPop;
}
}
// http://gunnarpeipman.com/2017/10/aspnet-core-node-d3js/
public async Task<IActionResult> Chart([FromServices] INodeServices nodeServices)
{
var options = new { width = 400, height = 200 };
var data = new[] {
new { label = "Abulia", count = 10 },
new { label = "Betelgeuse", count = 20 },
new { label = "Cantaloupe", count = 30 },
new { label = "Dijkstra", count = 40 }
};
List<AgeInfo> ls = new List<AgeInfo>();
ls.Add( new AgeInfo("<5", 2704659));
ls.Add( new AgeInfo("5-13", 4499890));
ls.Add( new AgeInfo("14-17", 2159981));
ls.Add( new AgeInfo("18-24", 3853788));
ls.Add( new AgeInfo("25-44", 14106543));
ls.Add( new AgeInfo("45-64", 8819342));
ls.Add( new AgeInfo("≥65", 612463));
// string markup = await nodeServices.InvokeAsync<string>("Node/d3Pie.js", options, data);
string markup = await nodeServices.InvokeAsync<string>("Node/d3chart.js", options, ls);
string html = @"<!DOCTYPE html>
<html>
<head><meta charset=""utf-8"" />
<style type=""text/css"">
.arc text
{
font: 10px sans-serif;
text-anchor: middle;
}
.arc path
{
stroke: #fff;
}
</style>
</head>
<body>
<img src=""" + markup + @""" />
</body>
</html>";
return Content(html, "text/html");
}
And then add the JavaScript
然后添加 JavaScript
// Include all modules we need
const svg2png = require("svg2png");
const { JSDOM } = require("jsdom");
const d3 = require('d3');
// https://bl.ocks.org/mbostock/3887235
module.exports = function (callback, options, data) {
var dom = new JSDOM('<!DOCTYPE html><html><head><meta charset="utf-8" /></head><body><svg width="960" height="500"></svg></body></html>');
var document = dom.window.document;
dom.window.d3 = d3.select(dom.window.document);
// callback(null, dom.window.document.body.innerHTML);
var svg = dom.window.d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
radius = Math.min(width, height) / 2,
g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var color = d3.scaleOrdinal(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var pie = d3.pie()
.sort(null)
.value(function (d) {
return d.population;
});
var path = d3.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var label = d3.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
/*
var dataaa =
[
{
age: "<5",
population: 2704659
},
{
age: "5-13",
population: 4499890
},
{
age: "14-17",
population: 2159981
},
{
age: "18-24",
population: 3853788
},
{
age: "25-44",
population: 14106543
}
,
{
age: "45-64",
population: 8819342
}
,
{
age: "≥65",
population: 612463
}
];
*/
var arc = g.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
arc.append("path")
.attr("d", path)
.attr("fill", function (d) {
return color(d.data.age);
});
arc.append("text")
.attr("transform", function (d) {
return "translate(" + label.centroid(d) + ")";
})
.attr("dy", "0.35em")
.text(function (d) {
return d.data.age;
});
//});
// var svgText = dom.window.document.body.outerHTML;
// var svgText = dom.window.document.body.innerHTML;
var svgText = dom.window.document.body.querySelector("svg").outerHTML
// callback(null, svgText);
// var svgText = dom.window.d3.select("svg").html();
// svgText=process.version; // v8.6.0
// svgText= JSON.stringify(process.versions); //
// var pjson = require('./package.json'); svgText = pjson.version;
// callback(null, svgText);
// callback(null, JSON.stringify( { width: width, height: height } ));
// var buf = Buffer.from(svgText);
// callback(null, JSON.stringify( buf ));
// var output = svg2png.sync(buf, { width: width, height: height } );
// callback(null, JSON.stringify( output ));
//callback(null, svgText);
// callback(null, 'data:image/svg+xml;base64,' + Buffer.from(svgText).toString('base64'));
svg2png(Buffer.from(svgText), { width: width, height: height })
.then(buffer => 'data:image/png;base64,' + buffer.toString('base64') )
.then(buffer => callback(null, buffer));
}
That should give you a the required d3-chart without needing a svg-compatible browser.
这应该为您提供所需的 d3-chart,而无需 svg 兼容的浏览器。
You might need to update npm before you can (successfully) install any nodeJS modules.
您可能需要先更新 npm,然后才能(成功)安装任何 nodeJS 模块。
npm install -g npm
You can also do this in a command-line application, just that then you need to set up your own DI contrainer.
您也可以在命令行应用程序中执行此操作,然后您需要设置自己的 DI 限制器。
回答by maeneak
Was looking for the same solution and stumbled on edge.js. It can be run from any .NET 4.5 application and installed via Nuget. It doesn't require node.js installed but you will need node to install D3 using NPM. Make sure package-lock.jsonand the node_modulesfolder is in the same directory as the edge.jsfile at runtime, or installed globally.
I just ran npm i d3-arrayfrom inside the \edgefolder, then included the *.json and *.js files, set them to content and copy to output directory. Then its as simple as:
正在寻找相同的解决方案并偶然发现了edge.js。它可以从任何 .NET 4.5 应用程序运行并通过 Nuget 安装。它不需要安装 node.js 但你需要 node 来使用 NPM 安装 D3。确保package-lock.json该node_modules文件夹edge.js在运行时与文件位于同一目录中,或全局安装。我只是npm i d3-array从\edge文件夹内部运行,然后包含 *.json 和 *.js 文件,将它们设置为内容并复制到输出目录。然后就这么简单:
class Program {
public static async Task Start(int[] someArray) {
var func = Edge.Func(@"
var d3 = require('d3-array')
return function (data, callback) {
callback(null, 'D3 says: ' + d3.min(data));
}
");
Console.WriteLine(await func(someArray));
}
static void Main(string[] args) {
Start(new int[] { 1, 2, 3, 4 }).Wait();
}
}
Outputs: D3 says: 1
输出: D3 says: 1
NOTE: In .Net7.2 i had to install the Edge.Js.BinariesNuGet package to install the edge folder in the project root. The Edge.Jspackage didn't do this, in 4.5 it did.
注意:在 .Net7.2 中,我必须安装Edge.Js.BinariesNuGet 包才能在项目根目录中安装 edge 文件夹。这个Edge.Js包没有这样做,在 4.5 中它做了。

