保持文本垂直居中在画布上 [英] Keep Text Vertically Centered on Canvas

查看:202
本文介绍了保持文本垂直居中在画布上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The issue that I am having is keeping the text entered by a user vertically centered within the canvas element. I have built a test environment to try and solve this issue, which I have provided in this post along with a fiddle. Here is my code:

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:

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/

JSFiddle: http://jsfiddle.net/grapien/R6DWN/3/

我遇到的问题是,如果用户输入小写字母y,例如文本高度更改,并且文本不保留在画布的中心。这是由于在y变量中执行的基线校正将需要根据输入的文本(小写和大写字符的组合)而不同,因为基线下面的文本正在倾斜在y变量中执行的校正。

The issue I am having is that if the user enters a lower case "y" for example the text height changes and the text does not remain in the center of the canvas. This due to the fact that the baseline correction performed in the y variable would need to differ depending on the text entered (combination of lower and uppercase characters) as the text below the baseline is skewing the correction performed in the y variable.

这是我遇到我的问题,因为我想保持文本在画布元素内始终居中。我唯一能想到的是计算在textbaseline参考点下面的非空白像素。然后使用从基线到文本末端的差异来将文本偏移到画布上的中心位置。我不知道你如何写这个脚本或如果它甚至可能。但这是我提出的最好的方法。

This is where I am having my problems as I would like to keep the text centered at all times within the canvas element. The only thing I can think of is to calculate the non-blank pixels above an below the textbaseline reference point. Then use the difference from the baseline to the ends of the text to offset the text to center it on the canvas. I am not sure how you approach writing this script or if it is even possible. But that is the best approach I have came up with.

如果任何人有任何想法或指导,将非常感谢,因为开发一种方法来解决这个问题,我得到了解决。

If anyone has any thoughts or guidance it would be greatly appreciated as developing an approach to solve this issue has got me stumped.

推荐答案

我相信我已经使用我在问题中说的技术解决了这个问题。我创建了一个新函数来计算在输入的文本的基线之下延伸的字体的数量。使用与用于计算高度的类似的技术。我使用字母基线,然后计算包含高于此基线的内容的像素。请参阅下面的功能。

I believe I have solved this question using the technique I stated in the question. I created a new function that calculates the amount of the font that extends below the baseline of the text entered. Using a similar technique as to what was used to calculate the height. I use the alphabetic baseline then calculate the pixels that contain content above this baseline. See the function below.

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将文本偏移到中心:

From there I simply use the following adjustment to the y to offset the text to center:

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/

This offsets the y to adjust for the portion of the text that is below the text baseline. I have updated the JSFiddle here http://jsfiddle.net/grapien/R6DWN/6/.

这篇关于保持文本垂直居中在画布上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆