【问题标题】:d3js bar graph with x+y axes: x axis value distributionx+y轴的d3js条形图:x轴值分布
【发布时间】:2020-04-20 00:34:38
【问题描述】:

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

x 轴文本标签与条形的宽度均匀分布,但是:x 轴上有宽度不同的标记/垂直线,尤其是第一个和最后一个部分,即使我已经指定了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

【问题讨论】:

    标签: javascript d3.js bar-chart axes


    【解决方案1】:

    您应该已经正确阅读了您提供的链接上的scaleBand 示例:

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

    ////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>

    【讨论】:

    • 谢谢!然后是一个后续问题:现在我通过.attr("x", function (d, i) { return (i * (canvasWidth / dataArray.length)) + (canvasWidth / dataArray.length) / 2 }) 将条中的点(白色文本)居中对齐。使用您的新示例,对齐失败。如何确保文本位于栏的水平中间?谢谢!
    • @Flo 与我在示例中对齐条本身的方式相同!始终使用xy 函数来确定位置
    • 不知道怎么回事,我试过.attr("x", function (d, i) { return x(d.Player); }).attr("x", function (d, i) { return (x(d.Player) + x.bandwidth()/2); })。既不将文本居中对齐...
    • @Flo 对于未来,我强烈建议将单独的问题作为单独的问题提出 - 这样您其他人回答问题的机会就会增加!关于文本问题,我已经更新了我的答案。我还建议您查看bl.ocks.org/emmasaunders/d682fd84b67b304219e49b1e8385b1f8 以了解文本锚定在 d3js 中的工作原理。新年快乐! :)
    猜你喜欢
    • 2014-07-07
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    相关资源
    最近更新 更多