【问题标题】:How to properly transpose X and Y axes using the D3 axis commands?如何使用 D3 轴命令正确转置 X 和 Y 轴?
【发布时间】:2016-08-09 02:30:33
【问题描述】:

原始代码位于:http://bl.ocks.org/Guerino1/be1a49bc4c4ad4d0f787a8e26ab2718e(请参阅标有“Transitions Axes using a button, with a short delay”的 HTML div)

在上面的示例中,我尝试使用以下 D3 代码将 Y 轴转置为 X,将 X 轴转置为 Y...

function draw70( xAxisData, yAxisData, selectString )
  {

    var flag = true;
    var w = 500;
    var h = 400;
    var marginLeft = 10;
    var marginRight = w - 10;
    var marginTop = 20;
    var marginBottom = h - 20;

    var lineData = [];
    var pt1 = {x: 0, y: 0};
    lineData.push(pt1);
    var pt2 = {x: 0, y: h};
    lineData.push(pt2);
    var pt3 = {x: w, y: h};
    lineData.push(pt3);
    var pt4 = {x: w, y: 0};
    lineData.push(pt4);
    var pt5 = {x: 0, y: 0};
    lineData.push(pt5);

    var lineFunction = d3.svg.line()
      .x(function(d) { return d.x; })
      .y(function(d) { return d.y; })
      .interpolate("linear");

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

    // Put a border around the canvas for visual effects
    canvas.append("path")
        .attr("d", lineFunction(lineData))
        .attr("stroke", "blue")
        .attr("stroke-width", 4)
        .attr("fill", "none");

    // InnerCanvas is the offset canvas, that is offset away
    // from the margins, using the transform/translate for the
    // entire canvas, instead of just for individual axis.
    var innerCanvas = canvas.append("g")
        .attr("transform", "translate(60,10)");

    // Setup y axis : Range is the length of the line
    // NOTE: A value of "1" for rangeRoundBands allows points
    // to be centered over the ordinal text markers
    var yAxisScale = d3.scale.ordinal().domain(yAxisData).rangeRoundBands([marginBottom-20, marginTop], 1);
    var yAxis = d3.svg.axis().scale(yAxisScale).orient("left");
    var yAxisGroup = innerCanvas.append("g")
        .attr("class", "y axis")
        .call(yAxis);

    // Setup x axis : Range is the length of the line
    // NOTE: A value of "1" for rangeRoundBands allows points
    // to be centered over the ordinal text markers
    var xAxisScale = d3.scale.ordinal().domain(xAxisData).rangeRoundBands([0, (marginRight-100)], 1);
    var xAxis = d3.svg.axis().scale(xAxisScale).orient("bottom");
    var xAxisGroup = innerCanvas.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0,354)")
      .call(xAxis);

    d3.select("#buttonChart70")
      .on("click", function(){

        var color;
        if (flag) {
          //yAxisScale = d3.scale.ordinal().domain(xAxisData).rangeRoundBands([marginBottom-20, marginTop], 1);
          //xAxisScale = d3.scale.ordinal().domain(yAxisData).rangeRoundBands([0, (marginRight-100)], 1);
          yAxisScale = d3.scale.ordinal().domain(xAxisData).rangeRoundBands([marginTop, marginBottom-20], 1);
          xAxisScale = d3.scale.ordinal().domain(yAxisData).rangeRoundBands([(marginRight-100), 0], 1);

yAxis.orient("底部"); xAxis.orient("左"); 颜色=“红色”; } 别的 { yAxisScale = d3.scale.ordinal().domain(yAxisData).rangeRoundBands([marginBottom-20, marginTop], 1); xAxisScale = d3.scale.ordinal().domain(xAxisData).rangeRoundBands([0, (marginRight-100)], 1); yAxis.orient("底部"); xAxis.orient("左"); 颜色=“黑色”; }

        flag = !flag

        // Transitions the Y axis to X value set.
        var yTransitions = innerCanvas.selectAll(".y.axis")
          .transition()
          .duration(2000)
            .delay(200)
            .attr("fill", color)
            .attr("transform", function(){
                if (flag){
                  return "transform(0, 354)";
                } else {
                  return "transform(marginTop, marginBottom-20)";
                  //return "transform(marginBottom-20, marginTop)";
                };
              }
            )
          .call(yAxis);

        // Transitions the X axis to Y value set.
        var xTransitions = innerCanvas.selectAll(".x.axis")
          .transition()
          .duration(2000)
            .delay(200)
            .attr("fill", color)
            //.attr("transform", "translate(0,354)")
            .attr("transform", function(){
                if (flag){
                  return "transform(marginTop, marginBottom-20)";
                  //return "transform(marginBottom-20, marginTop)";
                } else {
                  return "transform(0, 354)";
                };
              }
            )
          .call(xAxis);

      })
      .on("mouseover", function(){ 
        var thisObject = d3.select(this);
        thisObject.style({"background-color": "DarkGreen"});
      })
      .on("mouseleave", function(){ 
        var thisObject = d3.select(this);
        thisObject.style({"background-color": "#4CAF50"});
      });

  };

选择按钮后,轴会移动,但不会移动到正确的位置,也不会回到正确的位置。移动后文本也会反转。

注意:我想同时转换文本和行/路径。

这样做的正确方法是什么?

感谢您提供的任何帮助。

【问题讨论】:

    标签: javascript d3.js transition axis axis-labels


    【解决方案1】:

    如果我理解正确,您想将 xAxis 换成 yAxis,对吗?在这种情况下,您必须对刻度和轴进行所有更改,并在应用更改后转换轴:

    d3.transition(svg)
        .select(".x.axis")//this class was previously applied
        .transition()
        .duration(2000)
        .call(xAxis);
    

    检查这个sn-p:

    var width = 400, height = 400, flag = true;
    var svg = d3.select("#svgdiv")
      .append("svg")
      .attr("width", width)
      .attr("height", height);
    
    var xScale = d3.scale.ordinal()
      .domain("ABCDEFGHIJ".split(""))
      .rangeBands([30, width - 20]);
    
    var yScale = d3.scale.linear()
      .domain([0, 10])
      .range([height - 20, 20]);
    
    var xAxis = d3.svg.axis()
      .scale(xScale)
      .orient("bottom");
    
    var yAxis = d3.svg.axis()
      .scale(yScale)
      .orient("left");
    
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", `translate(0,${height-20})`)
      .call(xAxis);
    
    svg.append("g")
      .attr("class", "y axis")
      .attr("transform", "translate(30, 0)")
      .call(yAxis);
    
    //here is the code for transposing the axes:
    
    d3.select("#myButton").on("click", function(){
    
      if(flag){
        yAxis.orient("bottom");
        xAxis.orient("left");
    xScale.domain("ABCDEFGHIJ".split(""))
      .rangeBands([width - 20, 30]);
    yScale.domain([0, 10])
      .range([20, height - 20]);
      } else {
        yAxis.orient("left");
        xAxis.orient("bottom");
    xScale.domain("ABCDEFGHIJ".split(""))
      .rangeBands([30, width - 20]);
    
    yScale.domain([0, 10])
      .range([height - 20, 20]);
      };
      
      d3.transition(svg)
        .select(".x.axis")
        .transition()
        .duration(2000)
        .attr("transform", function(){
          if(flag){
          return "translate(30, 0)"
          } else { return `translate(0,${height-20})`}})
        .call(xAxis);
    
      d3.transition(svg)
        .select(".y.axis")
        .transition()
        .duration(2000)
        .attr("transform", function(){
          if(!flag){
          return "translate(30, 0)"
        } else { return `translate(10,${height-20})`}})
        .call(yAxis);
      
        flag = !flag;
      
    });
    .axis path,
    .axis line {
      fill: none;
      stroke: #aaa;
      shape-rendering: crispEdges;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    <button id="myButton">Swap</button>
    <div id="svgdiv"></div>

    【讨论】:

    • 顺便说一下,您的轴翻转不会准确地重新定位您的数据。转置时数字和字母会颠倒。它们不应颠倒过来。
    • @Information Technology,这只是重新设置范围的问题。再次检查 sn-p。
    • 即使在调整范围后仍然无法正常工作。我的示例专门使用了必须考虑的内部画布。它还显式地为一个轴上的标签使用更长的字符串(季节),以便当这些字符串过渡到左侧时必须考虑偏移量。我在响应 sn-p 中没有看到这些东西,我想知道它们是否与为什么它不能以相同的方式工作有关。注意:我更新了原始示例,以便您可以看到(在最后一个 HTML div 中)。
    • 我的 sn-p 只是一个一般性的答案,它不是基于您的代码。请随意不接受我的回答,并希望其他人为您提供所需的答案。
    猜你喜欢
    • 2016-05-31
    • 2014-07-07
    • 2021-12-04
    • 2020-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-05
    相关资源
    最近更新 更多