使用d3.js绘制的条形图中X轴未显示

3

我使用d3.js实现了动态分组柱状图,它的工作正常。根据我的数据,Y轴显示总订单数。我想在X轴上显示月份。但是它没有显示出来。这是我的代码:

    function Groupchart() {
    debugger;
    var w = 500;
    var h = 600;
    var MARGINS = { top: 1, right: 20, bottom: 2, left: 50 }
    var colors = [["TotalTicket", "#377EB8"],
                  ["TotalOrders", "#4DAF4A"]];
    var dataset = [{ "Month": "Jan", "TotalOrders": 7324, "TotalTicket": 23954, "Year": "2013", "Avg": "10%" },
                   { "Month": "Feb", "TotalOrders": 3738, "TotalTicket": 12319, "Year": "2013", "Avg": "12%" },
                   { "Month": "March", "TotalOrders": 4466, "TotalTicket": 15524, "Year": "2013", "Avg": "14%" },
                   { "Month": "May", "TotalOrders": 100, "TotalTicket": 200, "Year": "2013", "Avg": "50%" },
                   { "Month": "Oct", "TotalOrders": 109, "TotalTicket": 2000, "Year": "2013", "Avg": "9%" }]

    var x0Scale = d3.scale.ordinal()
                       .domain(d3.range(dataset.length))
                       .rangeRoundBands([MARGINS.left, w - MARGINS.right], 0.1);
    var x1Scale = d3.scale.ordinal()
                    .domain([0, d3.max(dataset, function (d) { return d.TotalOrders; })])
                    .rangeRoundBands([MARGINS.left, w - MARGINS.right], 0.1);

    var yScale = d3.scale.linear()
                    .domain([0, d3.max(dataset, function (d) { return (d.TotalTicket + 10000); })])
                    .range([h - MARGINS.top, MARGINS.bottom]);
    xAxis = d3.svg.axis().scale(x0Scale).tickSize(5).tickSubdivide(true).orient("bottom");
    yAxis = d3.svg.axis().scale(yScale).tickSize(5).orient("left").tickSubdivide(true);

    var TotalOrders = function (d) {
        return d.TotalOrders;
    };

    var TotalTicket = function (d) {
        return d.TotalTicket;
    };
    var Month = function (d) {
        return d.Month;
    };

    var Average = function (d) {
        return d.Avg;
    };

    var commaFormat = d3.format(',');

    //SVG element
    var svg = d3.select("#searchVolume")
                .append("svg")
                .attr("width", w)
                .attr("height", h)
                .attr("margin", MARGINS);


    /*Draw X Axis values*/
    svg.append('svg:g')
      .attr('class', 'x axis')
      .attr('transform', 'translate(0,' + (h - MARGINS.bottom) + ')')
      .call(xAxis);

    /*Draw Y Axis values*/
    svg.append('svg:g')
      .attr('class', 'y axis')
      .attr('transform', 'translate(' + (MARGINS.left) + ',0)')
      .call(yAxis);

    // Graph Bars
    var sets = svg.selectAll(".set")
        .data(dataset)
        .enter().append("g")
        .attr("class", "set")
        .attr("transform", function (d, i) {
            return "translate(" + x0Scale(i) + ",0)"
        })

        .on("mouseover", function (d, i) {
            //Get this bar's x/y values, then augment for the tooltip
            var xPosition = parseFloat(x0Scale(i) + x0Scale.rangeBand() / 6);
            var yPosition = 0;
            //Update Tooltip Position & value
            d3.select("#tooltip")
                .style("left", xPosition + "px")
                .style("top", yPosition + "px")
                .select("#cpcVal")
                .text(d.Month);
            d3.select("#tooltip").classed("hidden", false);
        })
        .on("mouseout", function () {
            //Remove the tooltip
            d3.select("#tooltip").classed("hidden", true);
        });

    sets.append("rect")
        .attr("class", "TotalTicket")
        .attr("width", x0Scale.rangeBand() / 2)
        .attr("y", function (d) {
            return yScale(d.TotalTicket);
        })
        .attr("x", x0Scale.rangeBand() / 2)
        .attr("height", function (d) {
            return h - yScale(d.TotalTicket);
        })
        .attr("fill", colors[0][1])
        .transition()
        .delay(function (d, i) { return i * 300 })
        .duration(1000)

    sets.append("rect")
        .attr("class", "TotalOrders")
        .attr("width", x0Scale.rangeBand() / 2)
        .attr("y", function (d) {
            return yScale(d.TotalOrders);
        })
        .attr("height", function (d) {
            return h - yScale(d.TotalOrders);
        })
       .attr("fill", colors[1][1])


    var legend = svg.append("g")
     .attr("class", "legend")
     //.attr("x", w - 65)
     //.attr("y", 50)
     .attr("height", 100)
     .attr("width", 100)
     .attr('transform', 'translate(-20,50)');

    var legendRect = legend.selectAll('rect').data(colors);

    legendRect.enter()
        .append("rect")
        .attr("x", w - 65)
        .attr("width", 10)
        .attr("height", 10);

    legendRect
        .attr("y", function (d, i) {
            return i * 20;
        })
        .style("fill", function (d) {
            return d[1];
        });

    var legendText = legend.selectAll('text').data(colors);

    legendText.enter()
        .append("text")
        .attr("x", w - 52);

    legendText
        .attr("y", function (d, i) {
            return i * 20 + 9;
        })
        .text(function (d) {
            return d[0];
        });

    svg.selectAll("text")
       .data(dataset, Average)
       .enter()
       .append("text")
       .text(function (d) {
           return(d.Avg);
       })
       .attr("class", "bartext")
       .attr("text-anchor", "middle")
       .attr("x", function (d, i) {
       return x0Scale(i) + x0Scale.rangeBand() / 2;
       })
       .attr("y", function (d) {
           return  yScale(d.TotalTicket) - 10;
       })
      .attr("font-family", "sans-serif")
      .attr("font-size", "15px")
      .attr("fill", "black");
}

请问有人能告诉我实际的问题是什么吗?


你能在 JSFiddle 上发布这段代码吗? - Manjunath Siddappa
这里有一个带有原始问题的 JSFiddle:http://jsfiddle.net/henbox/mvfmpdpp/。我认为这只是一个边距的问题,请尝试按照此示例进行操作:http://bl.ocks.org/mbostock/3885304。`xAxis`正在绘制,但由于底部边距未正确使用而被隐藏。另外,我不认为 svgmargin 属性? - Henry S
请尝试这个 JSFiddle,月份未分配给 x0Scale。http://jsfiddle.net/e1450pqh/3/ - Manjunath Siddappa
在这个代码片段中,您可以看到X轴上的数字。这样可以吗?还是您需要将月份显示在X轴上? - Manjunath Siddappa
你的 Fiddle 似乎是空的-@ Manjunath Siddappa。这是我的代码的 fiddle:http://jsfiddle.net/henbox/mvfmpdpp/。 - Kalpana Gupta
显示剩余2条评论
1个回答

5

这是一个边距问题。你的有效高度为 height - margin.top - margin.bottom。我已经相应地修正了示例(同时改善了可读性)。

要在序数比例尺中使用月份,必须使用月份初始化该比例尺。然后使用该比例尺将序数值映射到x轴比例尺值,例如 x0Scale(d.Month)

function createGroupchart() 
{
  var width  = 500;
  var height = 180;
  var margin = {
    'top'    : 5, 
    'right'  : 20, 
    'bottom' : 20, 
    'left'   : 50 
  };
  var colors = [
    ["TotalTicket", "#377EB8"],
    ["TotalOrders", "#4DAF4A"]
  ];
  var dataset = [
    {"Month": "Jan",   "TotalOrders": 7324, "TotalTicket": 23954, "Year": "2013", "Avg": "10%"},
    {"Month": "Feb",   "TotalOrders": 3738, "TotalTicket": 12319, "Year": "2013", "Avg": "12%"},
    {"Month": "March", "TotalOrders": 4466, "TotalTicket": 15524, "Year": "2013", "Avg": "14%"},
    {"Month": "May",   "TotalOrders": 100,  "TotalTicket": 200,   "Year": "2013", "Avg": "50%"},
    {"Month": "Oct",   "TotalOrders": 109,  "TotalTicket": 2000,  "Year": "2013", "Avg": "9%" }
  ];

  var x0Scale = d3.scale.ordinal()
    .domain(dataset.map(function(d)
    {
      return d.Month;
    }))
    .rangeRoundBands([margin.left, width - margin.right], 0.1);

  var x1Scale = d3.scale.ordinal()
    .domain([0, d3.max(dataset, function(d) 
    { 
      return d.TotalOrders; 
    })])
    .rangeRoundBands([margin.left, width - margin.right], 0.1);

  var yScale = d3.scale.linear()
    .domain([0, d3.max(dataset, function(d) 
    { 
      return (d.TotalTicket + 10000); 
    })])
    .range([height - margin.top - margin.bottom, 0]);

  var xAxis = d3.svg.axis()
    .scale(x0Scale)
    .tickSize(5)
    .tickSubdivide(true)
    .orient("bottom");

  var yAxis = d3.svg.axis()
    .scale(yScale)
    .tickSize(5)
    .orient("left")
    .tickSubdivide(true);

  var commaFormat = d3.format(',');


  // SVG element
  var svg = d3.select("#chart")
    .append("svg")
    .attr("width",  width)
    .attr("height", height)
    .attr("margin", margin);

  // Draw X Axis values
  svg.append('g')
    .attr('class', 'x axis')
    .attr('transform', 'translate(0,' + (height - margin.bottom - margin.top) + ')')
    .call(xAxis);

  // Draw Y Axis values
  svg.append('g')
    .attr('class', 'y axis')
    .attr('transform', 'translate(' + margin.left + ',0)')
    .call(yAxis);

  // Graph Bars
  var sets = svg.selectAll(".set")
    .data(dataset)
    .enter().append("g")
    .attr("class", "set")
    .attr("transform", function(d) 
    {
      return "translate(" + x0Scale(d.Month) + ",0)"
    });

  sets.append("rect")
    .attr("class", "TotalTicket")
    .attr("width", x0Scale.rangeBand() / 2)
    .attr("y", function(d) 
    {
      return yScale(d.TotalTicket);
    })
    .attr("x", x0Scale.rangeBand() / 2)
    .attr("height", function(d) 
    {
      return height - margin.top - margin.bottom - yScale(d.TotalTicket);
    })
    .attr("fill", colors[0][1]);

  sets.append("rect")
    .attr("class", "TotalOrders")
    .attr("width", x0Scale.rangeBand() / 2)
    .attr("y", function(d) 
    {
      return yScale(d.TotalOrders);
    })
    .attr("height", function(d) 
    {
      return height - margin.top - margin.bottom - yScale(d.TotalOrders);
    })
    .attr("fill", colors[1][1])


  var legend = svg.append("g")
    .attr("class", "legend")
    .attr("height", 100)
    .attr("width", 100)
    .attr('transform', 'translate(-30,20)');

  var legendRect = legend.selectAll('rect').data(colors);

  legendRect.enter()
    .append("rect")
    .attr("x", width - 65)
    .attr("width", 10)
    .attr("height", 10);

  legendRect
    .attr("y", function(d, i) 
    {
      return i * 20;
    })
    .style("fill", function(d) 
    {
      return d[1];
    });

  var legendText = legend.selectAll('text').data(colors);

  legendText.enter()
    .append("text")
    .attr("x", width - 52);

  legendText
    .attr("y", function(d, i) 
    {
      return i * 20 + 9;
    })
    .text(function(d) 
    {
      return d[0];
    });

  svg.selectAll("text")
    .data(dataset, function(d)
    {
      return d.Avg;
    })
    .enter()
    .append("text")
    .text(function(d) 
    {
      return d.Avg;
    })
    .attr("class", "bartext")
    .attr("text-anchor", "middle")
    .attr("x", function(d) 
    {
      return x0Scale(d.Month) + x0Scale.rangeBand() / 2;
    })
    .attr("y", function(d) 
    {
      return  yScale(d.TotalTicket) - 10;
    })
    .attr("font-family", "sans-serif")
    .attr("font-size", "15px")
    .attr("fill", "black");
}
createGroupchart()
svg .axis path, .axis line {
  fill            : none;
  stroke          : #000;
  shape-rendering : crispEdges;
}

svg .x.axis path {
  display : none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id='chart'></div>


@saaj这不是边距问题,她询问的是如何在x轴上显示月份而非数字。 - Manjunath Siddappa
@ManjunathSiddappa 哦,我可能误解了它,因为它不是很清楚。而且边距也是个问题;-) 我已经编辑了答案,谢谢提醒。 - saaj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接