坚持使用javascript代码,尝试将x轴转换为y轴

时间:2016-08-19 11:27:30

标签: javascript html d3.js

我有一段规范化堆积条形图的代码。我想将它转换为标准化的horzintal堆积条形图。

<html>
<head>
    <meta charset="utf-8">
    <style type="text/css">
    rect.bordered {
        stroke: #E6E6E6;
        stroke-width: 2px;
    }

    body {
        font-size: 9pt;
        font-family: Consolas, courier;
    }

    text.axis {
        fill: #000;
    }

    .axis path,
    .axis line {
        fill: none;
        stroke: #000;
        shape-rendering: crispEdges;
    }

    .bar {
        fill: steelblue;
    }

    .x.axis path {
        display: none;
    }

    .legend line {
        stroke: #000;
        shape-rendering: crispEdges;
    }

    form {
        position: absolute;
        right: 10px;
        top: 10px;
    }
    </style>
    <script src="http://d3js.org/d3.v3.js" type="text/javascript"></script>
    <title></title>
</head>
<body>
    <form>
    </form>

    <div id="chart"></div>

    <script type="text/javascript">

var margin = {top: 20, right: 231, bottom: 140, left: 40},
width = 1000 - margin.left - margin.right,
height = 800 - margin.top - margin.bottom;

var xscale = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);

var yscale = d3.scale.linear()
.rangeRound([height, 0]);

var colors = d3.scale.ordinal()
.range(["3b5999", "ff5700", "55acee", "0077B5", "ff0084", "3f729b", "34465d","FFFC00","bd081c","dd4b39"]);

var xaxis = d3.svg.axis()
.scale(xscale)
.orient("bottom");

var yaxis = d3.svg.axis()
.scale(yscale)
.orient("left")
.tickFormat(d3.format(".0%")); // **

var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

   // load and handle the data
d3.csv("a.csv", function(error, data) {

// rotate the data
var categories = d3.keys(data[0]).filter(function(key) { return key !== "Day"; });
var parsedata = categories.map(function(name) { return { "Day": name }; });
data.forEach(function(d) {
    parsedata.forEach(function(pd) {
        pd[d["Day"]] = d[pd["Day"]];
    });
});

// map column headers to colors (except for 'Day' and 'Base: All Respondents')
colors.domain(d3.keys(parsedata[0]).filter(function(key) { return key !== "Day" && key !== "Base: All Respondents"; }));

// add a 'responses' parameter to each row that has the height percentage values for each rect
parsedata.forEach(function(pd) {
    var y0 = 0;
    // colors.domain() is an array of the column headers (text)
    // pd.responses will be an array of objects with the column header
    // and the range of values it represents
    pd.responses = colors.domain().map(function(response) {
        var responseobj = {response: response, y0: y0, yp0: y0};
        y0 += +pd[response];
        responseobj.y1 = y0;
        responseobj.yp1 = y0;
        return responseobj;
    });
    // y0 is now the sum of all the values in the row for this category
    // convert the range values to percentages
    pd.responses.forEach(function(d) { d.yp0 /= y0; d.yp1 /= y0; });
    // save the total
    pd.totalresponses = pd.responses[pd.responses.length - 1].y1;
});

// sort by the value in 'Right Direction'
// parsedata.sort(function(a, b) { return b.responses[0].yp1 - a.responses[0].yp1; });

// ordinal-ly map categories to x positions
xscale.domain(parsedata.map(function(d) { return d.Day; }));

// add the x axis and rotate its labels
svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xaxis)
    .selectAll("text")
    .attr("y", 5)
    .attr("x", 7)
    .attr("dy", ".35em")
    .attr("transform", "rotate(65)")
    .style("text-anchor", "start");

// add the y axis
svg.append("g")
    .attr("class", "y axis")
    .call(yaxis);

// create svg groups ("g") and place them
var category = svg.selectAll(".category")
    .data(parsedata)
    .enter().append("g")
    .attr("class", "category")
    .attr("transform", function(d) { return "translate(" + xscale(d.Day) + ",0)"; });

// draw the rects within the groups
category.selectAll("rect")
    .data(function(d) { return d.responses; })
    .enter().append("rect")
    .attr("width", xscale.rangeBand())
    .attr('fill-opacity', 0.7)
    .attr("y", function(d) { return yscale(d.yp1); })
    .attr("height", function(d) { return yscale(d.yp0) - yscale(d.yp1); })
    .style("fill", function(d) { return colors(d.response); });

// position the legend elements
var legend = svg.selectAll(".legend")
    .data(colors.domain())
    .enter().append("g")
    .attr("class", "legend")
    .attr("transform", function(d, i) { return "translate(20," + ((height - 18) - (i * 20)) + ")"; });

legend.append("rect")
    .attr("x", width - 18)
    .attr("width", 18)
    .attr("height", 18)
    .style("fill", colors);

legend.append("text")
    .attr("x", width + 10)
    .attr("y", 9)
    .attr("dy", ".35em")
    .style("text-anchor", "start")
    .text(function(d) { return d; });

// animation
d3.selectAll("input").on("change", handleFormClick);

function handleFormClick() {
    if (this.value === "bypercent") {
        transitionPercent();
    } else {
        transitionCount();
    }
}

// transition to 'percent' presentation
function transitionPercent() {
    // reset the yscale domain to default
    yscale.domain([0, 1]);

    // create the transition
    var trans = svg.transition().duration(250);

    // transition the bars
    var categories = trans.selectAll(".category");
    categories.selectAll("rect")
        .attr("y", function(d) { return yscale(d.yp1); })
        .attr("height", function(d) { return yscale(d.yp0) - yscale(d.yp1); });

    // change the y-axis
    // set the y axis tick format
    yaxis.tickFormat(d3.format(".0%"));
    svg.selectAll(".y.axis").call(yaxis);
}

// transition to 'count' presentation
function transitionCount() {
    // set the yscale domain
    yscale.domain([0, d3.max(parsedata, function(d) { return d.totalresponses; })]);

    // create the transition
    var transone = svg.transition()
        .duration(250);

    // transition the bars (step one)
    var categoriesone = transone.selectAll(".category");
    categoriesone.selectAll("rect")
        .attr("y", function(d) { return this.getBBox().y + this.getBBox().height - (yscale(d.y0) - yscale(d.y1)) })
        .attr("height", function(d) { return yscale(d.y0) - yscale(d.y1); });

    // transition the bars (step two)
    var transtwo = transone.transition()
        .delay(350)
        .duration(350)
        .ease("bounce");
    var categoriestwo = transtwo.selectAll(".category");
    categoriestwo.selectAll("rect")
        .attr("y", function(d) { return yscale(d.y1); });

    // change the y-axis
    // set the y axis tick format
    yaxis.tickFormat(d3.format(".2s"));
    svg.selectAll(".y.axis").call(yaxis);
}
});

d3.select(self.frameElement).style("height", (height + margin.top + margin.bottom) + "px");

    </script>
</body>

我应该做出哪些改变?我尝试在初始化中交换xscale和yscale变量。但我仍然没有得到所需的输出。我会感谢任何帮助/建议。

编辑D3.js Stacked Bar Chart, from vertical to horizontal这也不起作用。
以上代码的灵感来自http://bl.ocks.org/tmaybe/6144082示例,我只对标准化/百分比版本感兴趣。

0 个答案:

没有答案