根据数据

时间:2018-05-02 13:55:35

标签: d3.js svg

我正在尝试创建SVG视图,其中,我需要根据矩形中数据的升序将矩形放在一行中。

矩形应根据值的差异放置在距左侧适当的距离处。

这是我到现在为止所得到的。但是,如果我使用线性刻度,我的矩形是重叠的。有没有办法可以避免这些矩形的重叠?

更新:
我们决定在同一级别上显示重叠的矩形和不重叠的矩形。但现在的问题是如何进行平移并通过更新y轴将矩形放在另一个下面。现在需要预先确定重叠,并且需要确定x和y坐标以进行转换。问题是复杂的,因为矩形大小可能会根据其中的文本大小而变化。

任何建议都将不胜感激。



<html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v3.min.js"></script>
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
  </style>
 
</head>

<body>
    <script>
    var data = [{
      x: 20,
      y: 10,
      baseFare: 50,
      class : "L" 
    },
	{
      x: 100,
      y: 10,
      baseFare: 100,
      class : "K"
    }, {
      x: 200,
      y : 10,
      baseFare : 230,
      class : "R"
    },
	{
      x: 500,
      y : 10,
      baseFare : 1000,
      class : "R"
    },
	{
      x: 500,
      y : 10,
      baseFare : 400,
      class : "M"
    },
	{
      x: 500,
      y : 10,
      baseFare : 300,
      class : "N"
    },
		{
      x: 500,
      y : 10,
      baseFare : 380,
      class : "Q"
    }
               ];
			   
 data = data.sort(function (a, b) {
            return d3.ascending(a.baseFare, b.baseFare);
        })

	var width = 2000;
	var height = 500;
		
    var svg = d3.select("body")
      .append("svg")
      .attr("width", width)
      .attr("height", height);
	  
    var xExtent = d3.extent(data, function(d) { return d.baseFare; });
	var xRange = xExtent[1] - xExtent[0];
	  
	 var linearScale = d3.scale.linear()
            .range([0, 500])
            .domain([d3.min(data, function (d) {
                return d.baseFare;
            }), d3.max(data, function (d) {
                return d.baseFare;
            })]);
				
	var y = 10;
	
	for (var i = 0; i < data.length; i++) {
      data[i].x = linearScale(data[i].baseFare);
  }

    var g = svg.selectAll('.someClass')
      .data(data)
      .enter()
      .append("g")
      .attr("class","someClass")
      .attr("transform", function(d) {
          return "translate(" + d.x + "," + d.y + ")";
      });

    g.append("rect")
      .attr("width", 40)
      .attr("height", 40)
      .attr("rx", 10)
      .attr("ry", 10)
	  .attr("stroke", "black")
	  .attr("stroke-opacity", 0.8)
      .style("fill", "lightblue");
      
      g.append("text")
      .style("fill", "black")
	  .attr("x", 15)
      .attr("y", 10)
      .style("alignment-baseline", "middle")
      .text(function(d) {
        return d.class;
      })

    g.append("text")
      .style("fill", "black")
	  .attr("x", 5)
      .attr("y", 30)
      .style("alignment-baseline", "middle")
      .text(function(d) {
        return "$" + d.baseFare;
      })
  </script>
  </body>
  </html>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

确定要应用于给定矩形的x平移时,可以检查此x平移是否会使此新矩形与前一个矩形重叠。如果是这种情况,则应用前一个矩形的平移加上矩形的宽度。

您可以替换:

for (var i = 0; i < data.length; i++) {
  data[i].x = linearScale(data[i].baseFare);
}

使用:

for (var i = 0; i < data.length; i++) {
  data[i].x = linearScale(data[i].baseFare);
  if (i > 0 && data[i - 1].x + 40 > data[i].x)
    data[i].x = data[i - 1].x + 41;
}

<html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v3.min.js"></script>
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
  </style>
 
</head>

<body>
<script>

var data = [
  {
    x: 20,
    y: 10,
    baseFare: 50,
    class : "L" 
  },
  {
    x: 100,
    y: 10,
    baseFare: 100,
    class : "K"
  },
  {
    x: 200,
    y: 10,
    baseFare : 230,
    class : "R"
  },
  {
    x: 500,
    y: 10,
    baseFare : 1000,
    class : "R"
  },
  {
    x: 500,
    y: 10,
    baseFare : 400,
    class : "M"
  },
  {
    x: 500,
    y: 10,
    baseFare : 300,
    class : "N"
  },
	{
    x: 500,
    y: 10,
    baseFare : 380,
    class : "Q"
  }
];

data = data.sort(function (a, b) {
  return d3.ascending(a.baseFare, b.baseFare);
})

var svg = d3.select("body").append("svg").attr("width", 2000).attr("height", 500);

var xExtent = d3.extent(data, function(d) { return d.baseFare; });
var xRange = xExtent[1] - xExtent[0];

var linearScale = d3.scale.linear()
  .range([0, 500])
  .domain([
    d3.min(data, function (d) { return d.baseFare; }),
    d3.max(data, function (d) { return d.baseFare; })
  ]);
			
var y = 10;

for (var i = 0; i < data.length; i++) {
  data[i].x = linearScale(data[i].baseFare);
  if (i > 0 && data[i - 1].x + 40 > data[i].x)
    data[i].x = data[i - 1].x + 41;
}

var g = svg.selectAll('.someClass')
  .data(data)
  .enter()
  .append("g")
  .attr("class","someClass")
  .attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")";
  });

g.append("rect")
  .attr("width", 40)
  .attr("height", 40)
  .attr("rx", 10)
  .attr("ry", 10)
  .attr("stroke", "black")
  .attr("stroke-opacity", 0.8)
  .style("fill", "lightblue");
  
  g.append("text")
  .style("fill", "black")
  .attr("x", 15)
  .attr("y", 10)
  .style("alignment-baseline", "middle")
  .text(function(d) { return d.class; })

g.append("text")
  .style("fill", "black")
  .attr("x", 5)
  .attr("y", 30)
  .style("alignment-baseline", "middle")
  .text(function(d) { return "$" + d.baseFare; })

</script>
</body>
</html>