nvd3折线图在X轴上显示日期刻度值

时间:2014-05-01 16:00:51

标签: javascript asp.net-mvc web nvd3.js

我需要在我的网站项目中添加折线图。它需要在x轴上有日期值,在y轴上有整数。目前数据显示如下:

enter image description here

我需要它显示在这个excel版本中:

enter image description here

我无法正确地将数据与x轴对齐,并且我无法在x轴上获取标签以显示正确的日期。我的网页(使用Razor语法)设置如下:

<style>
svg {
display: block;
}

#chart1 svg{
height: 500px;
min-width: 100px;
min-height: 100px;

}
</style>
<script>

var chart;

var data2 = JSON.parse(@Html.Raw(Json.Encode(ViewBag.data)));

var data = data2[0];

nv.addGraph(function() {

  chart = nv.models.lineChart();

  chart
  .x(function(d,i) 
  {     
   return i;
    })


  chart.xAxis 
  .tickFormat(function(d) 
  {      
   return d3.time.format('%b %d')(new Date(d));
    })


  chart.yAxis
  .axisLabel('Voltage (v)')
  .tickFormat(d3.format(',.2f'));

    chart.showXAxis(true);

    d3.select('#chart1 svg')
    //.datum([]) //for testing noData
    .datum(data)
.transition().duration(500)
    .call(chart);

      nv.utils.windowResize(chart.update);


    chart.dispatch.on('stateChange', function(e) { nv.log('New State:', JSON.stringify(e)); });

      return chart;
       });

      </script>

数据以正确的格式传入。有什么想法吗?

@ ViewBag.name

       

1 个答案:

答案 0 :(得分:2)

好的,我设法修复它,但这有点像黑客。在控制器中,我用整数索引替换了JSON数据中的日期。我通过找到最小日期,将其设置为x轴索引为0,将下一个日期设置为1等等来解决这些问题。 然后,我将格式化日期的JSON数组传递给控制器​​的视图,以便您可以使用索引查找日期。 控制器代码:

 public ActionResult MileageReport(DateTime startDate, DateTime endDate)
    {
        using (EventsManager manager = new EventsManager())
        {
            IEnumerable<Event> travelEvents = manager.GetEventsWhere(t => t.Eventtype == EventType.Travel.ToString() && t.Createddt > startDate && t.Createddt < endDate);
            Dictionary<DateTime, int> mappedDates = MapDatesToIndices(travelEvents);
            var groupedEvents = travelEvents.GroupBy(e => e.Userid);
            JArray jsonArray = new JArray();
            IColourPicker colourPicker = NinjectFactory.GetNinJectKernel().Get<IColourPicker>();
            int i = 0;

            List<Event> events, tempEvents;
            List<DateTime> days;
            Event travelEvent;

            foreach (IGrouping<string, Event> group in groupedEvents)
            {
                //we only want the last event for each day
                events = group.ToList();

                days = events.Select(e => e.Createddt.Value.Date).Distinct().OrderBy(o => o).ToList();

                dynamic tEvent = new ExpandoObject();
                tEvent.key = group.Key;
                tEvent.color = colourPicker.GetColour(i);

                JArray tEvents = new JArray();
                foreach (DateTime day in days)
                {
                    tempEvents = events.Where(e => e.Createddt.Value.Date == day).ToList();
                    travelEvent = tempEvents.Single(e => e.Mileage.Value == tempEvents.Select(m => m.Mileage.Value).Max());
                    object tvObj = new { x = mappedDates[travelEvent.Createddt.Value.Date], y = travelEvent.Mileage };

                    tEvents.Add(JObject.FromObject(tvObj));
                }
                tEvent.values = tEvents;
                jsonArray.Add(JObject.FromObject(tEvent));
                i++;
            }




            string jsonStringTemp = jsonArray.ToString();

            string jsonString = FormatJsonString(jsonStringTemp);
            ViewBag.xaxislabels = FormatDatesForIndices(mappedDates);
            ViewBag.data = jsonString;
            ViewBag.name = "Mileage Report";
            return PartialView("LineGraph");


        }
    }

    private dynamic FormatDatesForIndices(Dictionary<DateTime, int> mappedDates)
    {
        List<DateTime> dates = mappedDates.Keys.ToList();

        object[] items = new object[dates.Count];


        for (int i = 0; i < dates.Count; i++)
        {
            items[i] = new { date = dates[i].ToString(BaseFormats.DateDisplayFormatNoYear) };
        }

        JavaScriptSerializer js = new JavaScriptSerializer();
        string jsonString = js.Serialize(items);


        return jsonString;
    }

    private Dictionary<DateTime, int> MapDatesToIndices(IEnumerable<Event> travelEvents)
    {
        Dictionary<DateTime, int> mappedDates = new Dictionary<DateTime, int>();

        List<DateTime?> dts = travelEvents.Select(t => t.Createddt).ToList();

        dts = dts.Where(d => d != null).ToList();

        DateTime min = dts.Min().Value.Date;
        DateTime max = dts.Max().Value.Date;

        int i = 0;

        mappedDates.Add(min, i);

        min = min.AddDays(1);

        while (min.Date <= max.Date)
        {
            ++i;
            mappedDates.Add(min, i);
            min = min.AddDays(1);
        }

        return mappedDates;
    }

然后在视图中我覆盖x函数以返回我放入JSON数据的x值。我也覆盖了tickformat以返回我传递给视图的格式化日期。 查看代码:

<style>
 svg {
 display: block;
 }

 #chart1 svg{
  height: 500px;
  min-width: 100px;
  min-height: 100px;

}
</style>
<script>

var chart;

var data2 = JSON.parse(@Html.Raw(Json.Encode(ViewBag.data)));

var data = data2[0];

var m_xaxisLabels = JSON.parse(@Html.Raw(Json.Encode(ViewBag.xaxislabels)));

nv.addGraph(function() {

 chart = nv.models.lineChart();


 chart
  .x(function(d,i) 
  {     
   return d.x;
    })

   chart.xAxis.tickFormat(function(d, i){
     return m_xaxisLabels[d].date;
   });

  chart.yAxis
  .axisLabel('Voltage (v)')
  .tickFormat(d3.format(',.2f'));

  chart.showXAxis(true);

  d3.select('#chart1 svg')
  .datum(data)
.transition().duration(500)
  .call(chart);

  nv.utils.windowResize(chart.update);

 chart.dispatch.on('stateChange', function(e) { nv.log('New State:', JSON.stringify(e)); });

 return chart;
});

</script>


<h2>@ViewBag.name</h2>
<div id="chart1">
<svg></svg>
</div>

现在它有效!:

enter image description here