使用 d3js 创建饼图 - ASP.NET 和 JavaScript 集成示例






4.60/5 (3投票s)
本文介绍如何创建包含 d3js 饼图的 ASP.NET Web 窗体。
引言
主要目的是展示如何创建一个服务器网页,将数据发送到 JavaScript 可视化函数。由于网页上对不同类型的交互式图表的需求日益增长,并且客户端 js 库变得更好用和更容易使用,因此在服务器应用程序中集成不同的演示框架是 Web 编程中一项重要且流行的任务。有很多种选择。在本文中,d3js 库被用作可视化工具,数据准备工作在 ASP.NET Web 窗体中完成。
下一部分展示如何在 ASP.NET 网页上放置 d3js 饼图并使用一些数据初始化它。
创建 ASP.NET Web 窗体
- 创建一个新的空 ASP.NET Web 项目 (
AspNetToJs
)。添加新的 Web 窗体 *ShowDataV1.aspx*。 - 在解决方案中创建一个文件夹“*scripts*”。将 d3js 库添加到其中。我使用的是版本 4。
- 添加一个引用 d3js 的脚本管理器。如果要使 JavaScript 部分更加复杂,脚本管理器可能会很有用。或者只是在
head
部分添加script
标签。<form id="form1" runat="server"> <asp:ScriptManager runat="server"> <Scripts> <asp:ScriptReference Path="~/scripts/d3.min.js" /> </Scripts> </asp:ScriptManager
- 确定如何从数据源获取数据。在此示例中,我使用了具有以下简单结构的对象集合
public class UserActionsData { public string ActionCode { get; set; } public int ActionCount { get; set; } public string ActionDetails { get; set; } }
UserActionsData
数组将被传递给 d3js,以便创建一个交互式饼图,该图在单独的块中显示有关所选切片的详细信息。这是本例中使用的一些数据List<UserActionsData> sample_data = new List<UserActionsData> { new UserActionsData { ActionCode="A1", ActionCount=20, ActionDetails="Description for action 1" }, new UserActionsData { ActionCode="A2", ActionCount=70, ActionDetails="Description for action 2" }, new UserActionsData { ActionCode="A3", ActionCount=40, ActionDetails="Description for action 3" }, new UserActionsData { ActionCode="A4", ActionCount=35, ActionDetails="Description for action 4" }, new UserActionsData { ActionCode="A5", ActionCount=15, ActionDetails="Description for action 5" } };
在实际项目中,它很可能是一个数据库查询。
- 将两个占位符添加到网页。附加一个 HTML 元素用于饼图,另一个用于详细信息。当鼠标放置在指定的扇区上时,页面将在单独的 HTML 元素(
id = svg_panel_txt
的div
)中显示详细信息(ActionDetails
属性)。<div> <svg id="svg_panel" width="280" height="280"></svg> <div id="svg_panel_txt"></div> </div>
- 添加客户端可视化代码,它将构建饼图。以下脚本应插入到
head
标签中<script type="text/javascript"> // svg_id - id of target svg // data - array of objects {label, value} function drawPieChartSVG(svg_id, data) { var svg = document.getElementById(svg_id); var width = svg.width.baseVal.value, height = svg.height.baseVal.value, radius = Math.min(width, height) / 2; var colors = d3.scaleOrdinal(d3.schemeCategory10); var arc = d3.arc() .outerRadius(radius - 10) .innerRadius(0) .padAngle(0.03); var pie = d3.pie().value(function (d) { return d.value; }); var root = d3.select("#" + svg_id) .datum(data) .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(" + width / 2.0 + "," + height / 2.0 + ")"); var arcs = root .selectAll("g.slice") .data(pie) .enter() .append("g") .attr("class", "slice"); arcs .append("path") .attr("fill", function (d, i) { return colors(i); }) .attr("d", arc) // show details in the separate html element when mouse is over the specified sector .on("mouseover", function (d, i) { var txt = document.getElementById(svg_id + "_txt"); if (txt) { txt.innerHTML = d.data.label + " (" + d.data.value + ")"; } }); // place labels on the chart arcs.append("svg:text") .attr("transform", function (d) { d.innerRadius = radius / 2.0; d.outerRadius = radius; // text will be inserted in the center of the current section return "translate(" + arc.centroid(d) + ")";}) .attr("text-anchor", "middle") // d.data - our data item, assigned to the current section. "label" is a part of our data object .text(function (d, i) { return d.data.label; }); } </script>
函数
drawPieChartSVG
从数组“data
”中在 id 为svg_id
的svg
元素内创建一个新图表。此代码是在 d3js 网站上的一个示例的帮助下创建的。 - 到现在为止,应该没有构建或运行时错误。如果一切正常,添加数据准备代码,该代码创建一个对象集合,每个对象代表一个切片。为了使我们的可视化函数可以访问此数据,我们将添加一个 JavaScript 变量,将 JSON 字符串分配给它,然后将其传递给该函数。
//data for the pie chart var pie_chart_data = []; //draw the pie chart function updateChart() { drawPieChartSVG("svg_panel", pie_chart_data); }
在
scriptmanager
标签之后添加另一个代码,以便在加载所有脚本后调用updateChart
。<script type="text/javascript"> Sys.Application.add_load(updateChart); </script>
Sys.Application
是 ASP.NET Ajax 客户端应用程序对象。正如 MSDN 中所述,“
Sys.Application
是一个公开客户端事件并管理已向应用程序注册的客户端组件的对象。在客户端应用程序初始化后,此对象的成员全局可用”。 - 有几种方法可以从代码隐藏将 JavaScript 注入 HTML 页面。我们将通过 C# 中准备的 JavaScript 将值分配给变量。
代码隐藏protected void Page_Load(object sender, EventArgs e) { var serializer = new JavaScriptSerializer(); var str_sample_data = serializer.Serialize(sample_data); // add script tag to the page this.ClientScript.RegisterClientScriptBlock(this.GetType(), "mydata", "<script>pie_chart_data = " + str_sample_data + ";</script>"); }
生成的 JavaScript 代码将附加在 UI 元素之前。因此,数据将在 updateChart
函数调用时准备就绪。
自定义饼图读取数据的方式
现在让我们更改 JavaScript 代码以使其正确读取数据。
定义哪个字段保存每个切片的大小。它是“ActionCount
”。更改此行
var pie = d3.pie().value(function (d) { return d.value; });
将其更改为此行以使其与我们的数据兼容
var pie = d3.pie().value(function (d) { return d.ActionCount; });
替换行
.text(function (d, i) { return d.data.label; });
用这个:
.text(function (d, i) { return d.data.ActionCode; });
mouseover
事件处理程序应如下所示
function (d, i) {
var txt = document.getElementById(svg_id + "_txt");
if (txt) {
txt.innerHTML = d.data.ActionDetails + " (" + d.data.ActionCount + ")";
}
}
结果
运行 Web 窗体。预期结果如下所示
结论
新版本的 d3js 与以前的版本截然不同。
虽然此饼图是在加载网页后立即构建的,但 d3js 图表也可以在运行时动态更新。
无需调用 ClientScript.RegisterClientScriptBlock
,也可以通过将 script
标签传递给 asp:Label
控件元素的 Text
属性来获得相同的效果。