【问题标题】:Having issue to display line chart using d3.js in .NET MVC C# project在 .NET MVC C# 项目中使用 d3.js 显示折线图时出现问题
【发布时间】:2019-12-26 20:33:46
【问题描述】:

我正在尝试集成图表库 d3.js,我有其他图表库的经验,但我面临使用 d3.js 库显示折线图的问题,我分享了 MVC c# 项目的以下代码,我不知道'不知道为什么图表不呈现,谁能帮我解决这个问题,代码中的问题是什么。

以下是图表渲染的图像,我的图表是用x轴和y轴点渲染的,但没有画线,代码到底有什么问题。

Chart.cshtml

@{
    ViewBag.Title = "Index";
    Layout = null;
}

@section featured {
    <section class="featured">
        <div class="content-wrapper">
            <hgroup class="title">
                <h1>@ViewBag.Title - </h1>
            </hgroup>
        </div>
    </section>
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.14.2/d3.js" charset="utf-8"></script>
<style type="text/css">
    #chart text {
        fill: white;
        font: 10px sans-serif;
        text-anchor: end;
    }

    .axis text {
        font: 10px sans-serif;
    }

    .axis path, .axis line {
        fill: none;
        stroke: #fff;
        shape-rendering: crispEdges;
    }

    body {
        background: #1a1a1a;
        color: #eaeaea;
        padding: 10px;
    }

    path {
        stroke: steelblue;
        stroke-width: 2;
        fill: none;
    }
</style>
<div id="chart" height="120" width="120"></div>
<script type="text/javascript">
    var salesData;

    $(document).ready(function () {
        Plot();
    });

    function Plot() {
        var yearData;
        var salesData;

        var data =
            [
                { 'Year': '2008', 'Sale': 2000 },
                { 'Year': '2009', 'Sale': 4000 },
                { 'Year': '2015', 'Sale': 5000 }
            ]

        yearData = GetYears(data)
        salesData = GetSales(data)

        var margin = { top: 20, right: 30, bottom: 30, left: 40 },
            width = 1000 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

        var chart = d3.select("#chart")
            .append("svg") //append svg element inside #chart
            .attr("width", width + (2 * margin.left) + margin.right) //set width
            .attr("height", height + margin.top + margin.bottom); //set height

        var x = d3.scale.ordinal().domain(yearData).rangePoints([margin.left, width]);
        var y = d3.scale.linear().domain(salesData).range([height, 0]);

        var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom").ticks(data.Year); //orient bottom because x-axis will appear below the bars
        var yAxis = d3.svg.axis()
            .scale(yes) 
            .orient("left").ticks(10);

        // Define the line
        var valueline = d3.svg.line()
            .x(function (d) { return x(d.year); })
            .y(function (d) { return y(d.Sale); });


        chart.append("g")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

        chart.append("g")
            .attr("class", "y axis")
            .attr("transform", "translate(" + margin.left + ",0)")
            .call(yAxis)
            .append("text")
            .attr("y", 6)
            .text("Sales Data");

        // Add the valueline path.
        chart.append("path")
            //.attr("class", "line")
            .attr("d", valueline(data));
    }

    function GetYears(data) {
        var result = [];
        for (var i in data)
            result.push(data[i].Year);

        return result;
    }

    function GetSales(data) {
        var result = [];
        var max = 0.0;
        result.push(max);
        for (var i in data) {
            if (max < data[i].Sale) {
                max = data[i].Sale
            }
        }
        result.push(max + 50);
        return result;
    }
</script>

【问题讨论】:

  • 作为类型的行的访问器。需要.x(function (d) { return x(d.Year); })
  • + GetYears 返回 3 个元素,但 GetSales 返回 2 个元素。

标签: c# asp.net-mvc d3.js charts


【解决方案1】:

在将数据传递给图表之前,我没有使用GetYearsGetSales 方法,而是从输入数据中获取年份和销售额。例如,在将数据传递到图表之前,我将年份从 string 转换为 Date

var chartData = Array.from(data,
    p => ({ Date: new Date(p.Year, 1, 1), Sale: p.Sale }));

然后在 x 轴上显示年份范围。

代码中还有一些其他问题,例如GetYears 返回了 3 个元素,但 GetSales 返回了 2 个元素,或者您使用的某些函数显然属于不同的版本,例如您使用的是 scale.linearscaleLinear 以及一些错字,例如使用year 而不是Year 或使用yes 而不是y

要查看结果,只需点击底部的Run code sn-p。我把图表做得更小一点,以便在演示中显示。现在你有了一个工作代码,你可以开始定制它了。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.14.2/d3.js"
            charset="utf-8"></script>
    <title>Sample</title>
    <style type="text/css">
        #chart text {
            fill: white;
            font: 10px sans-serif;
            text-anchor: end;
        }

        .axis text {
            font: 10px sans-serif;
        }

        .axis path, .axis line {
            fill: none;
            stroke: #fff;
            shape-rendering: crispEdges;
        }

        body {
            background: #1a1a1a;
            color: #eaeaea;
            padding: 10px;
        }

        path {
            stroke: steelblue;
            stroke-width: 2;
            fill: none;
        }
    </style>
</head>
<body>
    <div id="chart"></div>
    <script>
        function Plot() {
            //Input data
            var data =
                [
                    { 'Year': '2008', 'Sale': 2000 },
                    { 'Year': '2009', 'Sale': 4000 },
                    { 'Year': '2015', 'Sale': 5000 }
                ]

            //Format data for the chart
            var chartData = Array.from(data,
                p => ({ Date: new Date(p.Year, 1, 1), Sale: p.Sale }));

            //Setup margin
            var margin = { top: 30, right: 30, bottom: 35, left: 50 },
                width = 400 - margin.left - margin.right,
                height = 300 - margin.top - margin.bottom;

            //Create chart
            var chart = d3.select("#chart")
                .append("svg")
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
                .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            //Setup X axis
            var x = d3.scaleTime()
                .domain(d3.extent(chartData, function (d) { return d.Date; }))
                .range([0, width]);
            chart.append("g")
                .attr("transform", "translate(0," + height + ")")
                .call(d3.axisBottom(x))
                .append("text")
                .text("Year")
                .attr("x", 0 + (width / 2))
                .attr("y", 0 + margin.bottom)
                .attr("dx", "1em")
                .style("text-anchor", "middle");

            //Setup Y axis
            var y = d3.scaleLinear()
                .domain([0, d3.max(chartData, function (d) { return d.Sale; })])
                .range([height, 0]);
            chart.append("g")
                .call(d3.axisLeft(y).ticks(10))
                .append("text")
                .text("Sales data")
                .attr("transform", "rotate(-90)")
                .attr("y", 0 - margin.left)
                .attr("x", 0 - (height / 2))
                .attr("dy", "1em")
                .style("text-anchor", "middle");

            //Add line
            chart.append("path")
                .datum(chartData)
                .attr("fill", "none")
                .attr("stroke", "steelblue")
                .attr("stroke-width", 1.5)
                .attr("d", d3.line()
                    .x(function (d) { return x(d.Date) })
                    .y(function (d) { return y(d.Sale) })
                );
        }
        Plot();
    </script>
</body>
</html>

【讨论】:

  • 您已经通过运行和显示图表解决了这个问题,但图表中仍然缺少一些东西,因为它的显示方式错误。
  • 图表中仍然缺少一些东西 → 事实上,我展示了应用其他更改的起点。更大的问题是 IMO 根本没有运行图表。如果我知道确切的要求,就很容易应用它们。使用日期,我认为scaleTime 更合适,但很容易将其更改为序数。其余更改相同:)
【解决方案2】:

#chart text {
  fill: white;
  font: 10px sans-serif;
  text-anchor: end;
}

.axis text {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #fff;
  shape-rendering: crispEdges;
}

body {
  background: #1a1a1a;
  color: #eaeaea;
  padding: 10px;
}

path {
  stroke: steelblue;
  stroke-width: 2;
  fill: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.js" charset="utf-8"></script>

<div id="chart"></div>

<script type="text/javascript">
  var salesData;

  $(document).ready(function() {
    Plot();
  });

  function Plot() {
    var yearData;
    var salesData;

    var data = [{
        'Year': '2012',
        'Sale': 2000
      },
      {
        'Year': '2014',
        'Sale': 3000
      },
      {
        'Year': '2015',
        'Sale': 5000
      }
    ]

    yearData = GetYears(data)
    salesData = GetSales(data)

    var margin = {
        top: 20,
        right: 30,
        bottom: 30,
        left: 40
      },
      width = 1000 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

    var chart = d3.select("#chart")
      .append("svg") //append svg element inside #chart
      .attr("width", width + (2 * margin.left) + margin.right) //set width
      .attr("height", height + margin.top + margin.bottom); //set height


    var x = d3.scale.ordinal().domain(yearData).rangePoints([margin.left, width]);
    var y = d3.scale.linear().domain(salesData).range([height, 0]);


    var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom").ticks(data.Year); //orient bottom because x-axis will appear below the bars
    var yAxis = d3.svg.axis()
      .scale(y)
      .orient("left").ticks(10);

    // Define the line
    var valueline = d3.svg.line()
      .x(function(d) {
        return x(d.Year);
      })
      .y(function(d) {
        return y(d.Sale);
      });


    chart.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

    chart.append("g")
      .attr("class", "y axis")
      .attr("transform", "translate(" + margin.left + ",0)")
      .call(yAxis)
      .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Sales Data");

    // Add the valueline path.
    chart.append("path")
      .attr("class", "line")
      .attr("d", valueline(data));


  }


  function GetYears(data) {
    var result = [];
    for (var i in data)
      result.push(data[i].Year);

    return result;
  }

  function GetSales(data) {
    var result = [];
    var max = 0.0;
    result.push(max);
    for (var i in data) {
      if (max < data[i].Sale) {
        max = data[i].Sale
      }
    }
    result.push(max + 50);

    return result;
  }
</script>

@RaghavThakka 似乎 javascript 文件中的一些配置点需要更改,甚至正在使用的 Year 属性也是错误的。它区分大小写。

我仅使用您的代码添加了示例 sn-p,并对 javascript 代码进行了一些更改。

请自行验证。

【讨论】:

  • 干得好,感谢您解决问题,这就是我想要的,问题已通过您的示例 sn-p 解决,因为我们的答案如预期的那样准确。非常感谢。
【解决方案3】:

我查看了您的代码,发现您使用的是 D3 5.14.2,但您在代码中使用的某些功能在此版本中已弃用。我对代码做了一些修改,希望对你有所帮助。

如果您需要更多示例,请查看link

<script type="text/javascript">
        var salesData;

        $(document).ready(function () {
            Plot();
        });

        function Plot() {
            var salesData;

            var data =
                [
                    { 'Year': '2008', 'Sale': 2000 },
                    { 'Year': '2009', 'Sale': 4000 },
                    { 'Year': '2015', 'Sale': 5000 }
                ]

            salesData = GetSales(data)

            var margin = { top: 20, right: 30, bottom: 30, left: 40 },
                width = 1000 - margin.left - margin.right,
                height = 500 - margin.top - margin.bottom;

            var chart = d3.select("#chart")
                .append("svg") //append svg element inside #chart
                .attr("width", width + (2 * margin.left) + margin.right) //set width
                .attr("height", height + margin.top + margin.bottom); //set height

            var x = d3.scaleTime()
                .domain(d3.extent(data, function (d) { return d3.timeParse("%Y")(d.Year); }))
                .range([margin.left, width])
            chart.append("g")
                .attr("transform", "translate(0," + height + ")")
                .call(d3.axisBottom(x));

            var y = d3.scaleLinear()
                .domain(salesData)
                .range([height, 0])
            chart.append("g")
                .attr("class", "y axis")
                .attr("transform", "translate(" + margin.left + ",0)")
                .call(d3.axisLeft(y))
                .append("text")
                .text("Sales Data");

            // Add the valueline path.
            chart.append("path")
                .datum(data)
                .attr("fill", "none")
                .attr("stroke", "steelblue")
                .attr("stroke-width", 1.5)
                .attr("d", d3.line()
                    .x(function (d) { return x(d3.timeParse("%Y")(d.Year)) })
                    .y(function (d) { return y(d.Sale) })
                )
        }

        function GetYears(data) {
            var result = [];
            for (var i in data)
                result.push(data[i].Year);

            console.log(result);

            return result;
        }

        function GetSales(data) {
            var result = [];
            var max = 0.0;
            result.push(max);
            for (var i in data) {
                if (max < data[i].Sale) {
                    max = data[i].Sale
                }
            }
            result.push(max + 50);

            console.log(result);
            return result;
        }
</script>

【讨论】:

  • 感谢您的意见,但似乎它对我不起作用,我也已经尝试过,但它不起作用。所以让我们等待另一个选项或另一个可以帮助我的答案。谢谢
  • @Raghav Thakkar,浏览器控制台有错误吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-19
  • 2018-01-22
  • 1970-01-01
  • 1970-01-01
  • 2013-01-09
  • 1970-01-01
相关资源
最近更新 更多