D3js - change Vertical bar chart to Horizontal bar chart

十年热恋 提交于 2019-12-17 04:35:12

问题


I have a vertical bar chart that is grouped in pairs. I was trying to play around with how to flip it horizontally. In my case, the keywords would appear on the y axis, and the scale would appear on the x-axis.

I tried switching various x/y variables, but that of course just produced funky results. Which areas of my code do I need to focus on in order to switch it from vertical bars to horizontal ones?

My JSFiddle: Full Code

var xScale = d3.scale.ordinal()
    .domain(d3.range(dataset.length))
    .rangeRoundBands([0, w], 0.05);

// ternary operator to determine if global or local has a larger scale
var yScale = d3.scale.linear()
    .domain([0, d3.max(dataset, function (d) {
    return (d.local > d.global) ? d.local : d.global;
})])
    .range([h, 0]);

var xAxis = d3.svg.axis()
    .scale(xScale)
    .tickFormat(function (d) {
        return dataset[d].keyword;
    })
    .orient("bottom");

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

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

//SVG element
var svg = d3.select("#searchVolume")
    .append("svg")
    .attr("width", w + margin.left + margin.right)
    .attr("height", h + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

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

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

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

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

回答1:


I just did the same thing last night, and I basically ended up rewriting the code as it was quicker than fixing all the bugs but here's the tips I can give you.

The biggest issues with flipping the x and y axis will be with things like return h - yScale(d.global) because height is calculated from the "top" of the page not the bottom.

Another key thing to remember is that when you set .attr("x", ..) make sure you set it to 0 (plus any padding for the left side) so = .attr("x", 0)"

I used this tutorial to help me think about my own code in terms of horizontal bars instead - it really helped

http://hdnrnzk.me/2012/07/04/creating-a-bar-graph-using-d3js/

here's my own code making it horizontal if it helps:

var w = 600;
var h = 600;
var padding = 30;

var xScale = d3.scale.linear()
        .domain([0, d3.max(dataset, function(d){
                                return d.values[0]; })]) //note I'm using an array here to grab the value hence the [0]
        .range([padding, w - (padding*2)]);

        var yScale = d3.scale.ordinal()
            .domain(d3.range(dataset.length))
            .rangeRoundBands([padding, h- padding], 0.05);

        var svg = d3.select("body")
            .append("svg")
            .attr("width", w)
            .attr("height", h)

        svg.selectAll("rect")
            .data(dataset)
            .enter()
            .append("rect")
            .attr("x", 0 + padding)
            .attr("y", function(d, i){
            return yScale(i);
            })
            .attr("width", function(d) {
                return xScale(d.values[0]);
            })
            .attr("height", yScale.rangeBand())



回答2:


An alternative is to rotate the chart (see this). This is a bit hacky as then you need to maintain the swapped axes in your head (the height is actually the width etc), but it is arguably simpler if you already have a working vertical chart.

An example of rotating the chart is below. You might need to rotate the text as well to make it nice.

_chart.select('g').attr("transform","rotate(90 200 200)");



回答3:


Here is the procedure I use in this case:

1) Inverse all Xs and Ys

2) Remember that the 0 for y is on top, thus you will have to inverse lots of values as previous values for y will be inversed (you don't want your x axis to go from left to right) and the new y axis will be inversed too.

3) Make sure the bars display correctly

4) Adapt legends if there are problems

This question may help in the sense that it shows how to go from horizontal bar charts to vertical: d3.js histogram with positive and negative values




回答4:


Another Interesting Horizontal Graph NVD3 which I found useful. Give it a Try.



来源:https://stackoverflow.com/questions/16202721/d3js-change-vertical-bar-chart-to-horizontal-bar-chart

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!