SVG元素的水平有序装箱

ham*_*son 18 javascript svg bin-packing d3.js

试图找出最好的方法,将装箱后的已知宽度的svg图像打包/分布在水平行中,如果容器的宽度太紧,可以将它们堆叠在一起。

容器的高度应最佳地自动调整,并且重力应为垂直中心点。创建了一些图像来说明所需的解决方案。

有没有解决这个问题的JS库,也许是d3?感觉上像是一个装箱问题,但也许在顺序和重力方面增加了一些复杂性。对画布解决方案不感兴趣。

如果容器足够宽

太紧,堆叠一些元素

更紧密地堆叠所有

Ger*_*ado 9

对于基于D3的纯SVG解决方案,我的建议是使用带有碰撞检测的力仿真。D3力模拟(d3.forceCollide)中的碰撞检测是圆形的,即以元素的半径为参数。因此,由于您具有正方形/矩形元素,因此我使用了发现的这种矩形碰撞检测。

这个想法是根据数据和可用宽度使用模拟来设置xy位置,并根据元素的大小进行碰撞。然后,在调整大小事件中,以新的宽度再次运行模拟。

请记住,与您会发现的大多数D3力导向图相反,我们不想显示整个仿真过程,而只显示最终位置。因此,您将设置仿真并立即停止仿真:

const simulation = d3.forceSimulation(data)
  //etc...
  .stop();
Run Code Online (Sandbox Code Playgroud)

然后,您执行以下操作:

simulation.tick(n);
Run Code Online (Sandbox Code Playgroud)

或者,在调整大小处理程序中,将其重新加热:

simulation.alpha(1).tick(n);
Run Code Online (Sandbox Code Playgroud)

n您想要的迭代次数在哪里。越多越好,但越慢...

这是一个非常粗糙的示例,移动右侧的蓝色手柄以挤压矩形:

const simulation = d3.forceSimulation(data)
  //etc...
  .stop();
Run Code Online (Sandbox Code Playgroud)
simulation.tick(n);
Run Code Online (Sandbox Code Playgroud)
simulation.alpha(1).tick(n);
Run Code Online (Sandbox Code Playgroud)

正如我所说,这是一个非常粗糙的代码,仅作为示例。您可以调整强度并改进其他零件,以满足您的需求。

  • @Gerardo Furtado谢谢您的回答。稍加调整,我认为有可能实现我一直在寻找的东西……三年前我问这个问题时! (2认同)

Bon*_*123 7

您尝试实现的是砌体布局。通常在不知道元素的高度和数量时使用。真实的砖石布局即使使用可变宽度的元素也可以使用。

这是一个JSFIDDLE示例(调整大小以查看元素如何打包)。

很多代码都需要一些JS,仍然不会是真正的砖石,为每列将具有相同的宽度(在这里或点击这里)。尽管您实际上可以通过使用多列布局以及媒体查询在纯CSS(无js)中实现此结果。但是,因为这仅在所有元素都具有相同的宽度时才适用,而且似乎不是您的情况,所以我建议您从下面的列表中选择一个:

水平砌体(您正在寻找的那个) 垂直砌体

我可能已经忘记了一些,如果是的话,请在评论部分提出建议,如果确实是一个砖石结构(支持可变宽度),根据OP的要求,我会将其添加到列表中。