私が抱えている問題は、ユーザーが入力したテキストをキャンバス要素内の垂直方向の中央に配置したままにすることです。私はこの問題を解決するためのテスト環境を構築しました。これは、この投稿でフィドルと一緒に提供しました。これが私のコードです:
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変数で実行されるベースライン修正が入力されたテキスト(小文字と大文字の組み合わせ)によって異なる必要があるためです。
これは、テキストを常にキャンバス要素内の中央に配置したいので、問題が発生している場所です。私が考えることができる唯一のことは、テキストベースラインの参照点の下の上の空白でないピクセルを計算することです。次に、ベースラインからテキストの端までの差を使用して、テキストをオフセットしてキャンバスの中央に配置します。このスクリプトの作成方法や、それが可能かどうかはわかりません。しかし、それは私が思いついた最良のアプローチです。
誰かが何か考えやガイダンスを持っているなら、この問題を解決するためのアプローチを開発することは私を困惑させたので、それは大いにありがたいです。