Масштабирование положения прямоугольника SVG на основе данных - PullRequest
0 голосов
/ 02 мая 2018

Я пытаюсь создать представление 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>

1 Ответ

0 голосов
/ 02 мая 2018

При определении 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...