2013-03-26 12 views
5

私が問題とするのは、キャンバス要素の中心に垂直に配置されたテキストをユーザーが保持することです。私はこの問題を解決するためのテスト環境を構築しました。この問題は、この記事ではフィドルと一緒に提供しました。ここに私のコードは次のとおりです。キャンバス上にテキストを縦に中央に置く

HTML:

Enter Your Text: <br/> 
<textarea id="inputtextuser" onkeyup="inputtextgo()" name="Text">Enter Your</textarea> <br/> 
TextBaseline: 
<select id="inputtextbaseline" onchange="inputtextgo()";> 
    <option value="alphabetic">alphabetic</option> 
    <option value="top">top</option> 
    <option value="bottom">bottom</option> 
    <option value="middle">middle</option> 
    <option value="hanging">hanging</option> 
</select> <br/> 
<canvas id="canvas1" width="300px" height="200px" >Your browser does not support the HTML5 canvas tag.</canvas> <br/> 
<div id ="textheightentered"></div> 

CSS:

canvas { 
    border: solid 1px black; 
} 

のJavaScript/jQueryの:

//Declaring the Canvas 
var canvas1 = document.getElementById('canvas1'); 
context1 = canvas1.getContext('2d'); 

//running the function to update the canvas 
inputtextgo(); 

function inputtextgo() { 
    //Retrieving the text entered by the user 
    var inputtext = document.getElementById("inputtextuser").value; 
    //Calling the function to calculate the height on the text entered by the user 
    var textheight = fontheight(inputtext); 
    //retrieving the baseline selected by the user 
    var baseline = document.getElementById("inputtextbaseline").value; 
    //calculating the new y needed to center the text based on the height of the text 
    var y = 100 + textheight/2; 

    //Updating the canvas for the new text entered by the user 
    context1.clearRect(0, 0, 300, 200); 
    context1.font = "36px arial"; 
    context1.textBaseline = baseline; 
    context1.fillText (inputtext, 0, y); 

    //Drawing a line across the middle of the canvas for reference 
    context1.strokeStyle="red"; 
    context1.moveTo(5,100); 
    context1.lineTo(290,100); 
    context1.stroke(); 
    $("#textheightentered").text("Text Height: " + textheight); 
} 

function fontheight(text){ 

    var canvas=document.createElement("canvas"); 
    canvas.width = 1000; 
    canvas.height = 200; 
    var ctx=canvas.getContext("2d"); 

    function measureTextHeight(left, top, width, height,text) { 

     // Draw the text in the specified area 
     ctx.save(); 
     ctx.clearRect(0,0, canvas.width, canvas.height); 
     ctx.baseline = "top"; 
     ctx.fillText(text, 0, 35); // This seems like tall text... Doesn't it? 
     ctx.restore(); 

     // Get the pixel data from the canvas 
     var data = ctx.getImageData(left, top, width, height).data, 
      first = false, 
      last = false, 
      r = height, 
      c = 0; 

     // Find the last line with a non-white pixel 
     while(!last && r) { 
      r--; 
      for(c = 0; c < width; c++) { 
       if(data[r * width * 4 + c * 4 + 3]) { 
        last = r; 
        break; 
       } 
      } 
     } 

     // Find the first line with a non-white pixel 
     while(r) { 
      r--; 
      for(c = 0; c < width; c++) { 
       if(data[r * width * 4 + c * 4 + 3]) { 
        first = r; 
        break; 
       } 
      } 

      // If we've got it then return the height 
      if(first != r) return last - first; 
     } 

     // We screwed something up... What do you expect from free code? 
     return 0; 
    } 
    ctx.font= "36px arial"; 
    var height = measureTextHeight(0, 0, canvas.width, canvas.height,text); 
    //return the height of the string 
    return height; 
} // end $(function(){}); 

JSFiddle:私が午前http://jsfiddle.net/grapien/R6DWN/3/

問題は例えば、ユーザが小文字の "y"を入力すると、テキストの高さが変化し、テキストがキャンバスの中央に残らないことを意味する。これは、y変数で実行されたベースライン補正が、入力されたテキスト(大文字と小文字の組み合わせ)によって異なる必要があるためです。ベースラインの下のテキストがy変数で実行された補正を歪めているためです。

キャンバス要素内にテキストを常に中央に配置したいので、ここで問題が発生しています。私が考えることができる唯一のことは、テキスト・ベースラインの基準点の下の空白でないピクセルを計算することです。次に、ベースラインからの差をテキストの両端に使用して、テキストをキャンバス上に中央に配置します。私はあなたがこのスクリプトの書き方にどう接しているのか、それが可能なのかどうかはわかりません。しかし、それが私が思いついた最善のアプローチです。

誰もが思考や指導を持っていれば、この問題を解決する方法を開発することで私は困惑してしまいます。

+0

私のポストマットを編集してくれてありがとう、私は私のレビューでカップルのものを逃したように見えます。 – grapien

答えて

0

私は質問に記載した手法を使ってこの問題を解決したと思います。私は、入力されたテキストのベースラインの下に広がるフォントの量を計算する新しい関数を作成しました。高さを計算するために使用されたものと同様の技術を使用します。アルファベットのベースラインを使用して、このベースラインを超えるコンテンツを含むピクセルを計算します。以下の関数を参照してください。これは、テキストのベースラインの下にあるテキストの部分を調整するために、Yをオフセット

var textheight = fontheight(inputtext); //Calculate Text Height 
var textheight2 = fontheight2(inputtext); //Calculate portion above the baseline 
var difference = textheight - textheight2; // Calculate the portion below the baseline 
var y = 100 - difference + textheight/2; // Adjust the y cordinate 

function fontheight2(text){ 

    var canvas=document.createElement("canvas"); 
    canvas.width = 1000; 
    canvas.height = 200; 
    var ctx=canvas.getContext("2d"); 

    function measureTextHeight(left, top, width, height,text) { 

     // Draw the text in the specified area 
     ctx.save(); 
     ctx.clearRect(0,0, canvas.width, canvas.height); 
     ctx.fillText(text, 0, 100); // This seems like tall text... Doesn't it? 
     ctx.restore(); 

     // Get the pixel data from the canvas 
     var data = ctx.getImageData(left, top, width, height).data, 
      first = false, 
      last = false, 
      r = 100, 
      c = 0; 

     // Find the first line with a non-white pixel 
     while(r) { 
      r--; 
      for(c = 0; c < width; c++) { 
       if(data[r * width * 4 + c * 4 + 3]) { 
        first = r; 
        break; 
       } 
      } 

      // If we've got it then return the height 
      if(first != r) return 99 - first; 
     } 

     // We screwed something up... What do you expect from free code? 
     return 0; 
    } 
    ctx.baseline = "Alphabetic"; 
    ctx.font= "36px arial"; 
    var height = measureTextHeight(0, 0, canvas.width, canvas.height,text); 
    //return the height of the string 
    return height; 
} // end $(function(){}); 

、そこから私は単に中心にテキストをオフセットするために、Yに次の調整を使用します。私はここでJSFiddleを更新しましたhttp://jsfiddle.net/grapien/R6DWN/6/

0

このlinkをご覧になれます。テキストラッパーが使用されます。

+0

私は実際に自分のウェブページ上でそのコードを使用していますが、すべての変数がユーザによって事前に設定されているため(つまり、ラインハイトとy)、ダイナミックではなく、オンザフライで計算されません。問題を解決する必要がないので、コードの複数の行部分を削除しました。本当の問題は、ユーザーが入力したテキストに基づいたテキストベースラインがなく、使用されているフォントライブラリであることです。これにより、ユーザーが入力した内容に基づいて異なるオフセットが発生します。より大きな問題は、このオフセットを動的に計算する方法です。 – grapien

+0

ええ、私はあなたにフィドルのコードをテストしていました。テキストのベースラインは25〜32ぐらいです。非常に単純な回避策として、私は、ユーザーのテキストの代わりに "Yy"の行の高さを取るでしょう。そうすれば、変化しないベースラインが得られます。 –

+0

私はコードをどのように動的にテストするのか把握することができましたが、私の答えは以下のとおりです。それは文字列を受け取り、その差を計算することによって基線の下にある文字列の部分を計算します。テキストの配置を調整するためにy変数のこの違いを考慮することができます。 – grapien

関連する問題