如何在带有scaleTime的条形图中使用x和宽度?

时间:2018-01-16 10:22:44

标签: javascript d3.js data-visualization

我在这里有一个codepen - https://codepen.io/anon/pen/xpaYYw?editors=0010

它是一个简单的测试图,但日期将格式化为这样。

我在x轴上有日期,在y

上有金额

如何使用x刻度来设置条形的宽度和x位置。

    layers.selectAll('rect')
      .data(data)
      .enter()
      .append('rect')

      .attr('height', function(d, i) {
        return height - y(d.one);
      })

      .attr('y', function(d, i) {
        return y(d.one);
      })

      .attr('width', function(d, i) {
        return 50;
      })

      .attr('x', function(d, i) {
        return 80*i;
      })

      .style('fill', (d, i) => {
        return colors[i];
      });

1 个答案:

答案 0 :(得分:4)

您的问题与编程,JavaScript或D3无关......问题是基本的dataviz概念(这就是我在您的问题中添加标记的原因):

你要做的不正确!您应该使用带有时间刻度的条形图。时间刻度用于时间序列(我们使用点或线连接的点)。

如果在x轴上使用带时间的条,则会遇到问题:

  1. 定位栏:栏的左边距始终为您设置的日期。整个栏将在那个日期之后;
  2. 设置条形图的宽度:在实际条形图中,对x轴使用分类变量,宽度没有意义。但在时间范围内,宽度代表时间
  3. 然而,仅仅为了解释,让我们创建一个带有时间尺度的条形图(尽管这是一个错误的选择)...以下是如何做到的:< / p>

    首先,在时间中设置条形的“宽度”。比方说,每个条的宽度为10天:

    private void DeleteButton_Clicked(object sender, RoutedEventArgs e)
    {
        Button deleteButton = sender as Button;
        var portfolio = deleteButton.DataContext as Portfolio; //or whatever your type is called
    
        //access any members of the portfolio...
    }
    

    然后,将条形的.attr("width", function(d){ return x(d3.timeDay.offset(d.date, 10)) - x(d.date) }) 位置设置为当前日期的宽度(即,在我们的示例中减去5天):

    x

    最后,不要忘记在时间范围内创建“填充”:

    .attr('x', function(d, i) {
        return x(d3.timeDay.offset(d.date, -5));
    })
    

    以下是包含这些更改的代码:

    var x = d3.scaleTime()
      .domain([d3.min(data, function(d) {
        return d3.timeDay.offset(d.date, -10);
      }), d3.max(data, function(d) {
        return d3.timeDay.offset(d.date, 10);
      })])
      .range([0, width]);
    
    var keys = [];
    var legendKeys = [];
    
    var maxVal = [];
    
    var w = 800;
    var h = 450;
    
    var margin = {
      top: 30,
      bottom: 40,
      left: 50,
      right: 20,
    };
    
    var width = w - margin.left - margin.right;
    var height = h - margin.top - margin.bottom;
    
    var colors = ['#FF9A00', '#FFEBB6', '#FFC400', '#B4EDA0', '#FF4436'];
    
    var data = [{
        "one": 4306,
        "two": 2465,
        "three": 2299,
        "four": 988,
        "five": 554,
        "six": 1841,
        "date": "2015-05-31T00:00:00"
      }, {
        "one": 4378,
        "two": 2457,
        "three": 2348,
        "four": 1021,
        "five": 498,
        "six": 1921,
        "date": "2015-06-30T00:00:00"
      }, {
        "one": 3404,
        "two": 2348,
        "three": 1655,
        "four": 809,
        "five": 473,
        "six": 1056,
        "date": "2015-07-31T00:00:00"
      },
    
    ];
    
    data.forEach(function(d) {
      d.date = new Date(d.date)
    })
    
    for (var i = 0; i < data.length; i++) {
      for (var key in data[i]) {
        if (!data.hasOwnProperty(key) && key !== "date")
          maxVal.push(data[i][key]);
      }
    }
    
    var x = d3.scaleTime()
      .domain([d3.min(data, function(d) {
        return d3.timeDay.offset(d.date, -10);
      }), d3.max(data, function(d) {
        return d3.timeDay.offset(d.date, 10);
      })])
      .range([0, width]);
    
    var y = d3.scaleLinear()
      .domain([0, d3.max(maxVal, function(d) {
        return d;
      })])
      .range([height, 0]);
    
    var svg = d3.select('body').append('svg')
      .attr('class', 'chart')
      .attr('width', w)
      .attr('height', h);
    
    var chart = svg.append('g')
      .classed('graph', true)
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
    
    var layersArea = chart.append('g')
      .attr('class', 'layers');
    
    
    var layers = layersArea.append('g')
      .attr('class', 'layer');
    
    layers.selectAll('rect')
      .data(data)
      .enter()
      .append('rect')
    
    .attr('height', function(d, i) {
      return height - y(d.one);
    })
    
    .attr('y', function(d, i) {
      return y(d.one);
    })
    
    // .attr('width', function(d, i) {
    //   return 50;
    // })
    
    .attr("width", function(d) {
      return x(d3.timeDay.offset(d.date, 10)) - x(d.date)
    })
    
    .attr('x', function(d, i) {
      return x(d3.timeDay.offset(d.date, -5));
    })
    
    .style('fill', (d, i) => {
      return colors[i];
    });
    
    chart.append('g')
      .classed('x axis', true)
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x)
        .tickFormat(d3.timeFormat("%Y-%m-%d")).tickValues(data.map(function(d) {
          return new Date(d.date)
        })));
    
    chart.append('g')
      .classed('y axis', true)
      .call(d3.axisLeft(y)
        .ticks(10));