2017-10-24 3 views
5

ファブリックJSを使用して、キャンバスにテキストオブジェクトとイメージオブジェクトを追加しています。ファブリックJS:テキストオブジェクトの選択領域が実際のテキストサイズより大きい

しかし、テキストオブジェクトを追加して選択すると、実際のテキストサイズよりも大きな選択領域が表示されます。

Please refer this link to see the screen-shot.

私たちは、テキストオブジェクトを追加するには、次のコードを使用しています。

 
var text_object = new fabric.Text('00', { 
        fontSize: 192, 
        fontFamily: 'Times New Roman', 
        padding: 0 
        }); 
text_object.top = parseInt((canvas.height - text_object.height)/2); 
text_object.left = parseInt((canvas.width - text_object.width)/2); 
text_object.lockUniScaling = true; 
canvas.add(text_object); 
canvas.renderAll(); 
canvas.setActiveObject(text_object); 

主な問題は、追加されたテキストオブジェクトの幅と高さを取得しようとするときです。テキストの実際のサイズではなく、テキストオブジェクトの選択領域の幅と高さを返します。

テキストオブジェクトの選択領域をテキストの実際のサイズと同じにするにはどうすればよいですか?

または、選択領域を除いて、実際のテキストサイズを取得するにはどうすればよいですか?

+0

あなたのコードで、あなたの問題を述べる最小限のスニペットを作成できますか? – Durga

+0

問題のコードスニペットを追加しました。だから確認してください。 –

答えて

3

あなたが望むものを達成するための直接的な方法はありません。これはテキストのベクトルパスの境界ボックスになります。

解決方法がわかりましたら、テキストを空のキャンバスにレンダリングし、getImageDataを使用してすべてのピクセルの透明度を確認し、塗りつぶされた点を見つけた最大と最小のxとyを見つけます。それは完璧ではありませんが、より良い解決策を簡単に得ることはできません。

解決策のサーバー側があると思いますが、わかりません。

理論上は、JSで独自のフォントレンダリングエンジンを作成することができますが、完璧なバウンディングボックスはありますが、シンプル/おもちゃの場合を除き、深刻なテキストレイアウトエンジンは数年実装するには、それは完全に範囲外ですね。

近似方法の助けが必要な場合は教えてください。

function getVisiblePixelsBoundingBox(canvas) { 
 
    const context = canvas.getContext("2d"); 
 
    const imageData = context.getImageData(0, 0, canvas.width, canvas.height).data; 
 
    let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; 
 
    for (let y = 0; y < canvas.height; y++) { 
 
     for (let x = 0; x < canvas.width; x++) { 
 
      const alpha = imageData[(y * canvas.width + x) * 4 + 3]; 
 
      if (alpha > 0) { 
 
       minX = Math.min(minX, x); 
 
       minY = Math.min(minY, y); 
 
       maxX = Math.max(maxX, x); 
 
       maxY = Math.max(maxY, y); 
 
      } 
 
     } 
 
    } 
 
    return { 
 
     left: minX, 
 
     top: minY, 
 
     width: maxX - minX, 
 
     height: maxY - minY 
 
    }; 
 
} 
 

 
// you will need to create a new canvas 
 
var canvas = document.createElement("canvas"), 
 
    context = canvas.getContext("2d"); 
 

 
// and set the width and height the same as the canvas you want to draw the text 
 
// here I'm just adding some values for the example: 
 
canvas.width = 600; 
 
canvas.height = 400; 
 

 
// now I'm going to draw some text on it 
 
context.font = "120px serif"; 
 
context.fillText("Lipsum", 100, 200); 
 

 
let boundingBox = getVisiblePixelsBoundingBox(canvas); 
 

 
// now this is not needed in your case, but want to see the canvas and 
 
// I will draw a rectangle around the bounding box to see how it works: 
 
document.body.appendChild(canvas); 
 
context.strokeStyle = "red"; 
 
context.strokeRect(boundingBox.left, boundingBox.top, boundingBox.width, boundingBox.height);

オクラホマので、これは良いようだが、問題の用心:編集は例を提供するために、

精度を

  • はに制限されていますピクセルなので、バウンディングボックスを描画するのはまったく問題ありませんが、操作にはあまり適していません。形状を完全に整列させるなど、はるかに高い精度が要求されます。また、測定方法のために、形状の一部が全く見えないほど薄い場合は、測定されません(おそらく大きな問題ではありません。非常に薄い形状がフォント)。

  • 結果を得るためにすべてのピクセルを繰り返しているため、実行が遅くなることがあります(JSはそれほど高速ではありません)。これを知っていると、キャンバスのサイズを小さくしようとすると、ターゲットキャンバスのキャンバスと同じキャンバスを使用しないように誘惑されるかもしれませんが、次の点に関連する新たな問題が導入されるため、

  • テキストをキャンバスの外に出すことで測定すると、境界ボックスは表示領域に制限されます(境界線に固執します)。実際の幅と高さが得られればキャンバスのサイズを大きくすることが考えられますが、フォントサイズとテキストの量を制限しないと、ブラウザが遅くなるキャンバスで終わるかもしれません。それでもクラッシュしてしまうので...境界ボックスが境界線に固執していることを受け入れるだけです。 measureTextで提供されている幅を使用すると役立つかもしれないと思うかもしれませんが、残念ながら、完全な画像をスキャンするために必要なトップと高さを得ることはできません。

+1

TextMetricsの標準は更新されているようですが、ブラウザはそれをまだサポートしていません。 https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics –

+0

Romanに感謝します。近似法の例を参考にしてください。だから我々はそれを確認し、それが私たちのために働くならそれを使用するでしょう。 –

+0

例が提供されています、 –

関連する問題