将文本保持垂直居中在画布上

时间:2013-03-26 22:05:13

标签: javascript jquery html5 canvas html5-canvas

我遇到的问题是保持用户输入的文本在canvas元素中垂直居中。我已经构建了一个测试环境来尝试解决这个问题,我在这篇文章中提供了一个小提琴。这是我的代码:

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变量中执行的校正。

这就是我遇到问题的地方,因为我希望在canvas元素中始终保持文本居中。我唯一能想到的是计算textbaseline参考点下方的非空白像素。然后使用从基线到文本末尾的差异来偏移文本以使其在画布上居中。我不确定你是如何编写这个脚本的,或者甚至可能。但这是我提出的最佳方法。

如果有人有任何想法或指导,我们将不胜感激,因为开发解决这个问题的方法让我感到难过。

2 个答案:

答案 0 :(得分: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/

答案 1 :(得分:0)

您可以查看此link。使用文本包装器。