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変数で実行されるベースライン修正が入力されたテキスト(小文字と大文字の組み合わせ)によって異なる必要があるためです。

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

誰かが何か考えやガイダンスを持っているなら、この問題を解決するためのアプローチを開発することは私を困惑させたので、それは大いにありがたいです。

4

1 に答える 1

1

私は質問で述べたテクニックを使ってこの質問を解決したと思います。入力したテキストのベースラインより下に伸びるフォントの量を計算する新しい関数を作成しました。高さの計算に使用されたものと同様の手法を使用します。アルファベットのベースラインを使用して、このベースラインより上のコンテンツを含むピクセルを計算します。以下の関数を参照してください。

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の調整を使用して、テキストを中央にオフセットします。

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

これにより、yがオフセットされ、テキストのベースラインより下にあるテキストの部分が調整されます。ここでJSFiddleを更新しましたhttp://jsfiddle.net/grapien/R6DWN/6/

于 2013-03-26T23:33:17.213 に答える