65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.60/5 (3投票s)

2016年8月16日

CPOL

3分钟阅读

viewsIcon

20217

downloadIcon

63

本文介绍如何创建包含 d3js 饼图的 ASP.NET Web 窗体。

引言

主要目的是展示如何创建一个服务器网页,将数据发送到 JavaScript 可视化函数。由于网页上对不同类型的交互式图表的需求日益增长,并且客户端 js 库变得更好用和更容易使用,因此在服务器应用程序中集成不同的演示框架是 Web 编程中一项重要且流行的任务。有很多种选择。在本文中,d3js 库被用作可视化工具,数据准备工作在 ASP.NET Web 窗体中完成。

下一部分展示如何在 ASP.NET 网页上放置 d3js 饼图并使用一些数据初始化它。

创建 ASP.NET Web 窗体

  1. 创建一个新的空 ASP.NET Web 项目 (AspNetToJs)。添加新的 Web 窗体 *ShowDataV1.aspx*。
  2. 在解决方案中创建一个文件夹“*scripts*”。将 d3js 库添加到其中。我使用的是版本 4。
  3. 添加一个引用 d3js 的脚本管理器。如果要使 JavaScript 部分更加复杂,脚本管理器可能会很有用。或者只是在 head 部分添加 script 标签。
    <form id="form1" runat="server">
            <asp:ScriptManager runat="server">
                <Scripts>
                    <asp:ScriptReference Path="~/scripts/d3.min.js" />
                </Scripts>
            </asp:ScriptManager
  4. 确定如何从数据源获取数据。在此示例中,我使用了具有以下简单结构的对象集合
    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" }
     };

    在实际项目中,它很可能是一个数据库查询。

  5. 将两个占位符添加到网页。附加一个 HTML 元素用于饼图,另一个用于详细信息。当鼠标放置在指定的扇区上时,页面将在单独的 HTML 元素(id = svg_panel_txtdiv)中显示详细信息(ActionDetails 属性)。
    <div>
       <svg id="svg_panel" width="280" height="280"></svg>
       <div id="svg_panel_txt"></div>
    </div>
  6. 添加客户端可视化代码,它将构建饼图。以下脚本应插入到 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_idsvg 元素内创建一个新图表。此代码是在 d3js 网站上的一个示例的帮助下创建的。

  7. 到现在为止,应该没有构建或运行时错误。如果一切正常,添加数据准备代码,该代码创建一个对象集合,每个对象代表一个切片。为了使我们的可视化函数可以访问此数据,我们将添加一个 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 是一个公开客户端事件并管理已向应用程序注册的客户端组件的对象。在客户端应用程序初始化后,此对象的成员全局可用”。

  8. 有几种方法可以从代码隐藏将 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 属性来获得相同的效果。

© . All rights reserved.