【问题标题】:D3 hierarchical bar chart - Rotate X and Y AxesD3 分层条形图 - 旋转 X 轴和 Y 轴
【发布时间】:2014-07-07 00:23:09
【问题描述】:

我看到了一个分层条形图的示例,并且它也适用于我的数据集。

http://d3-example.herokuapp.com/examples/bar/bar-hierarchy.html

但是,我想切换 x 轴和 Y 轴。基本上,希望看到带有分层数据的垂直条形图。请帮忙!

干杯, 阿琼

【问题讨论】:

    标签: javascript d3.js charts hierarchical


    【解决方案1】:

    我已经解决了您的问题,请查看我的 代码 你会得到解决方案的。

    <!DOCTYPE html>
    <meta charset="utf-8">
    <style>
    
    text {
      font: 10px sans-serif;
    }
    
    rect.background {
      fill: white;
    }
    
    .axis {
      shape-rendering: crispEdges;
    }
    
    .axis path,
    .axis line {
      fill: none;
      stroke: #000;
    }
    
    </style>
    <body>
    <script src="//d3js.org/d3.v3.min.js"></script>
    <script>
    
    var margin = {top: 10, right: 120, bottom: 120, left: 120},
        width = 960 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;
    
    var y = d3.scale.linear()
        .range([height, 0]);
    
    var barHeight = 20;
    
    var color = d3.scale.ordinal()
        .range(["steelblue", "#ccc"]);
    
    var duration = 750,
        delay = 25;
    
    var partition = d3.layout.partition()
        .value(function(d) { return d.size; });
    
    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left");
    
    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 + ")");
    
    svg.append("rect")
        .attr("class", "background")
        .attr("width", width)
        .attr("height", height)
        .on("click", up);
    
    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0, " + height + ")")
        .append("line")
        .attr("x1", "100%");
    
    svg.append("g")
        .attr("class", "y axis");
    
    d3.json("https://jsonblob.com/api/f577d19c-0f2b-11e7-a0ba-09040711ce47", function(error, root) {
      if (error) throw error;
    
      partition.nodes(root);
      y.domain([0, root.value]).nice();
      down(root, 0);
    });
    
    function down(d, i) {
      if (!d.children || this.__transition__) return;
      var end = duration + d.children.length * delay;
    
      // Mark any currently-displayed bars as exiting.
      var exit = svg.selectAll(".enter")
          .attr("class", "exit");
    
      // Entering nodes immediately obscure the clicked-on bar, so hide it.
      exit.selectAll("rect").filter(function(p) { return p === d; })
          .style("fill-opacity", 1e-6);
    
      // Enter the new bars for the clicked-on data.
      // Per above, entering bars are immediately visible.
      var enter = bar(d)
          .attr("transform", stack(i))
          .style("opacity", 1);
    
      // Have the text fade-in, even though the bars are visible.
      // Color the bars as parents; they will fade to children if appropriate.
      enter.select("text").style("fill-opacity", 1e-6);
      enter.select("rect").style("fill", color(true));
    
      // Update the x-scale domain.
      y.domain([0, d3.max(d.children, function(d) { return d.value; })]).nice();
    
      // Update the x-axis.
      svg.selectAll(".y.axis").transition()
          .duration(duration)
          .call(yAxis);
    
      // Transition entering bars to their new position.
      var enterTransition = enter.transition()
          .duration(duration)
          .delay(function(d, i) { return i * delay; })
          .attr("transform", function(d, i) { return "translate(" + barHeight * i * 2.5 + "," + 0 + ")"; });
    
      // Transition entering text.
      enterTransition.select("text")
          .style("fill-opacity", 1);
    
      // Transition entering rects to the new y-scale.
      enterTransition.select("rect")
          .attr("y", function(d) { return y(d.value); })
          .attr("height", function(d) { return height - y(d.value); })
          .style("fill", function(d) { return color(!!d.children); });
    
      // Transition exiting bars to fade out.
      var exitTransition = exit.transition()
          .duration(duration)
          .style("opacity", 1e-6)
          .remove();
    
      // Transition exiting bars to the new y-scale.
      exitTransition.selectAll("rect")
          .attr("height", function(d) { return height - y(d.value); });
    
      // Rebind the current node to the background.
      svg.select(".background")
          .datum(d)
        .transition()
          .duration(end);
    
      d.index = i;
    }
    
    function up(d) {
      if (!d.parent || this.__transition__) return;
      var end = duration + d.children.length * delay;
    
      // Mark any currently-displayed bars as exiting.
      var exit = svg.selectAll(".enter")
          .attr("class", "exit");
    
      // Enter the new bars for the clicked-on data's parent.
      var enter = bar(d.parent)
          .attr("transform", function(d, i) { return "translate(" + barHeight * i * 2.5 + "," + 0 + ")"; })
          .style("opacity", 1e-6);
    
      // Color the bars as appropriate.
      // Exiting nodes will obscure the parent bar, so hide it.
      enter.select("rect")
          .style("fill", function(d) { return color(!!d.children); })
        .filter(function(p) { return p === d; })
          .style("fill-opacity", 1e-6);
    
      // Update the y-scale domain.
      y.domain([0, d3.max(d.parent.children, function(d) { return d.value; })]).nice();
    
      // Update the y-axis.
      svg.selectAll(".y.axis").transition()
          .duration(duration)
          .call(yAxis);
    
      // Transition entering bars to fade in over the full duration.
      var enterTransition = enter.transition()
          .duration(end)
          .style("opacity", 1);
    
      // Transition entering rects to the new y-scale.
      // When the entering parent rect is done, make it visible!
      enterTransition.select("rect")
          .attr("height", function(d) { return height - y(d.value); })
          .attr("y", function(d) { return y(d.value); })
          .each("end", function(p) { if (p === d) d3.select(this).style("fill-opacity", null); });
    
      // Transition exiting bars to the parent's position.
      var exitTransition = exit.selectAll("g").transition()
          .duration(duration)
          .delay(function(d, i) { return i * delay; })
          .attr("transform", stack(d.index));
    
      // Transition exiting text to fade out.
      exitTransition.select("text")
          .style("fill-opacity", 1e-6);
    
      // Transition exiting rects to the new scale and fade to parent color.
      exitTransition.select("rect")
          .attr("height", function(d) { return height - y(d.value); })
          .attr("y", function(d) { return y(d.value); })
          .style("fill", color(true));
    
      // Remove exiting nodes when the last child has finished transitioning.
      exit.transition()
          .duration(end)
          .remove();
    
      // Rebind the current parent to the background.
      svg.select(".background")
          .datum(d.parent)
        .transition()
          .duration(end);
    }
    
    // Creates a set of bars for the given data node, at the specified index.
    function bar(d) {
      var bar = svg.insert("g", ".x.axis")
          .attr("class", "enter")
          .attr("transform", "translate(15,0)")
        .selectAll("g")
          .data(d.children)
        .enter().append("g")
          .style("cursor", function(d) { return !d.children ? null : "pointer"; })
          .on("click", down);
    
      bar.append("text")
          .attr("x", barHeight / 2)
          .attr("y", height + 10)
          .attr("dy", ".35em")
          .style("text-anchor", "start")
          .text(function(d) { return d.name; })
          .attr("transform", "rotate(45 " + (barHeight / 2) + " " + (height + 10) + ")")
    
      bar.append("rect")
          .attr("width", barHeight)
          .attr("height", function(d) { return height - y(d.value); })
          .attr("y", function(d) { return y(d.value); });
    
      return bar;
    }
    
    // A stateful closure for stacking bars horizontally.
    function stack(i) {
      var y0 = 0;
      return function(d) {
        var tx = "translate(" + barHeight * i * 1.5 + "," + y0 + ")";
        y0 += y(d.value);
        return tx;
      };
    }
    
    </script>

    【讨论】:

      【解决方案2】:

      这不太对.. 但它已经完成了一半.. 动画并不像单杠那样好用,而且向上钻取完全不起作用.. 希望有人可以帮助添加它。 .

      var m = [40, 50, 5, 70], // top right bottom left
      w = 550 - m[1] - m[3], // width
      h = 384 - m[0] - m[2], // height
      y = d3.scale.linear().range([h,0]),
      x = 70, // bar width
      z = d3.scale.ordinal().range(["steelblue", "#aaa"]); // bar color
      
      var hierarchy = d3.layout.partition()
          .value(function(d) { return d.size; });
      
      var yAxis = d3.svg.axis()
          .scale(y)
          .orient("left");
      
      var xAxis = d3.svg.axis()
          .scale(x)
          .orient("bottom");
      
      
      var svg = d3.select(".sales-pipeline-chart").append("svg:svg")
          .attr("width", w + m[1] + m[3])
          .attr("height", h + m[0] + m[2])
        .append("svg:g")
          .attr("transform", "translate(" + m[3] + "," + m[0] + ")");
      
      svg.append("svg:rect")
          .attr("class", "background")
          .attr("width", w)
          .attr("height", h)
          .on("click", up);
      
      svg.append("svg:g")
          .attr("class", "x axis");
      
      svg.append("svg:g")
          .attr("class", "y axis");
        /*.append("svg:line")
          .attr("y1", "100%");*/
      
      d3.json("/flare.json", function(root) {
        hierarchy.nodes(root);
        y.domain([0,root.value]).nice();
        down(root, 0);
      });
      
      function down(d, i) {
      
        if (!d.children || this.__transition__) return;
        var duration = d3.event && d3.event.altKey ? 7500 : 750,
            delay = duration / d.children.length;
      
        // Mark any currently-displayed bars as exiting.
        var exit = svg.selectAll(".enter").attr("class", "exit");
      
        // Entering nodes immediately obscure the clicked-on bar, so hide it.
        exit.selectAll("rect").filter(function(p) { return p === d; })
            .style("fill-opacity", 1e-6);
      
        // Enter the new bars for the clicked-on data.
        // Per above, entering bars are immediately visible.
          //var barWidth = w / d.children.length;
      
        var enter = bar(d)
            .attr("transform", stack(i))
            .style("opacity", 1);
      
        // Have the text fade-in, even though the bars are visible.
        // Color the bars as parents; they will fade to children if appropriate.
        enter.select("text").style("fill-opacity", 1e-6);
        enter.select("rect").style("fill", z(true));
      
        // Update the y-scale domain.
        y.domain([0, d3.max(d.children, function(d) { return d.value; })]).nice();
      
        // Update the y-axis.
        svg.selectAll(".y.axis").transition()
            .duration(duration)
            .call(yAxis);  
      
        // Transition entering bars to their new position.
        var enterTransition = enter.transition()
            .duration(duration)
            .delay(function(d, i) { return i * delay; })
            .attr("transform", function(d, i) { return "translate(" + x * i * 1.3 + "," + (h - y(d.value)) + ")"; });
            /*.call(xAxis);*/
      
        // Transition entering text.
        enterTransition.select("text").style("fill-opacity", 1);
      
        // Transition entering rects to the new x-scale.
        enterTransition.select("rect")
            .attr("height", function(d) { return y(d.value); })
            .style("fill", function(d) { return z(!!d.children); });
      
        // Transition exiting bars to fade out.
        var exitTransition = exit.transition()
            .duration(duration)
            .style("opacity", 1e-6)
            .remove();
      
        // Transition exiting bars to the new x-scale.
        exitTransition.selectAll("rect").attr("height", function(d) { return y(d.value); });
      
        // Rebind the current node to the background.
        svg.select(".background").data([d]).transition().duration(duration * 2); d.index = i;
      }
      
      function up(d) {
        if (!d.parent || this.__transition__) return;
        var duration = d3.event && d3.event.altKey ? 7500 : 750,
            delay = duration / d.children.length;
      
        // Mark any currently-displayed bars as exiting.
        var exit = svg.selectAll(".enter").attr("class", "exit");
      
        // Enter the new bars for the clicked-on data's parent.
        var enter = bar(d.parent)
            .attr("transform", function(d, i) { return "translate(" + x * i * 1.3 + "," + (h - y(d.value)) + ")"; })
            .style("opacity", 1e-6);
      
        // Color the bars as appropriate.
        // Exiting nodes will obscure the parent bar, so hide it.
        enter.select("rect")
            .style("fill", function(d) { return z(!!d.children); })
          .filter(function(p) { return p === d; })
            .style("fill-opacity", 1e-6);
      
        // Update the x-scale domain.
        y.domain([0, d3.max(d.parent.children, function(d) { return d.value; })]).nice();
      
        // Update the x-axis.
        svg.selectAll(".y.axis").transition()
            .duration(duration * 2)
            .call(yAxis);
      
        // Transition entering bars to fade in over the full duration.
        var enterTransition = enter.transition()
            .duration(duration * 2)
            .style("opacity", 1);
      
        // Transition entering rects to the new x-scale.
        // When the entering parent rect is done, make it visible!
        enterTransition.select("rect")
            .attr("height", function(d) { return y(d.value); })
            .each("end", function(p) { if (p === d) d3.select(this).style("fill-opacity", null); });
      
        // Transition exiting bars to the parent's position.
        var exitTransition = exit.selectAll("g").transition()
            .duration(duration)
            .delay(function(d, i) { return i * delay; })
            .attr("transform", stack(d.index));
      
        // Transition exiting text to fade out.
        exitTransition.select("text")
            .style("fill-opacity", 1e-6);
      
        // Transition exiting rects to the new scale and fade to parent color.
        exitTransition.select("rect")
            .attr("height", function(d) { return y(d.value); })
            .style("fill", z(true));
      
        // Remove exiting nodes when the last child has finished transitioning.
        exit.transition().duration(duration * 2).remove();
      
        // Rebind the current parent to the background.
        svg.select(".background").data([d.parent]).transition().duration(duration * 2);
      }
      
      // Creates a set of bars for the given data node, at the specified index.
      function bar(d) {
        var bar = svg.insert("svg:g", ".x.axis")
            .attr("class", "enter")
            .attr("transform", "translate(10,0)")
          .selectAll("g")
            .data(d.children)
          .enter().append("svg:g")
            .style("cursor", function(d) { return !d.children ? null : "pointer"; })
            .on("click", down);
      
        bar.append("svg:text")
            .attr("y", -6)
            .attr("x", x / 2)
            //.attr("dx", ".35em")
            .attr("text-anchor", "end")
            .text(function(d) { return d.name; });
      
        /*var barWidth = w / d.children.length;*/
      
        bar.append("svg:rect")
            .attr("height", function(d) { return y(d.value); })
            .attr("width", x/*barWidth*/);
      
        return bar;
      }
      
      // A stateful closure for stacking bars horizontally.
      function stack(i) {
        var y0 = 0;
        return function(d) {
          var ty = "translate(" + x * i * 1.2 + "," + y0 + ")";
          y0 += y(d.value);
          return ty;
        };
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-20
        • 1970-01-01
        • 1970-01-01
        • 2014-01-23
        • 2016-05-31
        • 1970-01-01
        • 2021-07-12
        • 1970-01-01
        相关资源
        最近更新 更多