我试图绘制具有不同宽度的特定数量的矩形,彼此相邻。当任何矩形达到我的svg元素的最大宽度(例如500)时,它应该在下一行继续。是否有可能以一种简单的方式解决这个问题?
Output - Image 这就是我到目前为止所得到的。问题是,萤火虫表明,我的最后一个宽度(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>
编辑 - 新图片 - Continue new Line
答案 0 :(得分: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>
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>