如何在d3.js中交换x和y轴 [英] How to swap x and y axis in d3.js

查看:80
本文介绍了如何在d3.js中交换x和y轴的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是d3.js的新手.我想交换d3.js中的轴.如何使用此

I am new in d3.js . I Want to swap the axis in d3.js. How i can convert X-axis into the y-axis and the y-axis into the x-axis while working with this example

我希望条形图从下到上,而不是从左到右? 这是代码

I want bars chart from bottom to top instead of left to right ? Here is the code

 <script>
      var outerWidth = 960;
      var outerHeight = 500;
      var margin = { left: 100, top: 8, right: 30, bottom: 47 };
      var barPadding = 0.2;

      var xColumn = 'Sales';
      var xColumnTooltip = 'Segment';
      var yColumn = 'Sub-Category';
      var colorColumn = 'Segment';
      var layerColumn = colorColumn;

      var hoveredColorValue;
      var hoveredStrokeColor = 'black';

      var innerWidth = outerWidth - margin.left - margin.right;
      var innerHeight = outerHeight - margin.top - margin.bottom;

      var svg = d3
        .select('body')
        .append('svg')
        .attr('width', outerWidth)
        .attr('height', outerHeight);
      var g = svg
        .append('g')
        .attr('transform', 'translate(' + margin.left+ ',' + margin.top + ')');

      // This is the layer where the bars are drawn.
      var baseBarLayer = g.append('g');

      // This layer contains a semi-transparent overlay that fades out the base bars.
      var overlayRect = g
        .append('g')
        .append('rect')
        .attr('width', innerWidth)
        .attr('height', innerHeight)
        .attr('fill', 'none')
        .style('pointer-events', 'none');

      // This contains the subset of bars rendered on top when you hover over the entries in the color legend.
      var foregroundBarLayer = g.append('g');

      var xAxisG = g
        .append('g')
        .attr('class', 'x axis')
        .attr('transform', 'translate(0,' + innerHeight + ')');
      var yAxisG = g.append('g').attr('class', 'y axis');
      var colorLegendG = g
        .append('g')
        .attr('class', 'color-legend')
        .attr('transform', 'translate(635, 0)');

      var xScale = d3.scale.linear().range([0, innerWidth]);
      var yScale = d3.scale.ordinal().rangeBands([innerHeight, 0], barPadding);
      var colorScale = d3.scale.category10();

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

      // Use a tip offset to ensure the tooltip is not rendered off-screen or over the y-axis labels.
      var tip = d3
        .tip()
        .attr('class', 'd3-tip')
        .offset([60, 0])
        .html(function(d) {
          return [
            d[colorColumn],
            ' in ',
            d[yColumn],
            ': ',
            tipNumberFormat(d[xColumnTooltip]),
            ' item(s)'
          ].join('');
        });
      g.call(tip);

      // Use a modified SI formatter that uses "B" for billions.
      var siFormat = d3.format('s');
      var customTickFormat = function(d) {
        return siFormat(d).replace('G', 'B');
      };

      var xAxis = d3.svg
        .axis()
        .scale(xScale)
        .orient('bottom')
        .ticks(5)
        .tickFormat(customTickFormat)
        .outerTickSize(0);
      var yAxis = d3.svg
        .axis()
        .scale(yScale)
        .orient('left')
        .outerTickSize(0);

      var colorLegend = d3.legend
        .color()
        .scale(colorScale)
        .shapePadding(6.24)
        .shapeWidth(25)
        .shapeHeight(25)
        .labelOffset(10);

      function render(data) {
        var nested = d3
          .nest()
          .key(function(d) {
            return d[layerColumn];
          })
          .entries(data);

        var stack = d3.layout
          .stack()
          .y(function(d) {
            return d[xColumn];
          })
          .values(function(d) {
            return d.values;
          });

        var layers = stack(nested.reverse()).reverse();

        xScale.domain([
          0,
          d3.max(layers, function(layer) {
            return d3.max(layer.values, function(d) {
              return d.y + d.y0;
            });
          })
        ]);

        yScale.domain(
          layers[0].values.map(function(d) {
            return d[yColumn];
          })
        );

        colorScale.domain(
          layers.map(function(layer) {
            return layer.key;
          })
        );

        colorScale.range(['#69acc8','#4a4ed8','#5700a3']);

        xAxisG.call(xAxis);
        yAxisG.call(yAxis);

        renderBars(baseBarLayer, layers);

        if (hoveredColorValue) {
          setOverlayTransparency(0.7);
          renderBars(
            foregroundBarLayer,
            layers.filter(function(layer) {
              return layer.key === hoveredColorValue;
            })
          );
        } else {
          setOverlayTransparency(0.0);
          renderBars(foregroundBarLayer, []);
        }

        colorLegendG.call(colorLegend);

        // Move the legend text down a bit.
        colorLegendG.selectAll('text').attr('y', 3);

        listenForHover(colorLegendG.selectAll('rect'), data);
        listenForHover(colorLegendG.selectAll('text'), data);
      }

      function renderBars(g, layers) {
        var layerGs = g.selectAll('.layer').data(layers);
        layerGs
          .enter()
          .append('g')
          .attr('class', 'layer');
        layerGs.exit().remove();

        layerGs.style('fill', function(d) {
          return colorScale(d.key);
        });

        var bars = layerGs.selectAll('rect').data(function(d) {
          return d.values;
        });
        bars
          .enter()
          .append('rect')
          .on('mouseover', function(d) {
            tip.show(d);

            // Ensure the tooltip is printed in the same x position (so it is not rendered off-screen to the left).
            d3.select('.d3-tip').style('left', '200px');
          })
          .on('mouseout', tip.hide);
        bars.exit().remove();
        bars
          .attr('x', function(d) {
            return xScale(d.y0);
          })
          .attr('y', function(d) {
            return yScale(d[yColumn]);
          })
          .attr('width', function(d) {
            return xScale(d.y);
          })
          .attr('height', yScale.rangeBand());
      }

      function listenForHover(selection, data) {
        selection
          .on('mouseover', function(d) {
            hoveredColorValue = d;
            render(data);
          })
          .on('mouseout', function(d) {
            hoveredColorValue = null;
            render(data);
          })
          .style('cursor', 'pointer');
      }

      function setOverlayTransparency(alpha) {
        overlayRect
          .transition()
          .duration(400)
          .attr('fill', 'rgba(255, 255, 255, ' + alpha + ')');
      }

      function type(d) {
        //d.revenue = +d.revenue;
        d.items = +d.items;
        //d.revenue_billions = +d.revenue_billions;
        d.total_items = +d.total_items;
        //d.year_created = +d.year_created;

        return d;
      }
      const dataUrl = 'items1(3).csv';


      d3.csv(dataUrl, type, render);
    </script>

在这段代码中,我试图

1-wvar y Scale与var xScale

1-swap var yScale with var xScale

2-wap var yAxis和var.Axis(.scale(xScale))带有.scale(yScale)

2-swap var xAxis with var yAxis and function (.scale(xScale)) with .scale(yScale)

3交换yScale.domain的xScale.domain

3-swap xScale.domain with yScale.domain

将4个xAxisG.call(xAxis)与yAxisG.call(yAxis)交换

4-swap xAxisG.call(xAxis) with yAxisG.call(yAxis)

5交换bar.attr('x'和相应的返回类型,带有bar.attr('y'和相应的返回类型

5-swap bars.attr('x' and corresponding return type with bars.attr('y' and corresponding return type

,但是它没有交换轴.如何交换轴?

but it did not swap the axis. How I can swap the axis?

推荐答案

该网站对此进行了很好的解释: https://www.d3-graph-gallery.com/barplot

This website explains it well: https://www.d3-graph-gallery.com/barplot

(比较 https://www.d3-graph-gallery.com/graph/barplot_basic.html https://www.d3 -graph-gallery.com/graph/barplot_horizo​​ntal.html )

通常,您只需要像这样交换x和y轴:

In general, you just need to swap x- and y-axis like this:

垂直(x轴取data.map(d => d.Country),y轴取[0, 13000]作为域):

Vertical (x-axis takes the data.map(d => d.Country) and y-axis takes the [0, 13000] as domain):

// X axis
var x = d3.scaleBand()
  .range([ 0, width ])
  .domain(data.map(function(d) { return d.Country; }))
  .padding(0.2);
svg.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x))
  .selectAll("text")
    .attr("transform", "translate(-10,0)rotate(-45)")
    .style("text-anchor", "end");

// Add Y axis
var y = d3.scaleLinear()
  .domain([0, 13000])
  .range([ height, 0]);
svg.append("g")
  .call(d3.axisLeft(y));

水平(y轴取data.map(d => d.Country),x轴取[0, 13000]作为域):

Horizontal (y-axis takes the data.map(d => d.Country) and x-axis takes the [0, 13000] as domain):

// Add X axis
var x = d3.scaleLinear()
  .domain([0, 13000])
  .range([ 0, width]);
svg.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x))
  .selectAll("text")
    .attr("transform", "translate(-10,0)rotate(-45)")
    .style("text-anchor", "end");

// Y axis
var y = d3.scaleBand()
  .range([ 0, height ])
  .domain(data.map(function(d) { return d.Country; }))
  .padding(.1)
svg.append("g")
  .call(d3.axisLeft(y))

为了进一步改进该示例,您不应将数据值的域硬编码为[0, 13000],而应使用d3.max():

To improve on that example further, you should not hard-code the domain of the data value to [0, 13000] but rather you should use d3.max():

例如: .domain([0, d3.max(data.map(d => +d.Value))])

完整示例:

垂直(x轴使用data.map(d => d.Country),y轴使用[0, d3.max(data.map(d => +d.Value))]作为域):

Vertical (x-axis takes the data.map(d => d.Country) and y-axis takes the [0, d3.max(data.map(d => +d.Value))] as domain):

// X axis
var x = d3.scaleBand()
  .range([ 0, width ])
  .domain(data.map(function(d) { return d.Country; }))
  .padding(0.2);
svg.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x))
  .selectAll("text")
    .attr("transform", "translate(-10,0)rotate(-45)")
    .style("text-anchor", "end");

// Add Y axis
var y = d3.scaleLinear()
  .domain([0, d3.max(data.map(d => +d.Value))])
  .range([ height, 0]);
svg.append("g")
  .call(d3.axisLeft(y));

水平(y轴取data.map(d => d.Country),x轴取[0, d3.max(data.map(d => +d.Value))]作为域):

Horizontal (y-axis takes the data.map(d => d.Country) and x-axis takes the [0, d3.max(data.map(d => +d.Value))] as domain):

// Add X axis
var x = d3.scaleLinear()
  .domain([0, d3.max(data.map(d => +d.Value))])
  .range([ 0, width]);
svg.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x))
  .selectAll("text")
    .attr("transform", "translate(-10,0)rotate(-45)")
    .style("text-anchor", "end");

// Y axis
var y = d3.scaleBand()
  .range([ 0, height ])
  .domain(data.map(function(d) { return d.Country; }))
  .padding(.1)
svg.append("g")
  .call(d3.axisLeft(y))

更新

对于您的特定示例,我无法进行分叉.但我可以从中分叉它: -放入我自己的叉子中- https://vizhub.com/Alex-ley/444e5503a19b4b829f94f8d732e5cba3

For your particular example, I could not fork it. but I could fork the one you forked it from: https://beta.vizhub.com/curran/ef717a89e37a4d9285cebfa904790665 - into my own fork - https://vizhub.com/Alex-ley/444e5503a19b4b829f94f8d732e5cba3

输出类似:

然后我分叉了一下,并为您翻转了轴: https://vizhub.com/Alex-ley/1ebd1b410b994ce1ad4e754bd7ebf89a?edit=files&file=index.html

Then I forked this and flipped the axes for you: https://vizhub.com/Alex-ley/1ebd1b410b994ce1ad4e754bd7ebf89a?edit=files&file=index.html

现在具有如下输出:

代码中最重要的部分是:

The most important part of the code is:

  function renderBars(g, layers) {
    var layerGs = g.selectAll('.layer').data(layers);
    layerGs
      .enter()
      .append('g')
      .attr('class', 'layer');
    layerGs.exit().remove();

    const maxY = d3.max(layers, function(layer) {
        return d3.max(layer.values, function(d) {
          return d.y + d.y0;
        });
      })
            console.log(maxY)
    layerGs.style('fill', function(d) {
      return colorScale(d.key);
    });

    var bars = layerGs.selectAll('rect').data(function(d) {
      return d.values;
    });
    bars
      .enter()
      .append('rect')
      .on('mouseover', function(d) {
        tip.show(d);

        // Ensure the tooltip is printed in the same x position (so it is not rendered off-screen to the left).
        d3.select('.d3-tip').style('left', '200px');
      })
      .on('mouseout', tip.hide);
    bars.exit().remove();
    bars
      .attr('x', function(d) {
        return xScale(d[yColumn]);
      })
      .attr('y', function(d) {
        return yScale(d.total_items - d.y0);
      })
      .attr('height', function(d) {
        return yScale(maxY - d.y);
      })
      .attr('width', xScale.rangeBand());
  }

这篇关于如何在d3.js中交换x和y轴的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆