рисование определенного количества прямоугольников (d3.js )

#javascript #d3.js

#javascript #d3.js

Вопрос:

Я пытаюсь нарисовать определенное количество прямоугольников разной ширины рядом друг с другом. Когда какой-либо прямоугольник достигает максимальной ширины моего элемента svg (например, 500), он должен продолжаться в следующей строке. Можно ли решить это простым способом?

Вывод — изображение Это то, что я получил до сих пор. Проблема в том, что firebug показывает, что моя последняя ширина (570) слишком велика для моего svg.

 <script>
var width = 500;
var height = 500;
var rectHeight = 20;
var xPos = 0;
var xWidthOld = 0;
var rectSpace = 0.5;
var dataArray = [20, 78, 40, 60, 570];

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

rects = d3.select("svg").selectAll("rect")
.data(dataArray)
.enter()
.append("rect")
.attr("width", function(d) { return d; })
.attr("height", rectHeight)
.attr("x", function(d, i) {
return getPos(d, i);
});


function getPos(rectWidth, index) {
if(index != 0)
xPos = xPos   xWidthOld   rectSpace;

xWidthOld = rectWidth;
return xPos;
}
</script>
  

РЕДАКТИРОВАТЬ — Новое изображение — Продолжить новую строку

Комментарии:

1. У вас есть пример, близкий к тому, что вы хотите? Обязательно ли использовать SVG?

2. В конце это должно работать как интерактивная древовидная карта, но все прямоугольники должны иметь одинаковую высоту, только ширина должна быть разной. Нет, мне не нужно, но я подумал, что это полезно использовать.

3. Он уже существует в D3, почему вы хотите сделать это самостоятельно? bl.ocks.org/mbostock/4063582

4. Можно ли с его помощью нарисовать ту же визуализацию, которую вы видите на моем рисунке (Edit-1)?

5. Покажите нам свой код

Ответ №1:

Я использовал два разных алгоритма. Первый — вычисление положения каждого узла в цикле D3, второй — предварительное вычисление позиций с помощью initData функции.

Вот что у меня есть:

Когда он переполняется, он переходит на строку

 var width = 500;
var height = 500;
var rectHeight = 20;
var posX = 0;
var posY = 0;
var rectSpace = 0.5;
var dataArray = [20, 78, 40, 60, 370, 42];

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

rects = d3.select("svg").selectAll("rect")
  .data(dataArray)
  .enter()
  .append("rect")
  .attr("width", function(d) {
    return d;
  })
  .attr("height", rectHeight)
  .attr("x", function(d, i) {
    return getPosX(d, i);
  })
  .attr("y", function(d, i) {
    return getPosY(d, i);
  });

// Calculate PosX
function getPosX(rectWidth, index) {
  // If rect goes out of the SVG, restart at posX = 0
  if (posX   rectWidth > width) {
    posX = 0;
  }
  newPosX = posX; // Return this position
  posX  = rectWidth   1; // prepare position for next node
  return newPosX;
}

// Calculate PosY
function getPosY(rectWidth, index) {
  // reset posX at first calculation of posY
  if (index == 0) {
    posX = 0;
  }
  // If rect goes out of the SVG increment Y position of rect
  if (posX   rectWidth > width) {
    posY  = rectHeight   1;
    posX = 0;
  }
  posX  = rectWidth   1; // Calculate position for next node
  return posY;
}  
 svg {
  border: 1px solid gray;
}  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>  

JSFiddle

При переполнении узел обрезается, а остальная часть добавляется в новую строку

 var width = 500;
var height = 500;
var rectHeight = 20;
var rectSpace = 0.5;
var dataArray = [20, 78, 40, 60, 1370, 42];
var nodes = [];

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

rects = d3.select("svg").selectAll("rect")
  .data(initData(dataArray))
  .enter()
  .append("rect")
  .attr("width", function(d) {
    return d.value;
  })
  .attr("height", rectHeight)
  .attr("x", function(d, i) {
    return d.x;
  })
  .attr("y", function(d, i) {
    return d.y;
  });

// Build displayed data below
function initData(data) {
  var posX = 0;
  var posY = 0;

  // Claculate position of each node
  for (var i in data) {
    var node = addNode(data[i], posX, posY);

    // If there is an overflow
    if (node.x   node.value > width) {
      var overflowValue = node.x   node.value - width;

      // Add nodes until there is no more overflow
      while (overflowValue > 0) {
        // Update current node value
        node.value = width - node.x;
        // Calculate new node posX and posY
        posX = 0;
        posY  = rectHeight   1;
        node = addNode(overflowValue, posX, posY);
        // Claculate new overflow
        overflowValue = node.x   node.value - width;
      }
    }
    posX  = node.value   1;
  }

  return nodes;
}

function addNode(value, x, y) {
  var newNode = {
    value: value,
    x: x,
    y: y
  };

  nodes.push(newNode);

  return newNode;
}  
 svg {
  border: 1px solid gray;
}  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>  

JSFiddle