d3js bar graph with x+y axes: x轴值分布

d3js bar graph with x+y axes: x axis value distribution

我正在尝试显示带有 x 轴和 y 轴的垂直条形图。我得到了带有 y 轴的条形图,但是我在 x 轴上遇到了困难。

x 轴文本标签与条的宽度均匀分布,但是:x 轴上有 markers/vertical 行,宽度不同,尤其是第一部分和最后一部分,即使我已指定 scaleBanddomain

我的代码:

<script src="https://d3js.org/d3.v5.min.js"></script>
<svg class="v5chart" width="960" height="500"></svg>

<style>
/*Rectangle bar class styling*/
.bar {
  fill: #0080FF
}
.bar:hover {
  fill: #003366
}

/*Text class styling*/
.text {
  fill: white;
  font-family: sans-serif
}
</style>

<script>

////VERTICAL BAR CHART WITH SVG AND NAMES
// Create data array of values to visualize
var dataArray = [{ "Player": "John Doe", "Points": 23 }, { "Player": "Jane Doe", "Points": 13 }, { "Player": "Mary Jane", "Points": 21 }, { "Player": "Debasis Das", "Points": 14 }, { "Player": "Nishant", "Points": 37 }, { "Player": "Mark", "Points": 15 }, { "Player": "Andrew", "Points": 18 }, { "Player": "Simon", "Points": 34 }, { "Player": "Lisa", "Points": 30 }, { "Player": "Marga", "Points": 20 }];

// Create variable for the SVG
var canvas = d3.select(".v5chart1").append("g").attr("transform", "translate(20,30)");

var canvasWidth = 500;


var maxValue = d3.max(dataArray, function (d) { return d.Points; });
var canvasHeight = maxValue*10;

var heightScale = d3.scaleLinear()
    .domain([0, d3.max(dataArray, function (d) { return d.Points; })])
    .range([canvasHeight, 0]); //use max value (37) * 10

var y_axis = d3.axisLeft()
    .scale(heightScale);

var x = d3.scaleBand()
    .rangeRound([0, canvasWidth], .1);

x.domain(dataArray.map(function (d) { return d.Player; }));

var x_Axis = d3.axisBottom(x);

// Select, append to SVG, and add attributes to rectangles for bar chart
canvas.selectAll("rect")
    .data(dataArray)
    .enter().append("rect")
    .attr("class", "bar")
    .attr("height", function (d, i) { return (d.Points * 10) })
    .attr("width", canvasWidth/dataArray.length)    
    .attr("x", function (d, i) { return (i * (canvasWidth / dataArray.length)) })
    .attr("y", function (d, i) { return canvasHeight - (d.Points * 10) });

// Select, append to SVG, and add attributes to text
canvas.selectAll("text")
    .data(dataArray)
    .enter().append("text")
    .text(function (d) { return d.Points })
    .attr("class", "text")
    .attr("x", function (d, i) { return (i * (canvasWidth / dataArray.length)) + (canvasWidth / dataArray.length)/2 })
    .attr("y", function (d, i) { return canvasHeight + 20 - (d.Points * 10) });



canvas.append("g")
    .attr("transform", "translate(0,0)")
    .call(y_axis);

canvas.append("g")
    .attr("transform", "translate(0," + canvasHeight + ")")
    .call(x_Axis)
    .selectAll("text")
    .attr("x",40)
    .attr("transform", function (d) {
        return "rotate(65)"
    });

</script>

我已经检查过这里:https://www.d3-graph-gallery.com/graph/custom_axis.html

您应该已经正确阅读了您提供的 link 中的 scaleBand 示例:

  • scaleBand 提供了一种方便的 bandwidth() 方法来为您提供每个柱的宽度
  • d3js 中的 od axis 的想法是您不需要自己进行计算,因此在您的情况下,您只需将玩家名称传递给 x 函数即可坐标计算给你。
  • 同样适用于 y 计算,但我把这个留给你自己弄清楚,一点也不难。
  • 关于 scaleBand 的另一个小事,你使用的是 rangeRound() 方法,我不熟悉,但是如果你使用 range() 方法结合 padding()正如您 link 编辑的示例,然后通过调整填充值,您可以控制栏的宽度,而不会影响 x 轴。值越高,条形越细,条形之间的 space 越多。

////VERTICAL BAR CHART WITH SVG AND NAMES
        // Create data array of values to visualize
        var dataArray = [{ "Player": "John Doe", "Points": 23 }, { "Player": "Jane Doe", "Points": 13 }, { "Player": "Mary Jane", "Points": 21 }, { "Player": "Debasis Das", "Points": 14 }, { "Player": "Nishant", "Points": 37 }, { "Player": "Mark", "Points": 15 }, { "Player": "Andrew", "Points": 18 }, { "Player": "Simon", "Points": 34 }, { "Player": "Lisa", "Points": 30 }, { "Player": "Marga", "Points": 20 }];
    
        // Create variable for the SVG
        var canvas = d3.select(".v5chart").append("g").attr("transform", "translate(20,30)");
    
        var canvasWidth = 500;
    
        var maxValue = d3.max(dataArray, function (d) { return d.Points; });
    
        var heightScale = d3.scaleLinear()
            .domain([0, d3.max(dataArray, function (d) { return d.Points; })])
            .range([maxValue * 10, 0]); //use max value (37) * 10
    
        var y_axis = d3.axisLeft()
            .scale(heightScale);
    
        var x = d3.scaleBand()
            .range([0, canvasWidth]).padding([0.1]);
    
        x.domain(dataArray.map(function (d) { return d.Player; }));
       
        var x_Axis = d3.axisBottom(x);
    
        // Select, append to SVG, and add attributes to rectangles for bar chart
        canvas.selectAll("rect")
            .data(dataArray)
            .enter().append("rect")
            .attr("class", "bar")
            .attr("height", function (d, i) { return (d.Points * 10) })
            .attr("width", x.bandwidth())    
            .attr("x", function (d, i) { return x(d.Player); })
            .attr("y", function (d, i) { return 370 - (d.Points * 10) });
    
        // Select, append to SVG, and add attributes to text
        canvas.selectAll("text")
            .data(dataArray)
            .enter().append("text")
            .text(function (d) { return d.Points })
            .attr("class", "text")
            .attr("text-anchor", "middle")
            .attr("x", function (d, i) { return x(d.Player)+x.bandwidth()/2; })
            .attr("y", function (d, i) { return 390 - (d.Points * 10) });
    
    canvas.append("g")
        .attr("transform", "translate(0,0)")
        .call(y_axis);

    canvas.append("g")
        .attr("transform", "translate(0,370)")
        .call(x_Axis);
.bar {
      fill: #0080FF
    }
    .bar:hover {
      fill: #003366
    }
    
    /*Text class styling*/
    .text {
      fill: white;
      font-family: sans-serif
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <svg class="v5chart" width="960" height="500"></svg>