【问题标题】:Why my rotated tick values are not getting displayed completely d3js?为什么我的旋转刻度值没有完全显示 d3js?
【发布时间】:2017-01-29 22:38:50
【问题描述】:

我正在制作一个图表,其中整个 svg 对象和刻度值都应该在给定的高度范围内。我想知道为什么我的旋转刻度值没有完全显示。高度是 100px,我希望我的图表和刻度值在 100 以内。我试过了 .attr("transform", "scale(1,1.4)")

功能但没用。这是到目前为止的代码!

数据是这个,渲染图表的代码在下面。

 { 
  "Height" : 100,
  "Width" : 250,
"margins" : {
    "top": 10,
    "left": 20,
    "right": 10,
    "bottom": 20
  },

  "data":[
          {
             "fruit" : "apple",
             "initialsale" : 40,
             "totalsale": 600
           },
           {
              "fruit" : "orange",
              "initialsale" : 40,
              "totalsale": 60
            },
          {
            "fruit" : "mango",
            "initialsale" : 1420,
            "totalsale": 6000
          }
        ]
}

function stackChart(){

  
  
 data =  { 
      "Height" : 100,
      "Width" : 250,
    "margins" : {
        "top": 10,
        "left": 20,
        "right": 10,
        "bottom": 20
      },

      "data":[
              {
                 "fruit" : "apple",
                 "initialsale" : 40,
                 "totalsale": 600
               },
               {
                  "fruit" : "orange",
                  "initialsale" : 40,
                  "totalsale": 60
                },
              {
                "fruit" : "mango",
                "initialsale" : 1420,
                "totalsale": 6000
              }
            ]
    };

var margin = data.margins;

var top = margin.top,
    bottom = margin.bottom,
    left = margin.left,
    right = margin.right,
    Width = data.Width,
    Height = data.Height,
    data = data.data;

var width = Width -left -right,
    height = Height -top - bottom;


var svg = d3.select("#stackChart")
  .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 + ")");


// Divider functionality
var div = 0;
if(Width>50&&Width<=100){
  div = 1.2
}
else if(Width>100&&Width<=200)
{
  div = 1.5
}
else if(Width>200&&Width<=300){
  div = 2.0
}
else if(Width>300&&Width<=400){
  div = 2.2
}
else if(Width>400&&Width<=500){
  div = 2.4
}
else if(Width>500&&Width<=600){
  div = 2.6
}
else if(Width>600&&Width<=800){
  div = 2.8
}
else if(Width>800){
  div = 3.0
}


var par = Width/div;

// var scale_parameter = Width/par;



var dataset = [];
var arr1 = [];
var arr2 = [];
data.forEach(function(d) {
                var currentObj = {}
                currentObj["os"] = d.os;
                currentObj["value"] = d.total;
                currentObj["percent"] = (d.initial/d.total)*100;
                arr1.push(currentObj);
                currentObj = {}
                currentObj["os"] = d.os;
                currentObj["value"] = d.total;
                currentObj["percent"] = ((d.total - d.initial)/d.total)*100;
                arr2.push(currentObj);
              }
            );
dataset = [{
    data: arr1,
    name: 'initial'
},{
   data: arr2,
  name: 'remaining'
}];

var series = dataset.map(function (d) {
    return d.name;
}),
dataset = dataset.map(function (d) {
    return d.data.map(function (o, i) {
        // Structure it so that your numeric
        // axis (the stacked amount) is y
        return {
            y: o.percent,
            x: o.os,
            v: o.value
        };
    });
}),
stack = d3.layout.stack(); //.layout in v3

stack(dataset);


var h1= Width * 0.7;
// Set x, y and colors
var x = d3.scale.ordinal()
  .domain(dataset[0].map(function(d) { return d.x; }))
  .rangeRoundBands([0, width], 0.15);

var y = d3.scale.linear()
  .domain([0, d3.max(dataset, function(d) {  return d3.max(d, function(d) { return d.y0+d.y; });  })])
  .range([height, 0]);

var colors = ["#14a900", "#cccccc"];


// Define and draw axes
var yAxis = d3.svg.axis()
  .scale(y)
  .orient("left")
  .ticks(5)
  .tickSize(1)
  .tickFormat( function(d) { return d } )


var xAxis = d3.svg.axis()
  .scale(x)
  .orient("bottom")

// Create groups for each series, rects for each segment

var groups = svg.selectAll("g.cost")
  .data(dataset)
  .enter().append("g")
  .attr("class", "cost")
  .style("fill", function(d, i) { return colors[i]; });


  // Height Calculation of the stack bars
  // y0 will be the base, y is the stacked up bar on y0

var crucial = 0;
var cr = 0;
var heightsof = [];
var rects = groups.selectAll("rect")
  .data(function(d) { return d; })
  .enter()
  .append("rect")
  // .attr("transform","scale(1,1.4)")
  .attr("x", function(d) { return x(d.x); })
  .attr("y", function(d) {
    crucial = y(d.y0 + d.y);
    return  crucial;
  })
  .attr("height", function(d) {
     return height - y(d.y);
   })
  .attr("width", x.rangeBand())

// Getting the length of the total bar
// For tilt angle

var calh=0;
  for(i=0;i<data.length+1;i++){
    var j = data.length;
    if(i==j){
      calh = heightsof[j]+heightsof[0];
    }
  }

  console.log(calh);
  var rect_width = Math.round($("rect").outerWidth());

  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    // .attr("transform","scale(1,)")


  var bool = [],
      counter = 0,
      y = [],
      x = 0,
      z = 0; // max value of y[]

  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", function(){
      return "translate(0,"+(h1)+")";
    })
    .call(xAxis)
    .selectAll("text")
            .style("fill","black")
            .each(function(d,i) {
                    var thisWidth = this.getComputedTextLength();
                    var x = Math.round(thisWidth);
                    y.push(x);
                    if(rect_width>x){
                      bool.push(true);
                    }
                    else{
                      bool.push(false);
                      counter++;
                    }
                    z = Math.max.apply(Math, y);
                  })
                  .style("text-anchor",function(d,i){
                    if(rect_width<=20){
                      return "end";
                    }
                    else {
                      return "middle";
                    }
                  })
                  .attr("transform", function(d,i) {      // Rotation Code
                    if(rect_width<=20) {
                      x = -90;
                      return "translate(-13,8) rotate("+x+")"; //  Minimum width rotation
                    }
                    else if (rect_width>z) {
                      return "rotate(0)";
                    }
                    else if(rect_width>20&&rect_width<z) {
                      var tilt = data.length;
                      var angle = Math.cos(z/rect_width)
                      console.log(angle);
                      if(angle>0&&bool[i]==false){
                        return "translate(-10,"+((y[i]/3)+12)+") rotate(-45)";// -(90-angle*100) +")"; // Rotating based on the maximum angle for proper alignment
                      }
                      if(angle>0&&bool[i]==true){
                        return "translate(-10,"+((y[i]/3)+8)+") rotate(-45)"//"+ -(90-angle*100) +")"; // Rotating based on the maximum angle for proper alignment
                      }
                      else{
                        return "translate(-10,"+((y[i]/3)+12)+") rotate("+ -(90+angle*10) +")"; // Rotating based on the maximum angle for proper alignment
                      }
                        }
                  });

   
}
<div id="stackChart">
  </div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script>
  stackChart();
  </script>

【问题讨论】:

  • 嗨,我尽可能多地编辑帖子。 @AndreiGheorghiu
  • @AndreiGheorghiu 这是图表的小提琴jsfiddle.net/okdfhhvp/2
  • @GerardoFurtado 请取消删除您的答案。它比我的好。 Sai,如果你不能把你的图例放在 100px 的高度,只需使用这个 CSS:transform:scale(factor) 就可以了,其中 factor 应该小于 1 以便缩小。如果您只想缩放高度,请使用scaleY 而不是scale。此外,Gerardo 关于没有两个不同的 svg 而是将所有内容都放在同一个 svg 中的评论是有道理的,除非您希望图例具有响应性。
  • @GerardoFurtado 嗨,我已将 y 轴和堆栈条按比例缩小到 1 以下,但我正面临失真问题。我猜唯一的解决方法是增加data.height。如果我错了,请纠正我。

标签: javascript html css d3.js


【解决方案1】:

您需要做的是将第二个&lt;svg&gt;(图例之一)的height 值从100 更改为120。我对d3.js 或您的脚本知之甚少,无法在您的脚本中实现它。在生成&lt;svg&gt; 之后,我可以写一个javascript sn-p 来即时执行它,但它会是hack-ish。
我猜这个信息和你的知道你自己的脚本是什么,你可以从那个传说的源头来解决这个问题。

感谢 Gerardo Furtado,您需要执行以下操作才能使您的 legend svg 有足够的空间(高度)来正确显示标签:

在 D3 中,轴生成器始终在 SVG 的原点 (0,0) 创建。然后,它被转换到用户想要的任何位置,并在轴下方创建刻度。目前,OP 正在将其翻译为"translate(0,"+(height)+")",高度为Height -top - bottom;。因此,解决方案只是增加data.margins.bottom 的值。为了不扭曲条形,请告知需要相应地增加data.height


如果您必须将您的图例放入 100px 高度,则需要对其应用此 CSS 规则:

transform: scale(factor);
transform-origin:left; /* keep it aligned on left side */

,其中factor 低于1 以便缩小。如果您不关心按比例缩放它,则可以将比例因子限制为仅Y 轴。 (使用scaleY 而不是scale)但这会扭曲您的图例svg 中的所有内容,包括文本。

【讨论】:

  • 嗨,我已将 y 轴和堆栈条缩小到 1 以下,但我正面临失真问题。我猜唯一的解决方法是增加data.height。如果我错了,请纠正我。
  • 如果您不想要失真,只需使用scale,这样您就可以缩小两个轴,而不仅仅是Y。使用一个参数,它将相同地缩放两个轴。使用两个参数,它将缩放(sx,sy)。使用transform-origin: left; 将其向右侧缩放。
  • @GerardoFurtado 这很奇怪。从那以后,我实际上花了一些时间在这里和 SOMeta 上查看了您的一些答案,并在合适的地方投了赞成票。我祝贺你为d3.js 所做的一切。删除了链接。如果您认为这是系统性的,您可以要求对您的答案的投票模式进行审查。如果它明确针对的是回答者,而不是答案,他们通常会成功,并且他们会删除有问题的选票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多