Tales
Tales

Reputation: 303

Area chart using dc.js and crossfilter

I have created a line chart using dc.js and crossfilter. The chart currently looks like this:

line chart

Required: I want the legend of active inactive on top left to position below(bottom) of the chart in center and the x-axis tick label should start from Jan to Dec. I am adding my code below. Thank you.

const dateNames = ["January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December"
];


var data = [
    {date: "2011-11-14T16:17:54Z", quantity: 2, active: 1000, inactive: 100, type: "tab", city: " "},
    {date: "2011-11-14T16:20:19Z", quantity: 2, active: 190, inactive: 100, type: "tab", city: "Berlin"},
    {date: "2011-11-14T16:28:54Z", quantity: 1, active: 300, inactive: 200, type: "visa", city: " "},
    {date: "2011-11-14T16:30:43Z", quantity: 2, active: 90, inactive: 0, type: "tab", city: "Amsterdam"},
    {date: "2011-11-14T16:48:46Z", quantity: 2, active: 90, inactive: 0, type: "tab", city: " "},
    {date: "2011-11-14T16:53:41Z", quantity: 2, active: 90, inactive: 0, type: "tab", city: " "},
    {date: "2011-11-14T16:54:06Z", quantity: 1, active: 100, inactive: 0, type: "cash", city: " "},
    {date: "2011-11-14T16:58:03Z", quantity: 2, active: 90, inactive: 0, type: "tab", city: " "},
    {date: "2011-11-14T17:07:21Z", quantity: 2, active: 90, inactive: 0, type: "tab", city: " "},
    {date: "2011-11-14T17:22:59Z", quantity: 2, active: 90, inactive: 0, type: "tab", city: " "},
    {date: "2011-11-14T17:25:45Z", quantity: 2, active: 200, inactive: 0, type: "cash", city: " "},
    {date: "2011-11-14T17:29:52Z", quantity: 1, active: 200, inactive: 100, type: "visa", city: ""}
  ];

  data.forEach(function(d){
    var tempDate = new Date(d.date);
    d.date = tempDate;
  
  })
  
  var facts = crossfilter(data);
  var all = facts.groupAll();
  
  
  //table
  var dateDimension = facts.dimension(function(d){ return d.date; });
  //line chart
  
  var dateGroup = dateDimension.group().reduceSum(function(d){ return d.active; });
  var dateGroupTip = dateDimension.group().reduceSum(function(d){ return d.inactive; });
  
  var minDate = dateDimension.bottom(1)[0].date;
  var maxDate = dateDimension.top(1)[0].date;

  var lineChart = dc.lineChart("#test")
    .width(700)
    .height(200)
    .brushOn(false)
    .margins({top:10,bottom:30,right:10,left:70})
    .dimension(dateDimension)
    .group(dateGroupTip,"inactive")
    .stack(dateGroup,"active")

    .renderHorizontalGridLines(true)
    .renderArea(true)
    .renderDataPoints(true)
    // // .interpolate('basis')
    // lineChart.xAxis().ticks(d3.timeMonth, 1)
    // lineChart.xAxis().tickFormat(d3.timeFormat('%b'))
    .clipPadding(data.length)
    .legend(dc.legend().y(10).x(0).itemHeight(12).gap(5))
    // .xAxis()
    // .ticks(d3.time.month, 7)
    // .tickFormat(d3.time.format('%e'));
    // .xAxis().tickFormat(d3.time. format('%B'))
    // .xUnits(d3.time.months)
    .x(d3.scaleLinear().domain([minDate,maxDate]))
    lineChart.yAxis().ticks(6);
    lineChart.xAxis().ticks(12);

dc.renderAll();
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" type="text/css" href="dc.css"/>

    <script src="d3.js"></script>
    <script src="crossfilter.js"></script>
    <script src="dc.js"></script>
</head>
<body>
    <div id="test"></div>
    <!-- <script src="app.js"></script> -->
    <script src="play.js"></script>
</body>
</html>

Upvotes: 3

Views: 210

Answers (1)

Gordon
Gordon

Reputation: 20140

Looks like you've figured most of it out, and got confused by the D3 version 3 to version 4 API changes?

Many of the lines you have commented out were correct except for these changes - stuff like d3.time.months changing to d3.timeMonths. You're not the only one - these changes caused a lot of confusion for all of us.

The last steps are

  1. Use time scales: .x(d3.scaleTime().domain([minDate,maxDate]))
  2. Round the dates down to the beginning of the month using d3.timeMonth, both in the dimension definition and in the minDate/maxDate calculation, e.g. var dateDimension = facts.dimension(function(d){ return d3.timeMonth(d.date); });
  3. Tell the chart how to calculate the number of points to show: .xUnits(d3.timeMonths)
  4. Format the x axis ticks: lineChart.xAxis().tickFormat(d3.timeFormat('%B'))

You had most of these, only commented out. Probably because you found examples using the D3v3 API, and they caused errors?

As for the legend, dc.js doesn't do anything sophisticated here - you just have to lay it out manually, setting the margins on the chart to allow enough space, and setting x and y on the legend to put the legend where you want it.

I found that

lineChart
    .margins({top:10,bottom:60,right:25,left:40});
    .legend(dc.legend().y(165).x(325).itemHeight(12).gap(5))

worked pretty well, but you'll have to adjust it to taste (and, unfortunately, when changes to your data cause the sizes of things to change).

screenshot with time scale and bottom legend

Here's a working fiddle.. I took the liberty of changing your example data so that it includes the desired months.

You're going to run into trouble with this design if your data spans multiple years, but I guess you can cross that bridge when you come to it.

Upvotes: 1

Related Questions