好的,我在一天的过程中对此进行了一些思考,终于有机会将一些演示代码放在一起。它在很多方面都明显不完美,但可能是一个很好的起点,并且似乎与我的大多数随机生成的多边形一起工作得很好。
第 1 部分:在多边形上居中文本。使用边界框被证明非常不令人满意,所以我没有设计一种技术来平均给定路径中的所有点container
:
// Determine the *weighted* center of this figure
var segments = Raphael.parsePathString( container.attr( 'path' ) );
var count = 0, sum_x = 0, sum_y = 0;
for ( var i = 0; i < segments.length; i++ )
{
if ( segments[i][0] == 'L' || segments[i][0] == 'M' )
{
count++;
sum_x += segments[i][1];
sum_y += segments[i][2];
}
}
var cx = sum_x / count, cy = sum_y / count;
第 2 部分:碰撞检测。我需要一种机制来检查给定对象是否在当前形状内。由于懒惰,我只是在创建画布之前扩展了 Raphael 元素对象。
Raphael.el.isObjectInside = function( obj )
{
var box = obj.getBBox();
return this.isPointInside( box.x, box.y )
&&
this.isPointInside( box.x2, box.y )
&&
this.isPointInside( box.x, box.y2 )
&&
this.isPointInside( box.x2, box.y2 );
}
第 3 部分:迭代调整大小。基本上,我们使用上面生成的坐标并将它们应用于生成的标签文本。我们每次迭代都会减少一次规模,直到我们低于某个阈值,此时我的代码会简单地放弃(你的代码可能不应该):
var s = 1.0;
if ( ibox.width >= cbox.width * 0.7 )
{
s = ( cbox.width * 0.7 ) / ibox.width;
}
while ( s > 0.1 )
{
insert.attr( { transform: [ "S", s, s, ibox.x + ibox.width / 2, ibox.y + ibox.height / 2, "T",
if ( container.isObjectInside( insert ) )
return;
s *= 0.65;
}
console.log("Warning: NOT a clean fit" );
对于我扔给它的大多数纯随机多边形,结果看起来都很好。我确信它的计算量远远超过它需要的量。我的代码在这里上演——只需单击多边形即可生成一个新的。
快乐编码。