私はRaphael.jsを使用して、画像上にポリゴン(または実際には閉じたパス)を作成しています。ポリゴンの中にテキストを入れたいです。テキスト要素を作成し、そのサイズと位置を調整して、全体がポリゴンの境界内に収まるようにする方法はありますか?
手動で調整できる適切な推測を与えることができるアルゴリズムは少なくともありますか?
さて、私はこれを1日を通して考え、ついに小さなデモコードをまとめる機会を得ました。それは多くの点で明らかに不完全ですが、良い出発点を形成する可能性があり、ランダムに生成されたポリゴンのほとんどでうまく機能するようです。
パート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:反復サイジング。基本的に、上記で生成された座標を使用して、生成されたラベルテキストに適用します。特定のしきい値を下回るまで、反復ごとに1回スケールを減らします。その時点で、MYコードは単純に諦めます(おそらく諦めるべきではありません)。
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" );
そして、結果は、私が投げた純粋にランダムなポリゴンのほとんどによく似ています。必要以上に計算量が多いと思います。私のコードはここでステージングされます-ポリゴンをクリックするだけで新しいポリゴンが生成されます。
ハッピーコーディング。